-
Notifications
You must be signed in to change notification settings - Fork 266
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: Use correct type for map update expression #3060
Conversation
Test/git-issues/git-issue-3059.dfy
Outdated
@@ -0,0 +1,10 @@ | |||
// RUN: %baredafny verify %args_0 "%s" > "%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.
@keyboardDrummer yay ! we can use the new CLI for tests now.
Source/DafnyCore/Resolver.cs
Outdated
@@ -15074,7 +15074,8 @@ public ResolutionContext(ICodeContext codeContext, bool isTwoState) | |||
ResolveExpression(e.Index, resolutionContext); | |||
ResolveExpression(e.Value, resolutionContext); | |||
AddXConstraint(expr.tok, "SeqUpdatable", e.Seq.Type, e.Index, e.Value, "update requires a sequence, map, or multiset (got {0})"); | |||
expr.Type = e.Seq.Type; | |||
var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Seq.Type); | |||
expr.Type = ty; |
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.
This does not look right to me — there's no member selection here. Instead, shouldn't we just revert to the base type? (e.Seq.Type
with the constraints removed?)
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.
We can't because at this point the type are not resolved. We first need to resolve identifier names (such as "foo"), hence the need to "partially resolve")
|
||
public override string Description => @" | ||
if false then always exit with a 0 exit code, regardless of whether errors are found. | ||
If true (default) then use the appropriate exit code.".TrimStart(); |
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.
It's a bit uncommon to have such a flag. Shouldn't we find another solution in the test suite itself?
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.
We already have this option in a substantial portion of our 1400+ tests, whenever you have %dafny_0, it means you have this flag.
Since %baredafny verify
only takes new arguments, we need to expose this option to make it work.
I don't know of another simple way.
What we could do is hide this option to users, but I don't know how to do that. @keyboardDrummer ?
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.
But the description of that flag says "deprecated" in the old CLI:
/countVerificationErrors:<n>
(deprecated)
0 - Set exit code to 0 regardless of the presence of any other errors.
1 (default) - Emit usual exit code (cf. beginning of the help message).
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 think for this test we should just use the old CLI. And we can then (in a separate PR) enhance LitTests.cs to accept || true
at the end of a command line, which is the "right" way to ignore an exit code. WDYT?
The proposed fix does not eliminate the problem. Here is an example where it remains: type foo = m: map<int, int> | forall n <- m.Keys :: m[n] < 5
method addToFoo() returns (r: foo)
ensures false
{
var m; // The type of m is to be inferred, but that won't happen until
// after type inference has processed the assignment to r.
r := m[1 := 7];
// To trigger the unsoundness, the verifier needs to be reminded that
// r is a variable of type foot. That is done by the following little
// trick:
ghost var u := RecoverType(r);
}
function RecoverType(a: foo): foo { a } As @cpitclaudel says above, we'd like to revert to the base type. The problem is that we can't get that directly from |
Source/DafnyCore/Resolver.cs
Outdated
var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Seq.Type); | ||
expr.Type = ty; |
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.
var ty = PartiallyResolveTypeForMemberSelection(expr.tok, e.Seq.Type); | |
expr.Type = ty; | |
expr.Type = PartiallyResolveTypeForMemberSelection(expr.tok, e.Seq.Type); |
That would be nice, but it's not that simple (I think?): we don't know yet that |
This PR fixes #3059
The solution was similar to the one implemented in #2059
It consists in not setting the type of the expression
m[k := v]
as the same type ofm
, but as the partially resolved type ofm
(whatever this means, I just took the code in other branches).I added a corresponding test.
This PR also introduces the command-line argument
--nonzero-exit-code-if-errors
set by default totrue
so that we can use the new Dafny CLI with%baredafny verify %args_0
for files that are supposed to fail.By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.