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: Support for enumerating datatypes in the Rust backend #5670

Merged
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ update-go-module:
update-runtime-dafny:
(cd "${DIR}"; cd Source/DafnyRuntime/DafnyRuntimeDafny; make update-go)

pr-nogeneration: format-dfy format update-runtime-dafny update-cs-module update-rs-module update-go-module
pr-nogeneration: format-dfy format update-runtime-dafny update-cs-module update-rs-module update-go-module update-rs-module

update-standard-libraries:
(cd "${DIR}"; cd Source/DafnyStandardLibraries; make update-binary)
Expand Down
16 changes: 15 additions & 1 deletion Source/DafnyCore/Backends/Dafny/DafnyCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2439,7 +2439,21 @@ protected override void EmitSeqBoundedPool(Expression of, bool includeDuplicates
}

protected override void EmitDatatypeBoundedPool(IVariable bv, string propertySuffix, bool inLetExprBody, ConcreteSyntaxTree wr, ConcreteSyntaxTree wStmts) {
AddUnsupported("<i>EmitDatatypeBoundedPool</i>");
if (GetExprConverter(wr, wStmts, out var exprBuilder, out var convert)) {
if (bv.Type.IsDatatype && bv.Type.AsDatatype is { } datatypeDecl) {

var signature = Sequence<_IFormal>.FromArray(new _IFormal[] { });
var c = exprBuilder.Builder.Call(signature);
c.SetName((DAST.CallName)DAST.CallName.create_CallName(Sequence<Rune>.UnicodeFromString("_AllSingletonConstructors"),
Option<_IType>.create_None(), Option<_IFormal>.create_None(), false, signature));
var wrc = new BuilderSyntaxTree<ExprContainer>(c, this);
EmitTypeName_Companion(bv.Type, wrc, wr, bv.Tok, null);
} else {
throw new InvalidOperationException("Datatype Bounded pool on non-datatype value");
}
} else {
throw new InvalidOperationException();
}
}

protected override void CreateIIFE(string bvName, Type bvType, IToken bvTok, Type bodyType, IToken bodyTok,
Expand Down
35 changes: 35 additions & 0 deletions Source/DafnyCore/Backends/Rust/Dafny-compiler-rust.dfy
Original file line number Diff line number Diff line change
Expand Up @@ -2389,11 +2389,21 @@ module {:extern "DCOMP"} DafnyToRustCompiler {
var datatypeName := escapeName(c.name);
var ctors: seq<R.EnumCase> := [];
var variances := Std.Collections.Seq.Map((typeParamDecl: TypeArgDecl) => typeParamDecl.variance, c.typeParams);
var singletonConstructors := [];
var usedTypeParams: set<string> := {};
for i := 0 to |c.ctors| {
var ctor := c.ctors[i];
var ctorArgs: seq<R.Field> := [];
var isNumeric := false;
if |ctor.args| == 0 {
var instantiation := R.StructBuild(R.Identifier(datatypeName).FSel(escapeName(ctor.name)), []);
if IsRcWrapped(c.attributes) {
instantiation := R.RcNew(instantiation);
}
singletonConstructors := singletonConstructors + [
instantiation
];
}
for j := 0 to |ctor.args| {
var dtor := ctor.args[j];
var formalType := GenType(dtor.formal.typ, GenTypeContext.default());
Expand Down Expand Up @@ -2785,6 +2795,31 @@ module {:extern "DCOMP"} DafnyToRustCompiler {
];
}

if |singletonConstructors| == |c.ctors| {
var datatypeType := R.TypeApp(R.TIdentifier(datatypeName), rTypeParams);
var instantiationType :=
if IsRcWrapped(c.attributes) then
R.Rc(datatypeType)
else
datatypeType;
s := s + [
R.ImplDecl(
R.Impl(
rTypeParamsDecls,
datatypeType,
"",
[R.FnDecl(
R.PUB,
R.Fn(
"_AllSingletonConstructors", [],
[],
Some(R.dafny_runtime.MSel("SequenceIter").AsType().Apply([instantiationType])),
"",
Some(R.dafny_runtime.MSel("seq!").AsExpr().Apply(singletonConstructors).Sel("iter").Apply([]))
)
)]))];
}

// Implementation of Eq when c supports equality
if cIsEq {
s := s + [R.ImplDecl(
Expand Down
605 changes: 313 additions & 292 deletions Source/DafnyCore/GeneratedFromDafny/DCOMP.cs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions Source/DafnyRuntime/DafnyRuntimeRust/src/system/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,12 @@ pub mod _System {
}
}

impl Tuple0 {
pub fn _AllSingletonConstructors() -> crate::SequenceIter<::std::rc::Rc<Tuple0>> {
crate::seq![::std::rc::Rc::new(Tuple0::_T0 {})].iter()
}
}

impl Eq
for Tuple0 {}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %testDafnyForEachCompiler "%s"

datatype D = A | B

const c := set d: D | true :: d

datatype {:rust_rc false} E = F | G

const h := set e: E | true :: e

method Main() {
print |c|, |h|, "\n";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
22
1 change: 1 addition & 0 deletions docs/dev/news/5643.fix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support for enumerating datatypes in the Rust backend
Loading