Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions NOW.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

Last updated: 2026-08-08

## typecheck: W456 immutable-array-element error scoped to const ROM (Closes #1925)

- W456 keyed on is_mutable alone, so fn-local let-arrays (inferred-mutability convention, like scalars) raised a hard error on element assignment
- SymbolEntry now carries is_const (module-level const only): const arrays keep the ROM error (unit test preserved), local let-arrays get the scalar-style warning
- tri-net full-spec typecheck sweep: 2 failing -> 0 -- the whole corpus is typecheck-clean for the first time
- Unit suite 1537/1537; FROZEN_HASH resealed

## typecheck: bare non-negative literals are context-polymorphic (Closes #1923)

- infer_expr pinned every integer literal to I32; in u32-dominant specs every 'let x = 0; x = u32_expr;' raised a false 'cannot assign U32 to I32' -- 27 tri-net specs failed typecheck on exactly this
Expand Down
32 changes: 26 additions & 6 deletions bootstrap/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12320,6 +12320,9 @@ struct SymbolEntry {
name: String,
type_info: TypeInfo,
is_mutable: bool,
/// True only for module-level `const` declarations (ROM); fn-local lets
/// follow t27's inferred-mutability convention.
is_const: bool,
}

struct FnEntry {
Expand All @@ -12346,13 +12349,15 @@ pub fn typecheck_ast(ast: &Node) -> TypeCheckResult {
name: child.name.clone(),
type_info: t,
is_mutable: false,
is_const: true,
});
}
NodeKind::StructDecl | NodeKind::EnumDecl => {
symbols.push(SymbolEntry {
name: child.name.clone(),
type_info: TypeInfo::Custom(child.name.clone()),
is_mutable: false,
is_const: false,
});
}
NodeKind::FnDecl => {
Expand Down Expand Up @@ -12442,6 +12447,7 @@ pub fn typecheck_ast(ast: &Node) -> TypeCheckResult {
name: pname.clone(),
type_info: resolve_type_str(ptype),
is_mutable: true,
is_const: false,
});
}
// #920 bug 2: thread an accumulating scope so a StmtLocal declared in
Expand Down Expand Up @@ -12597,7 +12603,8 @@ fn check_stmt(node: &Node, symbols: &mut Vec<SymbolEntry>, fns: &[FnEntry], resu
name: node.name.clone(),
type_info: t,
is_mutable: node.extra_mutable,
});
is_const: false,
});
}
NodeKind::StmtAssign => {
if !node.children.is_empty() {
Expand Down Expand Up @@ -12634,11 +12641,24 @@ fn check_stmt(node: &Node, symbols: &mut Vec<SymbolEntry>, fns: &[FnEntry], resu
} else {
String::new()
};
result.error_count += 1;
result.errors.push(format!(
"error: cannot assign to immutable array element '{}[...]'{}",
base_name, line
));
if sym.is_const {
// W456: a module-level const array is ROM.
result.error_count += 1;
result.errors.push(format!(
"error: cannot assign to immutable array element '{}[...]'{}",
base_name, line
));
} else {
// A fn-local let-array follows the same
// inferred-mutability convention as scalars:
// the backends promote it to var/mut, so this
// is a style warning, not an error.
result.warnings += 1;
result.errors.push(format!(
"warning: element assignment promotes '{}' to mutable{}",
base_name, line
));
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion bootstrap/stage0/FROZEN_HASH
Original file line number Diff line number Diff line change
@@ -1 +1 @@
37b349425f4d6551c495b3357d229b5a6fb2acf6c55712af4d4ecf5271ec5f53
e489784ba9eb56980a9cc0c39c7ff9fcac7029f88aac44133dffed1e30efea2e
9 changes: 8 additions & 1 deletion docs/NOW.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# NOW — typecheck: context-polymorphic integer literals (2026-08-08)
# NOW — typecheck: W456 scoped to const ROM arrays (2026-08-08)

Last updated: 2026-08-08

## typecheck: W456 immutable-array-element error scoped to const ROM (Closes #1925)

- W456 keyed on is_mutable alone, so fn-local let-arrays (inferred-mutability convention, like scalars) raised a hard error on element assignment
- SymbolEntry now carries is_const (module-level const only): const arrays keep the ROM error (unit test preserved), local let-arrays get the scalar-style warning
- tri-net full-spec typecheck sweep: 2 failing -> 0 -- the whole corpus is typecheck-clean for the first time
- Unit suite 1537/1537; FROZEN_HASH resealed

## typecheck: bare non-negative literals are context-polymorphic (Closes #1923)

- infer_expr pinned every integer literal to I32; in u32-dominant specs every 'let x = 0; x = u32_expr;' raised a false 'cannot assign U32 to I32' -- 27 tri-net specs failed typecheck on exactly this
Expand Down
Loading