Area
- Incan Language (syntax/semantics)
- Compiler (frontend/backend/codegen)
- Tooling (CLI/formatter/test runner)
- Runtime / Core crates (stdlib/core/derive)
- Documentation
Summary
Incan 0.3 exposed a recurring class of boundary-sensitive compiler defects: code that works locally changes behavior when the same symbol crosses an import, package, stdlib, decorator, static-initialization, or test-batch boundary.
The core problem appears to be that the compiler still carries several competing identities for the same source item: source spelling, local lowered name, canonical module path, exported/package identity, emitted Rust path, and synthetic test-runner harness identity. Those should be projections of one resolved symbol identity, but today some stages recompute or approximate them with strings and context-sensitive lookup.
This chore tracks a v0.4 architecture pass to make symbol identity first-class and make import/package/test boundaries behavior-preserving instead of semantic fault lines.
Recent motivating examples include public aliases, imported partial presets, decorator metadata, imported statics, package-boundary projections, and directory-batched inline tests.
Scope
- In scope:
- Define a single resolved symbol identity model for functions, methods, types, statics, aliases, partial presets, decorators, and exported package items.
- Make local, imported, package-consumer, stdlib, and test-batch references use the same semantic identity instead of re-looking up by short name.
- Separate source symbol identity from emitted Rust path selection.
- Audit frontend/typechecker, IR lowering, metadata export/import, package manifests, stdlib loading, and test-runner batching for duplicate name-resolution paths.
- Add import-boundary equivalence coverage for aliases, partials, decorators, statics, callable metadata, and inline tests.
- Add package-boundary round-trip coverage for the same surfaces.
- Document the intended symbol identity model for compiler contributors.
- Out of scope:
- Adding new language namespace features unless the audit proves the current model cannot express the intended behavior.
- Reworking all Rust emission architecture unrelated to symbol identity.
- Risks:
- This touches high-traffic compiler paths and can regress default-argument filling, callable metadata, stdlib loading, and package exports if done as a large unverified rewrite.
- The work should be staged behind focused invariants and equivalence tests rather than landed as a single broad refactor.
Plan
- Inventory every place that currently resolves a source item by short string, canonical path string, manifest export string, or emitted Rust path.
- Define the canonical symbol identity structure and projection rules for local source, imports, package exports, stdlib modules, and test harness modules.
- Move frontend/typechecker outputs toward carrying resolved symbol identities for value/type/static/callable references.
- Adjust IR lowering so call/static/type references preserve that identity and projected callable signatures/defaults.
- Adjust metadata export/import so aliases, partials, decorators, and statics round-trip without losing identity or projected surface.
- Adjust codegen so the emitter consumes resolved identities and only maps them to Rust paths; it should not rediscover semantics by bare name.
- Add equivalence tests comparing focused-file, directory-batch, package-producer, package-consumer, and stdlib-import behavior.
- Update contributor documentation with the rule: import boundaries may affect visibility and initialization timing, but not semantic identity.
Done when
- Local and imported references to the same exported symbol use the same semantic identity and projected signature.
- Aliases, partial presets, decorators, statics, callable metadata, and public package exports pass focused and imported/package-boundary equivalence tests.
incan test file.incn and incan test directory/ agree for inline-test symbol identity unless there is an explicit documented visibility difference.
- The emitter no longer performs semantic lookup by short name when a resolved symbol identity should already be available.
- Compiler contributor docs describe the identity model and the boundary invariants.
- The v0.4 release notes can point to this work as a deliberate reduction in import-boundary behavioral drift.
Area
Summary
Incan 0.3 exposed a recurring class of boundary-sensitive compiler defects: code that works locally changes behavior when the same symbol crosses an import, package, stdlib, decorator, static-initialization, or test-batch boundary.
The core problem appears to be that the compiler still carries several competing identities for the same source item: source spelling, local lowered name, canonical module path, exported/package identity, emitted Rust path, and synthetic test-runner harness identity. Those should be projections of one resolved symbol identity, but today some stages recompute or approximate them with strings and context-sensitive lookup.
This chore tracks a v0.4 architecture pass to make symbol identity first-class and make import/package/test boundaries behavior-preserving instead of semantic fault lines.
Recent motivating examples include public aliases, imported partial presets, decorator metadata, imported statics, package-boundary projections, and directory-batched inline tests.
Scope
Plan
Done when
incan test file.incnandincan test directory/agree for inline-test symbol identity unless there is an explicit documented visibility difference.