A module declared twice at the same level compiles clean and keeps only the last block — the first one's contents are gone with no diagnostic. Same for an enum (or any other declaration) followed by a module of that name.
module m { let a = 5 }
module m { let b = 6 }
from t | filter x == m.a
Error:
╭─[ :3:22 ]
│
3 │ from t | filter x == m.a
│ ─┬─
│ ╰─── Unknown name `m.a`
───╯
m.b resolves fine, so the second block replaced the first rather than merging with it. The reverse of the enum case behaves the same way — enum m { Paid = 0 } followed by module m { let a = 5 } silently drops the enum, while module then enum correctly errors with duplicate declarations of m after #6164.
The cause is the one #6164 fixes for type/enum defs: fold_module_def_stmt calls Module::insert, which overwrites the entry, rather than RootModule::declare, which reports a duplicate. fold_import_def_stmt has the same shape and is covered by #6150.
Only source-level duplicates reach this path — multi-file projects are safe, since insert_stmts_at_path merges a file's statements into an existing module-def stmt of the same name before the resolver runs.
Why the one-line swap to declare doesn't work as-is
Swapping the insert for declare(ident, kind, stmt.id, stmt.annotations) fails 31 lib tests with duplicate declarations of std: Module::new_root pre-seeds a std entry, so the module def that load_std_lib injects collides with the placeholder. A fix needs to let a module def fill a pre-seeded placeholder (and possibly merge into an existing module) while still rejecting genuine source-level duplicates — which is why this is a separate change from #6164 rather than part of it.
A
moduledeclared twice at the same level compiles clean and keeps only the last block — the first one's contents are gone with no diagnostic. Same for anenum(or any other declaration) followed by amoduleof that name.m.bresolves fine, so the second block replaced the first rather than merging with it. The reverse of the enum case behaves the same way —enum m { Paid = 0 }followed bymodule m { let a = 5 }silently drops the enum, whilemodulethenenumcorrectly errors withduplicate declarations of mafter #6164.The cause is the one #6164 fixes for type/enum defs:
fold_module_def_stmtcallsModule::insert, which overwrites the entry, rather thanRootModule::declare, which reports a duplicate.fold_import_def_stmthas the same shape and is covered by #6150.Only source-level duplicates reach this path — multi-file projects are safe, since
insert_stmts_at_pathmerges a file's statements into an existing module-def stmt of the same name before the resolver runs.Why the one-line swap to
declaredoesn't work as-isSwapping the
insertfordeclare(ident, kind, stmt.id, stmt.annotations)fails 31 lib tests withduplicate declarations of std:Module::new_rootpre-seeds astdentry, so the module def thatload_std_libinjects collides with the placeholder. A fix needs to let a module def fill a pre-seeded placeholder (and possibly merge into an existing module) while still rejecting genuine source-level duplicates — which is why this is a separate change from #6164 rather than part of it.