Skip to content

error[20605] "several modules with the same name": module identity is spelled-path-sensitive (relative root vs mount-routed absolute require) #3422

Description

@borisbat

Repro (on master, from the repo root)

daslang modules/dasPEG/peg/peg.das
error[20605]: several modules with the same name 'detail/colors'
namely 'modules/dasPEG/peg/detail/colors.das' and 'D:/Work/daScript/modules/dasPEG/peg/detail/colors.das'
	from modules/dasPEG/peg/peg.das

The same command with an absolute path to peg.das compiles fine. Same file, two spellings.

Mechanism

Require resolution inherits the parent file's spelled name instead of canonicalizing, and the module registry compares files by spelled path string:

  1. daslang modules/dasPEG/peg/peg.das — the root file registers under the relative string as typed.
  2. peg.das:10 require peg/parse_macro — not a same-dir file, resolves through the module search path (das_root scan) → absolute <root>/modules/dasPEG/peg/parse_macro.das.
  3. parse_macro.das:19 require detail/colors — same-dir relative to parse_macro's spelled name → registers colors.das under the absolute path.
  4. peg.das:11 require detail/colors — same-dir relative to peg.das's spelled name → resolves the same file under the relative path.

Two "distinct" files now both claim module name detail/colors → 20605.

General shape: any root file compiled by a relative path whose same-directory sibling is also reachable through a mount-routed require chain trips this.

How it surfaced

The CI changed-files lint gate feeds git diff relative paths; the moment peg.das entered a PR's changed set the gate went red (#3420). Worked around at the tool boundary — utils/lint/main.das now absolutizes its positional inputs (2f52e76) — but the compiler bug remains for any embedder/CLI passing relative paths.

Fix direction

Canonicalize for module identity (a normalizeFileName at require-resolution time, used only for the duplicate check / registry key). The blunt alternative — canonicalizing every registered name — would flip error messages and LineInfo to absolute paths tree-wide and could churn AOT hashes, so identity-only comparison looks like the safer shape.

🤖 Generated with Claude Code

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