Skip to content

Fix: Ability to cast a datatype to its trait when overriding functions #4824

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

Merged
merged 53 commits into from
Apr 1, 2024
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
f83131a
Add test for issue #4823
MikaelMayer Nov 28, 2023
fc46d04
Fix: Ability to cast a datatype to its trait when overriding functions
MikaelMayer Nov 28, 2023
1eddcca
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 1, 2023
6559a66
Remove unused statement
MikaelMayer Dec 1, 2023
b465a07
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 5, 2023
3e49055
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 5, 2023
fe9df6d
FIXER:dafny0/Fuel.legacy.dfy
MikaelMayer Dec 6, 2023
99e8d34
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 8, 2023
b8a73cc
Fixed the only failing test
MikaelMayer Dec 14, 2023
414a663
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Dec 14, 2023
4f903d8
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 14, 2023
ba76103
revert declaration
MikaelMayer Dec 14, 2023
f249bb4
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 18, 2023
c32c5fe
Fixed a brittleness issue
MikaelMayer Dec 19, 2023
a970998
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Dec 19, 2023
c827ec4
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 19, 2023
b796d3a
Updated libraries
MikaelMayer Dec 19, 2023
6eeb09a
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Dec 19, 2023
0bd8f05
Forgot one file
MikaelMayer Dec 19, 2023
728291b
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 20, 2023
f319c0b
updated standard libraries
MikaelMayer Dec 20, 2023
551a251
FIXER:git-issues/git-issue-1514.dfy
MikaelMayer Dec 21, 2023
d9b6c7a
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Dec 27, 2023
1316b50
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Jan 8, 2024
696ab51
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 8, 2024
2114cbd
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 8, 2024
aa2e397
Installed latest version of Go
MikaelMayer Jan 8, 2024
ccd9224
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Jan 8, 2024
7de2844
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 8, 2024
80c0acb
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Jan 8, 2024
03fafd6
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 9, 2024
4276fa1
Added a test + updated doo files
MikaelMayer Jan 12, 2024
df74b06
Fixed doo file creation
MikaelMayer Jan 12, 2024
2085aac
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Jan 12, 2024
344e96d
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 12, 2024
0b008ef
Updated doo files
MikaelMayer Jan 16, 2024
47ce6a6
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 16, 2024
47194b6
Regenerate doo files on a non-Windows box
robin-aws Jan 16, 2024
e135dcc
Merge branch 'master' into fix-4823-general-traits-bug-extends
alex-chew Jan 16, 2024
6893cc9
Remove file
MikaelMayer Jan 17, 2024
06fcc20
Merge branch 'fix-4823-general-traits-bug-extends' of https://github.…
MikaelMayer Jan 17, 2024
cacf520
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 17, 2024
280326a
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Jan 19, 2024
26ed1da
Update doo files again
robin-aws Jan 19, 2024
9004729
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Feb 7, 2024
8c6aadd
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Mar 28, 2024
093d5cc
Fixed test
MikaelMayer Mar 28, 2024
cc0f0af
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Mar 29, 2024
6d88e42
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Mar 29, 2024
9d66fa4
Fixed the doo files
MikaelMayer Apr 1, 2024
a65068b
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Apr 1, 2024
f673fb3
Merge branch 'master' into fix-4823-general-traits-bug-extends
MikaelMayer Apr 1, 2024
3c2d789
Merge branch 'master' into fix-4823-general-traits-bug-extends
RustanLeino Apr 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions Source/DafnyCore/Verifier/BoogieGenerator.Functions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,8 @@ void AddFunctionConsequenceAxiom(Boogie.Function boogieFunction, Function f, Lis
}
}

private int Cutoff = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

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

It seems this field is not used.


/// <summary>
/// The list of formals "lits" is allowed to contain an object of type ThisSurrogate, which indicates that
/// the receiver parameter of the function should be included among the lit formals.
Expand Down Expand Up @@ -876,9 +878,13 @@ private Axiom GetFunctionAxiom(Function f, Expression body, List<Formal> lits) {
}

var etranBody = layer == null ? etran : etran.LimitedFunctions(f, ly);
var trbody = etranBody.TrExpr(bodyWithSubst);
// Traits as datatypes might require boxing
var conclusion = etranBody.TrExpr(new BinaryExpr(f.tok, BinaryExpr.ResolvedOpcode.EqCommon,
new BoogieWrapper(funcAppl, f.ResultType), bodyWithSubst
) { RangeToken = f.RangeToken });

tastyVegetarianOption = BplAnd(etranBody.CanCallAssumption(bodyWithSubst),
BplAnd(TrFunctionSideEffect(bodyWithSubst, etranBody), Bpl.Expr.Eq(funcAppl, trbody)));
BplAnd(TrFunctionSideEffect(bodyWithSubst, etranBody), conclusion));
}

QKeyValue kv = null;
Expand Down
10 changes: 5 additions & 5 deletions Source/DafnyCore/Verifier/BoogieGenerator.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,7 @@ private void AddFunctionOverrideEnsChk(Function f, BoogieStmtListBuilder builder
//generating trait post-conditions with class variables
FunctionCallSubstituter sub = null;
foreach (var en in f.OverriddenFunction.Ens) {
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)f.OverriddenFunction.EnclosingClass, (ClassLikeDecl)f.EnclosingClass);
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)f.OverriddenFunction.EnclosingClass, (TopLevelDeclWithMembers)f.EnclosingClass);
foreach (var s in TrSplitExpr(sub.Substitute(en.E), etran, false, out _).Where(s => s.IsChecked)) {
builder.Add(Assert(f.tok, s.E, new PODesc.FunctionContractOverride(true)));
}
Expand Down Expand Up @@ -1135,7 +1135,7 @@ private void AddFunctionOverrideSubsetChk(Function func, BoogieStmtListBuilder b
List<FrameExpression> traitFrameExps = new List<FrameExpression>();
FunctionCallSubstituter sub = null;
foreach (var e in func.OverriddenFunction.Reads.Expressions) {
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)func.OverriddenFunction.EnclosingClass, (ClassLikeDecl)func.EnclosingClass);
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)func.OverriddenFunction.EnclosingClass, (TopLevelDeclWithMembers)func.EnclosingClass);
var newE = sub.Substitute(e.E);
FrameExpression fe = new FrameExpression(e.tok, newE, e.FieldName);
traitFrameExps.Add(fe);
Expand Down Expand Up @@ -1182,7 +1182,7 @@ private void AddFunctionOverrideReqsChk(Function f, BoogieStmtListBuilder builde
//generating trait pre-conditions with class variables
FunctionCallSubstituter sub = null;
foreach (var req in f.OverriddenFunction.Req) {
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)f.OverriddenFunction.EnclosingClass, (ClassLikeDecl)f.EnclosingClass);
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)f.OverriddenFunction.EnclosingClass, (TopLevelDeclWithMembers)f.EnclosingClass);
builder.Add(TrAssumeCmdWithDependencies(etran, f.tok, sub.Substitute(req.E), "overridden function requires clause"));
}
//generating class pre-conditions
Expand Down Expand Up @@ -1425,7 +1425,7 @@ private void AddMethodOverrideEnsChk(Method m, BoogieStmtListBuilder builder, Ex
//generating trait post-conditions with class variables
FunctionCallSubstituter sub = null;
foreach (var en in m.OverriddenMethod.Ens) {
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)m.OverriddenMethod.EnclosingClass, (ClassLikeDecl)m.EnclosingClass);
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)m.OverriddenMethod.EnclosingClass, (TopLevelDeclWithMembers)m.EnclosingClass);
foreach (var s in TrSplitExpr(sub.Substitute(en.E), etran, false, out _).Where(s => s.IsChecked)) {
builder.Add(Assert(m.RangeToken, s.E, new PODesc.EnsuresStronger()));
}
Expand All @@ -1442,7 +1442,7 @@ private void AddMethodOverrideReqsChk(Method m, BoogieStmtListBuilder builder, E
//generating trait pre-conditions with class variables
FunctionCallSubstituter sub = null;
foreach (var req in m.OverriddenMethod.Req) {
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)m.OverriddenMethod.EnclosingClass, (ClassLikeDecl)m.EnclosingClass);
sub ??= new FunctionCallSubstituter(substMap, typeMap, (TraitDecl)m.OverriddenMethod.EnclosingClass, (TopLevelDeclWithMembers)m.EnclosingClass);
builder.Add(TrAssumeCmdWithDependencies(etran, m.tok, sub.Substitute(req.E), "overridden requires clause"));
}
//generating class pre-conditions
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/Verifier/FunctionCallSubstituter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@
namespace Microsoft.Dafny {
public class FunctionCallSubstituter : Substituter {
public readonly TraitDecl Tr;
public readonly ClassLikeDecl Cl;
public readonly TopLevelDeclWithMembers Cl;

// We replace all occurrences of the trait version of the function with the class version. This is only allowed if
// the receiver is `this`. We underapproximate this by looking for a `ThisExpr`, which misses more complex
// expressions that evaluate to one.
public FunctionCallSubstituter(Dictionary<IVariable, Expression /*!*/> /*!*/ substMap, Dictionary<TypeParameter, Type> typeMap,
TraitDecl parentTrait, ClassLikeDecl cl)
TraitDecl parentTrait, TopLevelDeclWithMembers cl)
: base(new ThisExpr(cl.tok) { Type = UserDefinedType.FromTopLevelDecl(cl.tok, cl) }, substMap, typeMap) {
this.Tr = parentTrait;
this.Cl = cl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Fuel.legacy.dfy(247,22): Error: assertion might not hold
Fuel.legacy.dfy(280,26): Error: assertion might not hold
Fuel.legacy.dfy(335,26): Error: function precondition could not be proved
Fuel.legacy.dfy(324,21): Related location
Fuel.legacy.dfy(313,41): Related location
Fuel.legacy.dfy(312,58): Related location
Fuel.legacy.dfy(335,26): Error: function precondition could not be proved
Fuel.legacy.dfy(324,21): Related location
Fuel.legacy.dfy(314,72): Related location
Expand All @@ -27,26 +27,26 @@ Fuel.legacy.dfy(324,21): Related location
Fuel.legacy.dfy(314,93): Related location
Fuel.legacy.dfy(335,26): Error: function precondition could not be proved
Fuel.legacy.dfy(324,21): Related location
Fuel.legacy.dfy(312,43): Related location
Fuel.legacy.dfy(314,46): Related location
Fuel.legacy.dfy(335,26): Error: function precondition could not be proved
Fuel.legacy.dfy(324,21): Related location
Fuel.legacy.dfy(312,58): Related location
Fuel.legacy.dfy(313,41): Related location
Fuel.legacy.dfy(335,26): Error: function precondition could not be proved
Fuel.legacy.dfy(324,21): Related location
Fuel.legacy.dfy(314,46): Related location
Fuel.legacy.dfy(312,43): Related location
Fuel.legacy.dfy(335,49): Error: destructor 't' can only be applied to datatype values constructed by 'VTuple'
Fuel.legacy.dfy(335,50): Error: index out of range
Fuel.legacy.dfy(336,38): Error: index out of range
Fuel.legacy.dfy(336,42): Error: destructor 'u' can only be applied to datatype values constructed by 'VUint64'
Fuel.legacy.dfy(336,45): Error: function precondition could not be proved
Fuel.legacy.dfy(329,21): Related location
Fuel.legacy.dfy(311,43): Related location
Fuel.legacy.dfy(312,43): Related location
Fuel.legacy.dfy(336,45): Error: function precondition could not be proved
Fuel.legacy.dfy(329,21): Related location
Fuel.legacy.dfy(313,41): Related location
Fuel.legacy.dfy(311,43): Related location
Fuel.legacy.dfy(336,45): Error: function precondition could not be proved
Fuel.legacy.dfy(329,21): Related location
Fuel.legacy.dfy(312,58): Related location
Fuel.legacy.dfy(313,41): Related location
Fuel.legacy.dfy(336,45): Error: function precondition could not be proved
Fuel.legacy.dfy(329,21): Related location
Fuel.legacy.dfy(314,72): Related location
Expand All @@ -55,7 +55,7 @@ Fuel.legacy.dfy(329,21): Related location
Fuel.legacy.dfy(314,93): Related location
Fuel.legacy.dfy(336,45): Error: function precondition could not be proved
Fuel.legacy.dfy(329,21): Related location
Fuel.legacy.dfy(312,43): Related location
Fuel.legacy.dfy(312,58): Related location
Fuel.legacy.dfy(336,71): Error: index out of range
Fuel.legacy.dfy(397,22): Error: assertion might not hold
Fuel.legacy.dfy(398,22): Error: assertion might not hold
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// RUN: %baredafny verify %args --type-system-refresh --general-traits=datatype "%s" > "%t"
// RUN: %diff "%s.expect" "%t"

trait Test<T> {
function Cast(t: T): Test<T>
}

datatype Impl extends Test<Impl> = ImplConstructor()
{
function Cast(t: Impl): Test<Impl> { t }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Dafny program verifier finished with 1 verified, 0 errors
1 change: 1 addition & 0 deletions docs/dev/news/4823.fix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Ability to cast a datatype to its trait when overriding functions