Skip to content
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

fix: Account for the optional equality support of map/seq inside newtypes #5980

Merged
merged 14 commits into from
Dec 17, 2024

Conversation

RustanLeino
Copy link
Collaborator

@RustanLeino RustanLeino commented Dec 12, 2024

This PR extends fix #5973 of issue #5972 to also handle newtypes, subset types, and type synonyms wrapped around map and sequence types.

Fixes #5978

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

thingsChanged = true;
} else if (type.SupportsEquality) {
// nothing to do
} else if (type.Normalize() is UserDefinedType userDefinedType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this normalization? I thought that AsMapType and AsSeqType would actually do that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type.Normalize() cuts through any type proxies that may be sitting around the UserDefinedType.

AsMapType and AsSeqType call NormalizeExpand(), which cuts through both proxies and type synonyms. But that's too much, because a type synonym can also have an explicit (==) declaration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a type synonym does not have an explicit (==) annotation, it's still sound, right?
In general, I don't think you can conclude faster that a type synonym supports equality anyway. It seems that (==) is only a way to catch errors earlier.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An explicit (==) is also a way to advertise equality support to importers of the enclosing module. Without an explicit (==), an export provides of the type would not let importers use the type as supporting equality.

MikaelMayer
MikaelMayer previously approved these changes Dec 16, 2024
Copy link
Member

@MikaelMayer MikaelMayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved when all tests pass

@@ -96,13 +96,21 @@ public Type RhsWithArgument(List<Type> typeArgs) {
public TopLevelDecl AsTopLevelDecl => this;
public TypeDeclSynonymInfo SynonymInfo { get; set; }

public TypeParameter.EqualitySupportValue EqualitySupport {
private IndDatatypeDecl.ES equalitySupport = IndDatatypeDecl.ES.NotYetComputed;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Rust compiler will also need to have precise equality support, as it's the only backend that needs to distinguish between type-parameter conditional equality and no equality possible.
Hence, it's not only solving a soundness issue, it's also making the compilation to Rust possible.

@@ -30,27 +30,16 @@ boogie: ${DIR}/boogie/Binaries/Boogie.exe
tests:
(cd "${DIR}"; dotnet test Source/IntegrationTests)

# make test name=<part of the path of an integration test>
# make test name=<integration test filter>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes to the makefile make it much much easier to test single files without having to rebuild, and also to update individual outputs without having to run the IDE or a complex command (or Lit, which we are not always supporting)

return TypeParameter.EqualitySupportValue.Unspecified;
if (equalitySupport == IndDatatypeDecl.ES.NotYetComputed) {
var thingsChanged = false;
if (ModuleResolver.SurelyNeverSupportEquality(BaseType)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the types are topologically sorted, this will only be executed when the types this newtype depends on have been resolved.

@@ -400,6 +400,12 @@ public override bool SupportsEquality {
i++;
}
return true;
} else if (ResolvedClass is NewtypeDecl newtypeDecl) {
if (newtypeDecl.IsRevealedInScope(Type.GetScope())) {
return newtypeDecl.RhsWithArgument(TypeArgs).SupportsEquality;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of my change, we could also do the same treatment as for the datatypes, if you preferred. I'm fine with both approaches and to switch if you prefer.

(anotherIndDt != null && anotherIndDt.EqualitySupport == IndDatatypeDecl.ES.Never) ||
arg.Type.IsCoDatatype ||
arg.Type.IsArrowType) {
if (arg.IsGhost || SurelyNeverSupportEquality(arg.Type)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need this type traversal to be recursive, otherwise soundness issue 5972c.dfy

thingsChanged = true;
} else if (type.SupportsEquality) {
// nothing to do
} else if (type.Normalize() is UserDefinedType userDefinedType) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a type synonym does not have an explicit (==) annotation, it's still sound, right?
In general, I don't think you can conclude faster that a type synonym supports equality anyway. It seems that (==) is only a way to catch errors earlier.

MikaelMayer
MikaelMayer previously approved these changes Dec 16, 2024
@RustanLeino RustanLeino enabled auto-merge (squash) December 17, 2024 20:41
Copy link
Member

@MikaelMayer MikaelMayer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We reviewed each other's changes and we agree with them.

@RustanLeino RustanLeino merged commit 648da0e into dafny-lang:master Dec 17, 2024
22 checks passed
@RustanLeino RustanLeino deleted the issue-5972-addendum branch December 18, 2024 17:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

General newtypes not supporting equality in a sound way
2 participants