You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
A global.X assignment marks a same-named shadowing local as initialized, so E0381 never fires (exit 0) #2001
A global./this. assignment counts as initializing a block local that has the same name and shadows that global. So E0381 never fires for a later read of the uninitialized local, and the transpiler exits 0.
Found while checking PR #1993 (#1290) against the cnext-way "check everywhere" rule. #1993 fixes the same mistake in 1.3's modification analysis (AssignmentTargetExtractor). InitializationAnalyzer reads the target the same way and is not touched by that PR (no diff against main).
Reproduction (run on fix/1290-parameter-shadows-global @ 119f5e2; InitializationAnalyzer.ts is identical to main)
struct Point {
u32 x;
u32 y;
}
Point pt <- {x: 1, y: 2};
u32 shadowUninit() {
Point pt;
global.pt.x <- 5;
u32 r <- pt.x;
return r;
}
Control. The same function with the local named other (Point other; global.pt.x <- 5; u32 r <- other.x;) is rejected:
error[E0381]: use of uninitialized variable 'other.x'
So the only difference is that the local and the global share a spelling.
Cause
InitializationAnalyzer.enterAssignmentStatement takes targetCtx.IDENTIFIER()?.getText() without checking targetCtx.GLOBAL() / THIS(), then records the assignment against whatever that spelling resolves to: the shadowing local. _collectAssignmentsInStatement does the same (its comment says "Both bare identifier and this.member use the same IDENTIFIER token").
Definition of done
A global./this. assignment target never marks a local as initialized. Execution/error fixture, in C and C++, with the different-name control beside it.
Evidence (PR fix(#1290): a parameter that shadows a file-scope name moves like a local #1993, bd4f034d5): tests/bugs/issue-2001-qualified-write-initializes-local/ -- global-write-local-shadow and this-write-local-shadow now report E0381; qualified-write-control (execution, C+C++ parity) shows the same writes compile and run when nothing is uninitialized. The different-name control (other.x) is the existing E0381 behavior. Same commit also covers two related arms in the scope-member pre-scan: global-write-scope-member (global.count no longer initializes member count) and local-write-scope-member (a bare write to a shadowing local no longer initializes the member).
The fixture fails if the spelling match is put back (mutation-checked).
Evidence (bd4f034d5): disabling the qualified-target return in enterAssignmentStatement fails global-write-local-shadow, this-write-local-shadow and global-write-scope-member ("Expected errors but transpilation succeeded"); dropping the pre-scan's global. skip fails global-write-scope-member; dropping its local-binding check fails local-write-scope-member. Restored: 5/5 pass.
Activity
fix(#2001): a global./this. write never initializes a same-named local
fix(#2003,#2004): initialization binds through 1.4; one statement wal…