Problem
pslua records how local bindings inside a Let resolve — sequentially, like Scheme's let* — as a GHC-style Note [Sequential scoping of Let bindings] in lib/Language/PureScript/Backend/IR/Types.hs. A Note is a named block comment that other sites reference by name instead of restating the rationale.
This Note is load-bearing rather than descriptive. It states that every traversal walking under Let binders while duplicate names can still occur must implement the convention, and that they must all agree — then enumerates the implementors:
* 'countFreeRefs' threads the scope through the groupings left to right;
* 'alphaEq' resolves names to binder positions the same way, so it
stays correct on shadowed input;
* the well-scopedness lint
('Language.PureScript.Backend.IR.Linter.unboundLocals' — ...)
tracks bound names the same way;
* 'qualifyTopRefs' (Linker, ahead of the optimizer pipeline) decides
whether a local reference escapes to a top-level binding by
threading bound names the same way;
* 'Language.PureScript.Backend.IR.Uniquify.uniquifyNamesInExpr'
resolves names to fresh, site-wide unique names the same way, ...
Two further traversals now implement the same rule and appear nowhere in that list:
Both reference the Note from their own Haddock, so the link runs one way only: a reader standing at the Note cannot see them. Since the list reads as exhaustive ("they must all agree"), the omission actively misleads — the next change to a scoping-sensitive traversal consults the Note, finds five implementors, and misses two.
This family has now produced three defects: #37, where an optimizer traversal resolved a sibling-bound reference against the wrong binder, DCE deleted the "unused" binder, and codegen emitted a dangling Lua variable (the Note cites it); then #345; then #349. The Note is the artifact meant to prevent the fourth.
Approach
Add the two missing implementors to the Note's bullet list, each with a one-clause statement of what it threads, in the style of the existing entries.
Also attach the obligation explicitly: a traversal that implements this convention must be listed here. Today the list is only implicitly exhaustive, which is why two additions slipped past it — stating the rule makes the omission a reviewable defect rather than an oversight.
The change edits a single comment block, so it is small enough to ride along in the next PR that touches a scoping-sensitive traversal instead of taking a cycle of its own.
Prerequisites / Relations
None. Follows #345 and #349, whose fixes created the omission.
Verification / Measurement
Every site whose Haddock claims to implement the convention appears in the Note's list. Documentation only — behaviour is already pinned by the golden test test/ps/src/Golden/Issue37/Test.purs and the "Let sequential (let*) scoping" tests, so this adds no test of its own.
Problem
psluarecords how local bindings inside aLetresolve — sequentially, like Scheme'slet*— as a GHC-styleNote [Sequential scoping of Let bindings]inlib/Language/PureScript/Backend/IR/Types.hs. ANoteis a named block comment that other sites reference by name instead of restating the rationale.This Note is load-bearing rather than descriptive. It states that every traversal walking under
Letbinders while duplicate names can still occur must implement the convention, and that they must all agree — then enumerates the implementors:Two further traversals now implement the same rule and appear nowhere in that list:
freshenBinders(Language.PureScript.Backend.IR.Optimizer), the helper that renames aLet's binders when a rewrite needs fresh names — corrected in freshenBinders renames a free reference sharing its Standalone Let binder's name #345 to walk the binders in scope order;alphaKey, the function that computes the alpha-equivalence key used by common-subexpression elimination — corrected in CSE alphaKey hoists a Let's binders into its rename map, missing alpha-equivalent keys #349 to key aLet's binders in scope order.Both reference the Note from their own Haddock, so the link runs one way only: a reader standing at the Note cannot see them. Since the list reads as exhaustive ("they must all agree"), the omission actively misleads — the next change to a scoping-sensitive traversal consults the Note, finds five implementors, and misses two.
This family has now produced three defects: #37, where an optimizer traversal resolved a sibling-bound reference against the wrong binder, DCE deleted the "unused" binder, and codegen emitted a dangling Lua variable (the Note cites it); then #345; then #349. The Note is the artifact meant to prevent the fourth.
Approach
Add the two missing implementors to the Note's bullet list, each with a one-clause statement of what it threads, in the style of the existing entries.
Also attach the obligation explicitly: a traversal that implements this convention must be listed here. Today the list is only implicitly exhaustive, which is why two additions slipped past it — stating the rule makes the omission a reviewable defect rather than an oversight.
The change edits a single comment block, so it is small enough to ride along in the next PR that touches a scoping-sensitive traversal instead of taking a cycle of its own.
Prerequisites / Relations
None. Follows #345 and #349, whose fixes created the omission.
Verification / Measurement
Every site whose Haddock claims to implement the convention appears in the Note's list. Documentation only — behaviour is already pinned by the golden test
test/ps/src/Golden/Issue37/Test.pursand the "Let sequential (let*) scoping" tests, so this adds no test of its own.