diff --git a/src/analyzer/mod.rs b/src/analyzer/mod.rs index 918b35d..337af9b 100644 --- a/src/analyzer/mod.rs +++ b/src/analyzer/mod.rs @@ -797,6 +797,11 @@ impl Analyzer { *span, )); } + } else { + // Assigning to an undeclared name is an + // error — the lowering would otherwise + // silently synthesize a VarId for it. + self.emit_undefined_var(name, *span); } } LValue::ArrayIndex(name, idx) => { @@ -808,6 +813,8 @@ impl Analyzer { *span, )); } + } else { + self.emit_undefined_var(name, *span); } // Indexing an array counts as a read of the array, // and the index expression itself may contain reads. diff --git a/src/analyzer/tests.rs b/src/analyzer/tests.rs index 4b2a40b..a4932a4 100644 --- a/src/analyzer/tests.rs +++ b/src/analyzer/tests.rs @@ -360,6 +360,23 @@ fn analyze_unknown_struct_type_errors() { ); } +#[test] +fn analyze_assign_to_undefined_var_errors() { + // Assigning to an undeclared variable must produce E0502 + // rather than silently creating the variable. + let errors = analyze_errors( + r#" + game "Test" { mapper: NROM } + on frame { nope = 5 } + start Main + "#, + ); + assert!( + errors.contains(&ErrorCode::E0502), + "assignment to undefined var should produce E0502, got: {errors:?}" + ); +} + #[test] fn analyze_enum_variants_as_constants() { let result = analyze_ok(