fix(laurel): local variable no longer shadows output parameter#642
fix(laurel): local variable no longer shadows output parameter#642fabiomadge wants to merge 1 commit intostrata-org:mainfrom
Conversation
…a-org#567) When a local variable declaration has the same name as an output parameter (e.g. `var result` in a procedure with auto-generated `returns (result : int)`), emit `set`/`havoc` instead of `init` in the generated Core. This avoids shadowing the output parameter, which caused the return value to be silently lost. The fix uses a local `intro` helper that checks `isOutputParam` once and replaces `init` with the appropriate Core statement: - `init name type (some expr)` → `set name expr` - `init name type none` → `havoc name` - `init` before `call` → dropped (call writes directly)
There was a problem hiding this comment.
This PR changes Laurel in a way that I think is confusing.
What happens if I do:
procedure double(x: int) returns (result: int)
ensures result == 1
{
result := 1;
var result: int := 23;
return;
};
Would that fail?
Instead of what this PR does, I'd rather add a feature to Laurel that enables anonymous return variables, so we can replace the code that creates a "result" return variable.
We could also consider adding an option that disallows shadowing of return parameters.
fabiomadge
left a comment
There was a problem hiding this comment.
Verification fails for the example you provided, as result becomes 23. I don't think there is any situation where a Laurel user should see Core type-checking errors. I don't understand what value anonymous return values add to a language not primarily targeted at humans, to make them worth the added complexity. I'm fine with preventing users from redeclaring return values, but that seems like a different PR to me. We should close this PR if you object to the change.
That seems wrong
Agreed. Laurel's resolution phase should prevent that.
Because then the languages building on top of Laurel don't have to come up with names for the output parameters when there is no name in the user program, which gives them the problem of having to come up with a unique name, a problem that Laurel can solve for them. |
Fixes #567.
Problem
When a Laurel procedure declares a local variable with the same name as an output parameter (e.g.
var result: int := x + xin a procedure withreturns (result: int)), the generated Core emitsinit resultinside the$bodyblock, which shadows the output parameter. Thereturnstatement then assigns the local to itself, and the output parameter is never written.Fix
In
translateStmtforLocalVariable: when the variable name matches an output parameter, emitset/havocinstead ofinit, since the variable already exists in Core as the output parameter.init name type (some expr)→set name exprinit name type none→havoc nameinitbeforecall→ dropped (thecallwrites to the existing variable directly)Before
After
Tests
New test
T18_LocalVarShadowsOutputcovers five cases:resultname