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

Allow non-reference-type traits #4137

Merged
merged 47 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e861001
Parsing and resolution
RustanLeino Jun 5, 2023
73b6431
Add verification support
RustanLeino Jun 5, 2023
952a34b
Adjust error message wording in .expect files
RustanLeino Jun 5, 2023
b0d07f2
Adjust .expect files for verification messages
RustanLeino Jun 5, 2023
d990ba9
Add compilation support
RustanLeino Jun 5, 2023
f961c73
Fix up recently added coersions
RustanLeino Jun 6, 2023
23e9172
Add new tests
RustanLeino Jun 6, 2023
21438a7
Add tests for issue 4046
RustanLeino Jun 6, 2023
b9f4f39
Fix whitespace
RustanLeino Jun 6, 2023
3e484c0
Update options doc
RustanLeino Jun 6, 2023
b91ffee
Adjust wording in expected error in tutorial
RustanLeino Jun 8, 2023
3e688c9
Update Go runtime with new generated code
RustanLeino Jun 8, 2023
cefc6de
Merge branch 'master' into non-reference-traits
RustanLeino Jun 8, 2023
4883fb3
Correct spelling
RustanLeino Jun 8, 2023
1c15a01
Remove p_no_mutable_fields_in_value_types
RustanLeino Jun 8, 2023
3482ada
Add test for p_general_traits_beta
RustanLeino Jun 8, 2023
43ef4ff
Merge branch 'master' into non-reference-traits
RustanLeino Jun 8, 2023
832ee5e
Fix error-catalog template
RustanLeino Jun 8, 2023
6cc241d
Merge branch 'master' into non-reference-traits
RustanLeino Jun 8, 2023
6a4bac2
Fix merge
RustanLeino Jun 8, 2023
9687c6f
Fix newtype-with-trait printing in Python, per reveiw comments
RustanLeino Jun 22, 2023
b8de6e0
chore: Parameter renaming to simplify merge
RustanLeino Jun 29, 2023
11d65c2
Merge branch 'master' into non-reference-traits
RustanLeino Jun 29, 2023
60af01f
Fix merge
RustanLeino Jun 29, 2023
6279117
Fix testDafnyForEachCompiler violations
RustanLeino Jun 29, 2023
cd341cf
Find moduleInfo elsewhere
RustanLeino Jun 29, 2023
05f6742
Merge branch 'master' into non-reference-traits
RustanLeino Jun 30, 2023
6ccf0fd
Merge branch 'master' into non-reference-traits
RustanLeino Jun 30, 2023
9d5baf2
Report C++’s lack of trait support to TestDafny
RustanLeino Jun 30, 2023
bdad171
Speed up test
RustanLeino Jun 30, 2023
408efd0
Merge branch 'master' into non-reference-traits
RustanLeino Jul 1, 2023
086b484
Fix merge
RustanLeino Jul 1, 2023
e17b252
Update docs/HowToFAQ/Errors-Parser.template
RustanLeino Jul 3, 2023
a835cde
Update docs/DafnyRef/Options.txt
RustanLeino Jul 3, 2023
fa2f8a4
Update Test/traits/NonReferenceTraitsCompile.dfy
RustanLeino Jul 3, 2023
ef5b66e
Update Test/traits/NonReferenceTraits.dfy
RustanLeino Jul 3, 2023
9213570
Update Source/DafnyCore/AST/Modules/ModuleDefinition.cs
RustanLeino Jul 3, 2023
4a900e7
Update Source/DafnyCore/Resolver/NameResolutionAndTypeInference/NameR…
RustanLeino Jul 3, 2023
c88fb15
Update Source/DafnyCore/Compilers/Java/Compiler-java.cs
RustanLeino Jul 3, 2023
f21d7c1
Update Source/DafnyCore/Resolver/NameResolutionAndTypeInference/NameR…
RustanLeino Jul 3, 2023
dc33d45
Act on PR comments
RustanLeino Jul 3, 2023
4c87084
Merge branch 'master' into non-reference-traits
RustanLeino Jul 3, 2023
1efca99
Change wording in error message
RustanLeino Jul 3, 2023
023f848
Adjust line numbers in .expect file
RustanLeino Jul 3, 2023
148f93b
Make test what it what meant to be
RustanLeino Jul 3, 2023
5cd1185
Fix message in error-message testing (parsing)
RustanLeino Jul 3, 2023
c0e4279
Account for changed wording in error messages
RustanLeino Jul 3, 2023
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
15 changes: 12 additions & 3 deletions Source/DafnyCore/AST/Cloner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ public virtual TopLevelDecl CloneDeclaration(TopLevelDecl d, ModuleDefinition pa

if (d is AbstractTypeDecl) {
var dd = (AbstractTypeDecl)d;
return new AbstractTypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, CloneTPChar(dd.Characteristics), dd.TypeArgs.ConvertAll(CloneTypeParam), dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
return new AbstractTypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent,
CloneTPChar(dd.Characteristics), dd.TypeArgs.ConvertAll(CloneTypeParam),
dd.ParentTraits.ConvertAll(CloneType),
dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
} else if (d is SubsetTypeDecl) {
Contract.Assume(!(d is NonNullTypeDecl)); // don't clone the non-null type declaration; close the class, which will create a new non-null type declaration
var dd = (SubsetTypeDecl)d;
Expand All @@ -78,10 +81,12 @@ public virtual TopLevelDecl CloneDeclaration(TopLevelDecl d, ModuleDefinition pa
var dd = (NewtypeDecl)d;
if (dd.Var == null) {
return new NewtypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, CloneType(dd.BaseType),
dd.ParentTraits.ConvertAll(CloneType),
dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
} else {
return new NewtypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, CloneBoundVar(dd.Var, false),
CloneExpr(dd.Constraint), dd.WitnessKind, CloneExpr(dd.Witness),
dd.ParentTraits.ConvertAll(CloneType),
dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
}
} else if (d is TupleTypeDecl) {
Expand All @@ -92,13 +97,17 @@ public virtual TopLevelDecl CloneDeclaration(TopLevelDecl d, ModuleDefinition pa
var dd = (IndDatatypeDecl)d;
var tps = dd.TypeArgs.ConvertAll(CloneTypeParam);
var ctors = dd.Ctors.ConvertAll(CloneCtor);
var dt = new IndDatatypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, tps, ctors, dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
var dt = new IndDatatypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, tps, ctors,
dd.ParentTraits.ConvertAll(CloneType),
dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
return dt;
} else if (d is CoDatatypeDecl) {
var dd = (CoDatatypeDecl)d;
var tps = dd.TypeArgs.ConvertAll(CloneTypeParam);
var ctors = dd.Ctors.ConvertAll(CloneCtor);
var dt = new CoDatatypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, tps, ctors, dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
var dt = new CoDatatypeDecl(Range(dd.RangeToken), dd.NameNode.Clone(this), parent, tps, ctors,
dd.ParentTraits.ConvertAll(CloneType),
dd.Members.ConvertAll(d => CloneMember(d, false)), CloneAttributes(dd.Attributes), dd.IsRefining);
return dt;
} else if (d is IteratorDecl) {
var dd = (IteratorDecl)d;
Expand Down
6 changes: 5 additions & 1 deletion Source/DafnyCore/AST/Grammar/ParseErrors.cs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ public enum ErrorId {
p_deprecated_statement_refinement,
p_internal_exception,
p_file_has_no_code,

p_general_traits_beta,
}

static ParseErrors() {
Expand All @@ -153,6 +153,10 @@ static ParseErrors() {
Only modules may be declared abstract.
", Remove(true));

Add(ErrorId.p_general_traits_beta,
@"Use of traits as non-reference types is a beta feature. To engage, use /generalTraits:1.
", Remove(true));

Add(ErrorId.p_no_ghost_for_by_method,
@"
Functions with a [by method](https://dafny.org/latest/DafnyRef/DafnyRef#sec-function-declarations)
Expand Down
28 changes: 20 additions & 8 deletions Source/DafnyCore/AST/Grammar/Printer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ public void PrintTopLevelDecls(Program program, IEnumerable<TopLevelDecl> decls,
if (i++ != 0) { wr.WriteLine(); }
Indent(indent);
PrintClassMethodHelper("type", at.Attributes, at.Name + TPCharacteristicsSuffix(at.Characteristics), d.TypeArgs);
PrintExtendsClause(at);
if (at.Members.Count == 0) {
wr.WriteLine();
} else {
Expand All @@ -284,6 +285,7 @@ public void PrintTopLevelDecls(Program program, IEnumerable<TopLevelDecl> decls,
if (i++ != 0) { wr.WriteLine(); }
Indent(indent);
PrintClassMethodHelper("newtype", dd.Attributes, dd.Name, new List<TypeParameter>());
PrintExtendsClause(dd);
wr.Write(" = ");
if (dd.Var == null) {
PrintType(dd.BaseType);
Expand Down Expand Up @@ -359,6 +361,11 @@ public void PrintTopLevelDecls(Program program, IEnumerable<TopLevelDecl> decls,
if (i++ != 0) { wr.WriteLine(); }
PrintClass(cl, indent, fileBeingPrinted);

} else if (d is ClassLikeDecl) {
var cl = (ClassLikeDecl)d;
if (i++ != 0) { wr.WriteLine(); }
PrintClass(cl, indent, fileBeingPrinted);

} else if (d is ValuetypeDecl) {
var vtd = (ValuetypeDecl)d;
if (i++ != 0) { wr.WriteLine(); }
Expand Down Expand Up @@ -608,7 +615,7 @@ void PrintIteratorSignature(IteratorDecl iter, int indent) {
Indent(indent);
PrintClassMethodHelper("iterator", iter.Attributes, iter.Name, iter.TypeArgs);
if (iter.IsRefining) {
wr.Write(" ... ");
wr.Write(" ...");
} else {
PrintFormals(iter.Ins, iter);
if (iter.Outs.Count != 0) {
Expand Down Expand Up @@ -654,14 +661,9 @@ public void PrintClass(ClassLikeDecl c, int indent, string fileBeingPrinted) {
Indent(indent);
PrintClassMethodHelper((c is TraitDecl) ? "trait" : "class", c.Attributes, c.Name, c.TypeArgs);
if (c.IsRefining) {
wr.Write(" ... ");
wr.Write(" ...");
} else {
string sep = " extends ";
foreach (var trait in c.ParentTraits) {
wr.Write(sep);
PrintType(trait);
sep = ", ";
}
PrintExtendsClause(c);
}

if (c.Members.Count == 0) {
Expand All @@ -684,6 +686,15 @@ public void PrintClass(ClassLikeDecl c, int indent, string fileBeingPrinted) {
}
}

private void PrintExtendsClause(TopLevelDeclWithMembers c) {
string sep = " extends ";
foreach (var trait in c.ParentTraits) {
wr.Write(sep);
PrintType(trait);
sep = ", ";
}
}

public void PrintMembers(List<MemberDecl> members, int indent, string fileBeingPrinted) {
Contract.Requires(members != null);

Expand Down Expand Up @@ -809,6 +820,7 @@ public void PrintDatatype(DatatypeDecl dt, int indent, string fileBeingPrinted)
Contract.Requires(dt != null);
Indent(indent);
PrintClassMethodHelper(dt is IndDatatypeDecl ? "datatype" : "codatatype", dt.Attributes, dt.Name, dt.TypeArgs);
PrintExtendsClause(dt);
wr.Write(" =");
string sep = "";
foreach (DatatypeCtor ctor in dt.Ctors) {
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/AST/Grammar/ProgramParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ public static void AddParseResultToProgram(DfyParseResult parseResult, Program p
literalModuleDecl.ModuleDef.EnclosingModule = defaultModule;
}

if (declToMove is ClassLikeDecl classDecl) {
classDecl.NonNullTypeDecl.EnclosingModuleDefinition = defaultModule;
if (declToMove is ClassLikeDecl { NonNullTypeDecl: { } nonNullTypeDecl }) {
nonNullTypeDecl.EnclosingModuleDefinition = defaultModule;
}
if (declToMove is DefaultClassDecl defaultClassDecl) {
foreach (var member in defaultClassDecl.Members) {
Expand Down
5 changes: 4 additions & 1 deletion Source/DafnyCore/AST/Modules/ScopeCloner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,10 @@ public override TopLevelDecl CloneDeclaration(TopLevelDecl d, ModuleDefinition m
var tps = d.TypeArgs.ConvertAll(CloneTypeParam);
var characteristics = TypeParameter.GetExplicitCharacteristics(d);
var members = based is TopLevelDeclWithMembers tm ? tm.Members : new List<MemberDecl>();
var otd = new AbstractTypeDecl(Range(d.RangeToken), d.NameNode.Clone(this), m, characteristics, tps, members, CloneAttributes(d.Attributes), d.IsRefining);
// copy the parent traits only if "d" is already an AbstractTypeDecl and is being export-revealed
var otd = new AbstractTypeDecl(Range(d.RangeToken), d.NameNode.Clone(this), m, characteristics, tps,
new List<Type>(), // omit the parent traits
members, CloneAttributes(d.Attributes), d.IsRefining);
based = otd;
if (d is ClassLikeDecl { IsReferenceTypeDecl: true } cl) {
reverseMap.Add(based, cl.NonNullTypeDecl);
Expand Down
5 changes: 3 additions & 2 deletions Source/DafnyCore/AST/TypeDeclarations/AbstractTypeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ public bool SupportsEquality {
get { return Characteristics.EqualitySupport != TypeParameter.EqualitySupportValue.Unspecified; }
}

public AbstractTypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, TypeParameter.TypeParameterCharacteristics characteristics, List<TypeParameter> typeArgs, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, members, attributes, isRefining) {
public AbstractTypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, TypeParameter.TypeParameterCharacteristics characteristics,
List<TypeParameter> typeArgs, List<Type> parentTraits, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, members, attributes, isRefining, parentTraits) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Expand Down
1 change: 0 additions & 1 deletion Source/DafnyCore/AST/TypeDeclarations/ClassDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public class ClassDecl : ClassLikeDecl, IHasDocstring {
public override bool IsReferenceTypeDecl => true;
public override bool AcceptThis => true;

public override bool CanBeRevealed() { return true; }
[FilledInDuringResolution] public bool HasConstructor; // filled in (early) during resolution; true iff there exists a member that is a Constructor
[ContractInvariantMethod]
void ObjectInvariant() {
Expand Down
21 changes: 9 additions & 12 deletions Source/DafnyCore/AST/TypeDeclarations/ClassLikeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,18 @@ namespace Microsoft.Dafny;
public abstract class ClassLikeDecl : TopLevelDeclWithMembers, RevealableTypeDecl, ICanFormat {
public NonNullTypeDecl NonNullTypeDecl; // returns non-null value iff IsReferenceTypeDecl

public override bool CanBeRevealed() { return true; }

public bool IsObjectTrait {
get => Name == "object";
}

/// <summary>
/// The IsReferenceTypeDecl getter must not be called before this information is available.
/// For most types, this information is known immediately, but for a TraitDecl, the information is not known until
/// SetUpAsReferenceType has been called. The SetUpAsReferenceType method is called very early during resolution,
/// namely during name registration of the enclosing module.
/// </summary>
public abstract bool IsReferenceTypeDecl { get; }

public TopLevelDecl AsTopLevelDecl => this;
Expand Down Expand Up @@ -63,18 +72,6 @@ public virtual bool SetIndent(int indentBefore, TokenNewIndentCollector formatte
return true;
}

public List<Type> PossiblyNullTraitsWithArgument(List<Type> typeArgs) {
Contract.Requires(typeArgs != null);
Contract.Requires(typeArgs.Count == TypeArgs.Count);
// Instantiate with the actual type arguments
var subst = TypeParameter.SubstitutionMap(TypeArgs, typeArgs);
return ParentTraits.ConvertAll(traitType => (Type)UserDefinedType.CreateNullableType((UserDefinedType)traitType.Subst(subst)));
}

public override List<Type> ParentTypes(List<Type> typeArgs) {
return PossiblyNullTraitsWithArgument(typeArgs);
}

protected override string GetTriviaContainingDocstring() {
IToken candidate = null;
foreach (var token in OwnedTokens) {
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/AST/TypeDeclarations/CoDatatypeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ public class CoDatatypeDecl : DatatypeDecl {
[FilledInDuringResolution] public CoDatatypeDecl SscRepr;

public CoDatatypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, List<TypeParameter> typeArgs,
[Captured] List<DatatypeCtor> ctors, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, ctors, members, attributes, isRefining) {
[Captured] List<DatatypeCtor> ctors, List<Type> parentTraits, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, ctors, parentTraits, members, attributes, isRefining) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/AST/TypeDeclarations/DatatypeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ void ObjectInvariant() {
public override IEnumerable<Node> PreResolveChildren => Ctors.Concat<Node>(base.PreResolveChildren);

public DatatypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, List<TypeParameter> typeArgs,
[Captured] List<DatatypeCtor> ctors, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, members, attributes, isRefining) {
[Captured] List<DatatypeCtor> ctors, List<Type> parentTraits, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, members, attributes, isRefining, parentTraits) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Expand Down
4 changes: 2 additions & 2 deletions Source/DafnyCore/AST/TypeDeclarations/IndDatatypeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public enum ES { NotYetComputed, Never, ConsultTypeArguments }
public ES EqualitySupport = ES.NotYetComputed;

public IndDatatypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, List<TypeParameter> typeArgs,
[Captured] List<DatatypeCtor> ctors, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, ctors, members, attributes, isRefining) {
[Captured] List<DatatypeCtor> ctors, List<Type> parentTraits, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, typeArgs, ctors, parentTraits, members, attributes, isRefining) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Expand Down
10 changes: 6 additions & 4 deletions Source/DafnyCore/AST/TypeDeclarations/NewtypeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,19 @@ public class NewtypeDecl : TopLevelDeclWithMembers, RevealableTypeDecl, Redirect
public SubsetTypeDecl.WKind WitnessKind { get; set; } = SubsetTypeDecl.WKind.CompiledZero;
public Expression/*?*/ Witness { get; set; } // non-null iff WitnessKind is Compiled or Ghost
[FilledInDuringResolution] public NativeType NativeType; // non-null for fixed-size representations (otherwise, use BigIntegers for integers)
public NewtypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, Type baseType, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, new List<TypeParameter>(), members, attributes, isRefining) {
public NewtypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, Type baseType, List<Type> parentTraits,
List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, new List<TypeParameter>(), members, attributes, isRefining, parentTraits) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Contract.Requires(isRefining ^ (baseType != null));
Contract.Requires(members != null);
BaseType = baseType;
}
public NewtypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, BoundVar bv, Expression constraint, SubsetTypeDecl.WKind witnessKind, Expression witness, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, new List<TypeParameter>(), members, attributes, isRefining) {
public NewtypeDecl(RangeToken rangeToken, Name name, ModuleDefinition module, BoundVar bv, Expression constraint,
SubsetTypeDecl.WKind witnessKind, Expression witness, List<Type> parentTraits, List<MemberDecl> members, Attributes attributes, bool isRefining)
: base(rangeToken, name, module, new List<TypeParameter>(), members, attributes, isRefining, parentTraits) {
Contract.Requires(rangeToken != null);
Contract.Requires(name != null);
Contract.Requires(module != null);
Expand Down
2 changes: 1 addition & 1 deletion Source/DafnyCore/AST/TypeDeclarations/NonNullTypeDecl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public override List<Type> ParentTypes(List<Type> typeArgs) {
foreach (var rhsParentType in Class.ParentTypes(typeArgs)) {
var rhsParentUdt = (UserDefinedType)rhsParentType; // all parent types of .Class are expected to be possibly-null class types
Contract.Assert(rhsParentUdt.ResolvedClass is TraitDecl);
result.Add(UserDefinedType.CreateNonNullType(rhsParentUdt));
result.Add(UserDefinedType.CreateNonNullTypeIfReferenceType(rhsParentUdt));
}

return result;
Expand Down
23 changes: 21 additions & 2 deletions Source/DafnyCore/AST/TypeDeclarations/TopLevelDeclWithMembers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,21 @@ public void SetMembersBeforeResolution() {
MembersBeforeResolution = Members.ToImmutableList();
}

public List<Type> RawTraitsWithArgument(List<Type> typeArgs) {
Contract.Requires(typeArgs != null);
Contract.Requires(typeArgs.Count == TypeArgs.Count);
// Instantiate with the actual type arguments
var subst = TypeParameter.SubstitutionMap(TypeArgs, typeArgs);
return ParentTraits.ConvertAll(traitType => {
var ty = (UserDefinedType)traitType.Subst(subst);
return (Type)UserDefinedType.CreateNullableTypeIfReferenceType(ty);
});
}

public override List<Type> ParentTypes(List<Type> typeArgs) {
return RawTraitsWithArgument(typeArgs);
}

public static List<UserDefinedType> CommonTraits(TopLevelDeclWithMembers a, TopLevelDeclWithMembers b) {
Contract.Requires(a != null);
Contract.Requires(b != null);
Expand Down Expand Up @@ -132,8 +147,12 @@ private void AddTraitAncestors(ISet<TraitDecl> s) {
Contract.Requires(s != null);
foreach (var parent in ParentTraits) {
var udt = (UserDefinedType)parent; // in a successfully resolved program, we expect all .ParentTraits to be a UserDefinedType
var nntd = (NonNullTypeDecl)udt.ResolvedClass; // we expect the trait type to be the non-null version of the trait type
var tr = (TraitDecl)nntd.Class;
TraitDecl tr;
if (udt.ResolvedClass is NonNullTypeDecl nntd) {
tr = (TraitDecl)nntd.Class;
} else {
tr = (TraitDecl)udt.ResolvedClass;
}
s.Add(tr);
tr.AddTraitAncestors(s);
}
Expand Down
20 changes: 16 additions & 4 deletions Source/DafnyCore/AST/TypeDeclarations/TraitDecl.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Microsoft.Dafny.Auditor;
using System.Diagnostics.Contracts;

namespace Microsoft.Dafny;

Expand All @@ -8,14 +9,25 @@ public class TraitDecl : ClassLikeDecl {
public bool IsParent { set; get; }
public override bool AcceptThis => true;

public override bool IsReferenceTypeDecl => true; // SOON: IsObjectTrait || ParentTraits.Any(parent => parent.IsRefType);
internal void SetUpAsReferenceType(bool isReferenceType) {
// Note, it's important to set .NonNullTypeDecl first, before calling NewSelfSynonym(), since the latter will look at the former.
Contract.Assert(NonNullTypeDecl == null); // SetUpAsReferenceType should be called only once
if (isReferenceType) {
NonNullTypeDecl = new NonNullTypeDecl(this);
}

this.NewSelfSynonym();
}

public override bool IsReferenceTypeDecl => NonNullTypeDecl != null;

/// <summary>
/// This constructor creates a TraitDecl object. However, before the object really functions as a TraitDecl, it is necessary
/// to call SetUpAsReferenceType, which sets .NonNullTypeDecl (if necessary) and calls NewSelfSynonym().
/// </summary>
public TraitDecl(RangeToken rangeToken, Name name, ModuleDefinition module,
List<TypeParameter> typeArgs, [Captured] List<MemberDecl> members, Attributes attributes, bool isRefining, List<Type> /*?*/ traits)
: base(rangeToken, name, module, typeArgs, members, attributes, isRefining, traits) {

NonNullTypeDecl = new NonNullTypeDecl(this); // SOON: this should be done only if the trait is a reference type
this.NewSelfSynonym();
}

public override IEnumerable<Assumption> Assumptions(Declaration decl) {
Expand Down
Loading