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: Correct cast of EnclosingClass #4954

Merged
merged 6 commits into from
Jan 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 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
@@ -0,0 +1,29 @@
// RUN: %testDafnyForEachResolver "%s" -- --general-traits=datatype

trait A<K> {
function FunctionRequires(): bool
requires true
function FunctionReads(): bool
reads {}
decreases 2
function FunctionEnsures(): bool
ensures true

method MethodRequires()
requires true
method MethodEnsures()
ensures true
}

type B extends A<string> {
// Each of the following 5 override checks once caused a crash, because those checks
// were not expecting the overrides to be found in an abstract type.

function FunctionRequires(): bool
function FunctionReads(): bool
decreases 2
function FunctionEnsures(): bool

method MethodRequires()
method MethodEnsures()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

Dafny program verifier finished with 6 verified, 0 errors
1 change: 1 addition & 0 deletions docs/dev/news/4954.fix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix crash when a function/method with a specification is overridden in an abstract type.
Loading