-
Notifications
You must be signed in to change notification settings - Fork 44
Fix scoping bug in HeapParam pass #1113
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
base: main
Are you sure you want to change the base?
Changes from all commits
4d34998
7760c92
f8acfc6
39189f3
515f13d
4c72dc4
9788a1b
60cedac
a5a6d5c
702bf34
906fe44
dd17265
d5e90af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,4 +12,5 @@ vcs/*.smt2 | |
| *.py.ion | ||
| *.py.ion.core.st | ||
|
|
||
| Strata.code-workspace | ||
| Strata.code-workspace | ||
| IntermediatePrograms/ | ||
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -315,7 +315,11 @@ where | |||||||||||
| let isLast := idx == n - 1 | ||||||||||||
| let s' ← recurse s (isLast && valueUsed) | ||||||||||||
| let rest' ← processStmts (idx + 1) rest | ||||||||||||
| pure (s' :: rest') | ||||||||||||
| -- Flatten blocks created by recurse so that | ||||||||||||
| -- Declare targets remain in the enclosing scope. | ||||||||||||
| match s'.val with | ||||||||||||
| | .Block innerStmts (some "$inlineMe") => pure (innerStmts ++ rest') | ||||||||||||
| | _ => pure (s' :: rest') | ||||||||||||
|
tautschnig marked this conversation as resolved.
Comment on lines
+318
to
+322
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Two outstanding items from the prior thread (marked resolved, but I don't think the concerns actually went away): (a) /-- Internal sentinel block label produced by the field-target branch at line 396
and consumed here. Must not appear anywhere else in the program. -/
private abbrev inlineMeLabel : String := "$inlineMe"
-- then at line 321:
| .Block innerStmts (some inlineMeLabel) => pure (innerStmts ++ rest')( Alternatively, with a helper predicate: private def isInlineMeBlock : StmtExpr → Option (List StmtExprMd)
| .Block inner (some "$inlineMe") => some inner
| _ => none
-- usage:
match isInlineMeBlock s'.val with
| some innerStmts => pure (innerStmts ++ rest')
| none => pure (s' :: rest')Either makes the "only here" invariant documentable in one place and immune to a future copy-paste of the string elsewhere in the codebase. (b) Your question: "Are you sure it's an issue if the sentinel block survives?" — yes, and it's exactly the Your fix currently works because every procedure body in the Laurel surface syntax parses as a
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Workaround with abbrev doesn't work for me. "(abbrev is reducible during elaboration, so the pattern matches the literal. I verified this shape locally in a scratch file.)" Do you know why we're seeing different local results?
I don't follow the explanation. You're saying there is an issue for a particular test that's already in the codebase, but that test passes. So what's the issue? |
||||||||||||
| termination_by sizeOf remaining | ||||||||||||
| let stmts' ← processStmts 0 stmts | ||||||||||||
| return ⟨ .Block stmts' label, source ⟩ | ||||||||||||
|
|
@@ -389,7 +393,7 @@ where | |||||||||||
|
|
||||||||||||
| -- Create a block if necessary | ||||||||||||
| if suffixes.length > 0 then | ||||||||||||
| return ⟨ StmtExpr.Block (newAssign :: suffixes) none, source ⟩ | ||||||||||||
| return ⟨ StmtExpr.Block (newAssign :: suffixes) (some "$inlineMe"), source ⟩ | ||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Second occurrence of the
Suggested change
Also: a brief comment here explaining why a sentinel block is needed (i.e. naming the "field-target Assigns may introduce Declare-typed targets that must stay in the enclosing scope" contract) would help the next reader — right now the word
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That a block is needed on this line is because the return type is for single statements, so there is no other solution than to create a block. If you want to see why the "$inlineMe" label is given you can search for that and you fill find an existing comment explaining it. I don't want to duplicate that comment. Do you agree? |
||||||||||||
| else | ||||||||||||
| return newAssign | ||||||||||||
|
|
||||||||||||
|
|
||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -180,6 +180,15 @@ private def runLaurelPasses (options : LaurelTranslateOptions) (program : Progra | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| -- Run resolve after the pass if needed | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if pass.needsResolves then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let result := resolve program (some model) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let newErrors := result.errors.filter fun e => !resolutionErrors.contains e | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !newErrors.isEmpty then | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let newDiags := newErrors.toList.map fun d => | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { d with | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| message := | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| s!"Internal error: resolution after '{pass.name}' introduced this diagnostic: {d.message}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type := .StrataBug } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| emit pass.name "laurel.st" program | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return (program, model, allDiags ++ newDiags, allStats) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
keyboardDrummer marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| program := result.program | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| model := result.model | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| emit pass.name "laurel.st" program | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
181
to
194
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for taking suggestion (b) from the prior thread ( (a) Gating on Concrete suggestion: add a second independent flag, or just run the check unconditionally (it's one extra
Suggested change
This also folds in (c) If you prefer to keep the check gated for cost reasons, file a follow-up to expand coverage — otherwise the comment on
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you reply to what I said before regarding this issue? I feel you're restating earlier comments without progressing the conversation. I said "The check helps improve Laurel developer productivity. I think it's OK if it doesn't run after all passes." and "This code is only run when there is a bug in one of the passes, so it's OK if it does not perform well." |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,8 +15,8 @@ namespace Strata.Laurel | |
| def instanceProcedureProgram := r" | ||
| composite Counter { | ||
| var count: int | ||
| procedure increment(self: Counter) | ||
| // ^^^^^^^^^ error: Instance procedure 'increment' on composite type 'Counter' is not yet supported | ||
| procedure self_increment(self: Counter) | ||
| // ^^^^^^^^^^^^^^ error: Instance procedure 'self_increment' on composite type 'Counter' is not yet supported | ||
| opaque | ||
| { | ||
| self#count := self#count + 1 | ||
|
Comment on lines
17
to
22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This rename from Three levels of fix, in ascending effort:
(1) at minimum is cheap and keeps this PR's scope tight. Also: this rename changed what the test asserts about. The
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you think the stated reason to do (1) describes a realistic scenario? The revert scenario doesn't seem likely enough to warrant the comment to me. I've made issue #1176 for doing (3) |
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a semantic change (Transparent → Opaque with empty postconditions/modifies) but no new test specifically demonstrates the bug that made the change necessary. The three
ConstrainedTypeElimTest.leanhunks just addopaqueto the expected pretty-printed output — they'd pass with or without the change (just with different snapshots).Can you add a
#guard_msgsfixture that fails before this change and passes after? From the PR description "small transparency bug in ConstrainedTypeElim" I'd guess the issue is that a downstream pass (ProcedureInlining? verifier?) was treating the witness procedure as a callable and either inlining its body at witness call-sites or propagating its preconditions — but the exact failure mode isn't documented anywhere in the commit history or the PR body. Without a targeted test, a future pass that flips this back to.Transparentwouldn't regress any snapshot.If no minimal repro is feasible, at minimum a one-line comment here explaining why witness procs must be opaque (e.g. "opaque so ProcedureInlining does not inline
$witness_Tat call-sites; the witness is only meant to establish non-vacuity of the constraint") would keep this intentional.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's my previous comment on this:
It states that this change was made so that tests pass. Why are you asking for adding tests so that this change doesn't get reverted, if the current tests already prevent reverting this change?