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

C# compiler error when generated lambda refers to out parameter #531

Open
lukemaurer opened this issue Feb 5, 2020 · 0 comments
Open

C# compiler error when generated lambda refers to out parameter #531

lukemaurer opened this issue Feb 5, 2020 · 0 comments
Labels
kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label lang: c# Dafny's C# transpiler and its runtime part: code-generation Support for transpiling Dafny to another language. If relevant, add a `lang:` tag

Comments

@lukemaurer
Copy link
Collaborator

If a lambda in the source code mentions an out parameter, the out parameter's value is captured in a temporary variable at the moment the closure is created, since C# doesn't allow out parameters to occur inside lambdas. However, this isn't done for source-level constructs that are compiled into lambdas, such as set comprehensions:

method Test(a : int) returns (b : int, c : int) requires a != 0 {
  var xs := set x | x in { 1, 2, 3, 4, 5 } :: x % a == b;
  b := |xs|;
}

method Main() {
  var x, _ := Test(2);
  print x, "\n";
}
Errors compiling program
/var/folders/4z/3lglrccd2ts1ns79fkybj4cwlwfdyg/T/fd0rhgw2.0.cs(1649,71) : error CS1628: Parameter `b' cannot be used inside `lambda expression' when using `ref' or `out' modifier

(Note that Test() must have two out parameters, as otherwise the generated C# code has a return type rather than an out parameter.)

lukemaurer pushed a commit that referenced this issue Feb 12, 2020
… in lambdas

The pre-compiler now transforms each method with multiple (non-ghost) out
parameters into one that returns a single tuple, when targeting a language
(currently Java or JavaScript) that has neither output parameters (as C# has)
nor support for returning multiple values (as Go has).

This work exposed a bug (#531) in the handling of free occurrences of out
parameters in constructs that are translated as lambdas in the target language.
Namely, such out parameters need to be copied into temporary variables in the
same way that free variables of source-level lambdas are copied.  (Previously,
this was done with let expressions but not other constructs like set
comprehensions.)  Also, Java requires more care than other languages in dealing
with free vars in lambdas, as *no* mutable variable may occur free in a lambda
in Java.  (More precisely, any free variable in a lambda or inner class must be
"effectively final," which is to say it could have been declared as final even
if it wasn't.)

The simplest solution to this was to take the way free variables are handled
for source-level lambdas (see the LambdaExpr case of TrExpr), generalize it a
bit, and use it for anything translated into a lambda: copy the free variables
into temporaries (using a beta redex), then, before translating the body,
perform substitution on the source term, replacing each free variable with its
corresponding temporary.  This makes it unnecessary to remember any state
associated with generating a lambda in the target language; in particular, the
inLetExprBody parameter isn't needed anymore.

FIXME: Currently, Dafny assumes that all tuple types that the program will need
are created by the parser, since each tuple type is created in a half-finished
state (no destructors, for instance) and needs the resolver to run to finish
it.  For the tupling pass, this means that the program needs to mention each
tuple type that will be needed in the final program (see SillyMethod() in
Arrays.dfy and Calls.dfy).  This is of course a temporary workaround; somehow
we need to be able to create tuple types in post-resolver code.
@robin-aws robin-aws added lang: c# Dafny's C# transpiler and its runtime part: code-generation Support for transpiling Dafny to another language. If relevant, add a `lang:` tag labels Jun 23, 2020
@acioc acioc added this to the Dafny 3.0 milestone Aug 20, 2020
@acioc acioc added the kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label label Aug 20, 2020
@atomb atomb removed this from the Dafny 3.0 milestone Apr 21, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label lang: c# Dafny's C# transpiler and its runtime part: code-generation Support for transpiling Dafny to another language. If relevant, add a `lang:` tag
Projects
None yet
Development

No branches or pull requests

4 participants