-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add type descriptors for data constructors in Java, when necessary #301
Conversation
…awslabs/polymorph into robin-aws/add-type-descriptors-for-java
a116040
to
0a24bc8
Compare
|
||
class WrappersInterop { | ||
|
||
static function method CreateStringSome(s: string): Option<string> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generics? CreateSome<T>(t: T): Option<T>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately no, but I beefed up the module comment to explain why better.
"ensures res.Success? ==> ", | ||
"&& fresh(res.value)", | ||
"&& fresh(res.value.%s)".formatted(nameResolver.mutableStateFunctionName()), | ||
"&& fresh(res.value.%s)".formatted(nameResolver.callHistoryFieldName()), | ||
"&& res.value.%s()".formatted(nameResolver.validStateInvariantName()) | ||
).lineSeparated(); | ||
|
||
final TokenTree createSuccessOfClient = TokenTree |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little confused about where this is getting emitted.
On the one hand, I see additions in the "StandardLibrary" but I also see this getting written here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similarly added more comments to explain better.
…awslabs/polymorph into robin-aws/add-type-descriptors-for-java
Potentially radically different from when I blocked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Java docs on new public methods is the only blocking comment.
.github/workflows/pull.yml
Outdated
4.1.0, | ||
4.3.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: I am still learning how to best utilize GHA/Ws,
and it seems that GitHub is evolving them as well.
And our test models need to be refactored to an integration test project...
.github/workflows/pull.yml
Outdated
dafny-version: [ | ||
4.1.0, | ||
4.3.0 | ||
] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Is there no way to declare this once and reference it elsewhere in this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely possible but not nearly as simple as you'd think :) I made the change as I already had to do something similar for Dafny (where we needed a lot more dynamic calculation)
...mithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyApiCodegen.java
Show resolved
Hide resolved
...n/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java
Show resolved
Hide resolved
...n/smithy-dafny-codegen/src/main/java/software/amazon/polymorph/smithydafny/DafnyVersion.java
Show resolved
Hide resolved
...dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Constants.java
Show resolved
Hide resolved
...thy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java
Show resolved
Hide resolved
public CodeBlock createNone(CodeBlock typeDescriptor) { | ||
if (datatypeConstructorsNeedTypeDescriptors()) { | ||
return CodeBlock.of( | ||
"$T.create_None($L)", | ||
ClassName.get("Wrappers_Compile", "Option"), | ||
typeDescriptor); | ||
} else { | ||
return CodeBlock.of( | ||
"$T.create_None()", | ||
ClassName.get("Wrappers_Compile", "Option")); | ||
} | ||
} | ||
|
||
public CodeBlock createSome(CodeBlock typeDescriptor, CodeBlock value) { | ||
if (datatypeConstructorsNeedTypeDescriptors()) { | ||
return CodeBlock.of( | ||
"$T.create_Some($L, $L)", | ||
Constants.DAFNY_OPTION_CLASS_NAME, | ||
typeDescriptor, | ||
value); | ||
} else { | ||
return CodeBlock.of( | ||
"$T.create_Some($L)", | ||
Constants.DAFNY_OPTION_CLASS_NAME, | ||
value); | ||
} | ||
} | ||
|
||
public CodeBlock createSuccess(CodeBlock valueTypeDescriptor, CodeBlock value) { | ||
if (datatypeConstructorsNeedTypeDescriptors()) { | ||
return CodeBlock.of( | ||
"$T.create_Success($L, Error._typeDescriptor(), $L)", | ||
Constants.DAFNY_RESULT_CLASS_NAME, | ||
valueTypeDescriptor, | ||
value); | ||
} else { | ||
return CodeBlock.of( | ||
"$T.create_Success($L)", | ||
Constants.DAFNY_RESULT_CLASS_NAME, | ||
value); | ||
} | ||
} | ||
|
||
public CodeBlock createFailure(CodeBlock typeDescriptor, CodeBlock error) { | ||
if (datatypeConstructorsNeedTypeDescriptors()) { | ||
return CodeBlock.of( | ||
"$T.create_Failure($L, Error._typeDescriptor(), $L)", | ||
Constants.DAFNY_RESULT_CLASS_NAME, | ||
typeDescriptor, | ||
error); | ||
} else { | ||
return CodeBlock.of( | ||
"$T.create_Failure($L)", | ||
Constants.DAFNY_RESULT_CLASS_NAME, | ||
error); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blocking: Add Java docs.
Smithy-Dafny is a wildly confusing project with many hands contributing functionality.
We MUST describe what our methods do.
I checked, its true, all of these method names are unique.
But they are barely unique.
We need to java docs so future us know when to invoke this these methods.
...thy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java
Show resolved
Hide resolved
...thy-dafny-codegen/src/main/java/software/amazon/polymorph/smithyjava/nameresolver/Dafny.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Tony Knapp <[email protected]>
This is necessary for Dafny 4.3 and higher, as Dafny no longer adds this method on reference types. The explicit construction of the right kind of TypeDescriptor (which works both before and after 4.3) was already implemented for other shapes in typeDescriptor(ShapeId), so I just tweaked the case identification, and scoped the default case more explicitly to shapes we know it works for, and now raise an exception for unrecognized shape types. Unfortunately not covered by any TestModels (which is why #301 didn't fix this as well), but tested on MPL: aws/aws-cryptographic-material-providers-library#195
#195) Applies several fixes/improvements in order to work with newer Dafny versions. * Adds `smithy-dafny` as a submodule so that we can lock down the exact commit used to generate code, and use the tool in CI. * Updates the shared makefile with similar improvements to smithy-dafny's (hook up `--library-root` and `--patch-files-dir`, generate dependencies first) * Regenerates the checked-in code using a newer `smithy-dafny` to abstract away from the changes in Java TypeDescriptors when constructing datatypes in Dafny 4.3. This includes adding some helper methods to Dafny code for the benefit of Java external code, in the same style as smithy-lang/smithy-dafny#301 did. * Also updated various `__default` classes to use the above to avoid constructing Dafny datatypes directly. * Regenerating means that the effect of smithy-lang/smithy-dafny#311 on C# code shows up too. * Introduced `InternalResult<T, R>` to replace some internal-only uses of Dafny's compiled `Result` type, to avoid even more Dafny helper methods. * Leverage the `smithy-dafny` `<library-root>/codegen-patches[/<service>]` feature to extract out manual patch files. * This allows building with a newer version of Dafny to work despite having to regenerate code differently, in some cases by providing different patch files for different version ranges. * Cheated slightly by using this to conditionally remove an instance of `{:vcs_split_on_every_assert}` on `AwsKmsKeyring.OnDecrypt'` that is necessary on Dafny 4.2 but makes things work on Dafny 4.4 (which was not the intention of the patching feature, but also solves this problem much more cheaply than having to refactor the code to work in both versions :) * Add regenerating code to CI, either to verify that it matches what's checked in, or to pick up the necessary changes to work with newer Dafny versions. Manually verified the CI passes on the source branch with the latest Dafny nightly prerelease: https://github.com/aws/aws-cryptographic-material-providers-library/actions/runs/8039889665 Note that CI will now reject making further manual edits to generated files without capturing those edits in patch files. The error message will suggest how to update the patch files accordingly. See also https://github.com/smithy-lang/smithy-dafny/tree/main-1.x/TestModels/CodegenPatches
…crete class) (#331) *Description of changes:* Reverts the part of #301 that changed the result type of constructing services from the concrete class type to the trait type, which turned out to be breaking in .NET as well as Dafny and was manually reverted in aws/aws-cryptographic-material-providers-library#257. See aws/aws-cryptographic-material-providers-library#267 for the upcoming proper fix to the MPL using this change. As it turns out this change wasn't necessary in the first place, and the `CreateSuccessOfClient/CreateFailureOfError` helpers are unchanged and still use the trait type, because these helpers are only needed for services that are created by target language code, i.e. SDK-style services and `--local-service-test` wrapped services. Regular local services are constructed in Dafny code so they never need the helper methods.
…ary (smithy-lang#301) *Description of changes:* As part of the progress towards supporting traits on non-reference types, the Java backend in Dafny 4.2 changed datatype constructors to require type descriptors for any generic type parameters: dafny-lang/dafny#4240. This change fixes a big chunk of the failing nightly build failures by augmenting the Java code generation to conditionally provide these type descriptors when creating `Result` and `Option` values. In most cases this is handled by the new `nameresolver.Dafny.createSuccess/Failure/Some/None` helper methods, but in some cases some new Dafny helper methods are added to `StandardLibrary` or emitted as well, so that TestModels can provide the same Java code for any Dafny version. It also adds a parameter for the target Dafny version so it knows when to emit them, exposed both as a `--dafny-version` option for the CLI and a `dafnyVersion` configuration value on `smithy-build.json` file. This defaults to `4.1.0`, but the latter knob is actually required when using the latest "edition" of the Smithy plugin (now `2023.10` instead of `2023`), as this is exactly the kind of otherwise-breaking change editions are designed to support! Finally, it refactors the CI to test all Dafny-relevant things on multiple versions of Dafny. It follows the same workflow template as https://github.com/aws/aws-cryptographic-material-providers-library-java/tree/main/.github/workflows (and kudos to @texastony!). This exposed one verification regression on 4.3 that I'm looking into, and may factor out of this PR if it's not quick to fix. --------- Co-authored-by: Tony Knapp <[email protected]>
#195) Applies several fixes/improvements in order to work with newer Dafny versions. * Adds `smithy-dafny` as a submodule so that we can lock down the exact commit used to generate code, and use the tool in CI. * Updates the shared makefile with similar improvements to smithy-dafny's (hook up `--library-root` and `--patch-files-dir`, generate dependencies first) * Regenerates the checked-in code using a newer `smithy-dafny` to abstract away from the changes in Java TypeDescriptors when constructing datatypes in Dafny 4.3. This includes adding some helper methods to Dafny code for the benefit of Java external code, in the same style as smithy-lang/smithy-dafny#301 did. * Also updated various `__default` classes to use the above to avoid constructing Dafny datatypes directly. * Regenerating means that the effect of smithy-lang/smithy-dafny#311 on C# code shows up too. * Introduced `InternalResult<T, R>` to replace some internal-only uses of Dafny's compiled `Result` type, to avoid even more Dafny helper methods. * Leverage the `smithy-dafny` `<library-root>/codegen-patches[/<service>]` feature to extract out manual patch files. * This allows building with a newer version of Dafny to work despite having to regenerate code differently, in some cases by providing different patch files for different version ranges. * Cheated slightly by using this to conditionally remove an instance of `{:vcs_split_on_every_assert}` on `AwsKmsKeyring.OnDecrypt'` that is necessary on Dafny 4.2 but makes things work on Dafny 4.4 (which was not the intention of the patching feature, but also solves this problem much more cheaply than having to refactor the code to work in both versions :) * Add regenerating code to CI, either to verify that it matches what's checked in, or to pick up the necessary changes to work with newer Dafny versions. Manually verified the CI passes on the source branch with the latest Dafny nightly prerelease: https://github.com/aws/aws-cryptographic-material-providers-library/actions/runs/8039889665 Note that CI will now reject making further manual edits to generated files without capturing those edits in patch files. The error message will suggest how to update the patch files accordingly. See also https://github.com/smithy-lang/smithy-dafny/tree/main-1.x/TestModels/CodegenPatches
Description of changes:
As part of the progress towards supporting traits on non-reference types, the Java backend in Dafny 4.2 changed datatype constructors to require type descriptors for any generic type parameters: dafny-lang/dafny#4240.
This change fixes a big chunk of the failing nightly build failures by augmenting the Java code generation to conditionally provide these type descriptors when creating
Result
andOption
values. In most cases this is handled by the newnameresolver.Dafny.createSuccess/Failure/Some/None
helper methods, but in some cases some new Dafny helper methods are added toStandardLibrary
or emitted as well, so that TestModels can provide the same Java code for any Dafny version.It also adds a parameter for the target Dafny version so it knows when to emit them, exposed both as a
--dafny-version
option for the CLI and adafnyVersion
configuration value onsmithy-build.json
file. This defaults to4.1.0
, but the latter knob is actually required when using the latest "edition" of the Smithy plugin (now2023.10
instead of2023
), as this is exactly the kind of otherwise-breaking change editions are designed to support!Finally, it refactors the CI to test all Dafny-relevant things on multiple versions of Dafny. It follows the same workflow template as https://github.com/aws/aws-cryptographic-material-providers-library-java/tree/main/.github/workflows (and kudos to @texastony!). This exposed one verification regression on 4.3 that I'm looking into, and may factor out of this PR if it's not quick to fix.
Note the nightly build depends on a pending patch tosetup-dafny-action
to provide the actual version when usingnightly-latest
: dafny-lang/setup-dafny-action#19By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.