Skip to content

Duplicate module definitions silently discard the earlier declaration #6166

Description

@prql-bot

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions