174 lines
6.4 KiB
Markdown
174 lines
6.4 KiB
Markdown
# Name Resolution - Callable Sets and Cross-Module Linking Decision
|
|
|
|
Status: Accepted (Implemented)
|
|
Cycle: Initial name-resolution closure pass
|
|
|
|
## 1. Context
|
|
|
|
PBS v1 needs a deterministic rule for how callable names cross module boundaries.
|
|
|
|
The open questions were:
|
|
|
|
- what exactly `import { f } from @project:path;` imports when `f` has multiple exported signatures,
|
|
- whether callable sets from different origins may merge,
|
|
- whether same-name imported callables from different origins are tolerated until callsite analysis,
|
|
- whether local and imported callable names may coexist under one visible function name,
|
|
- and how `mod.barrel` bounds the callable set that becomes importable.
|
|
|
|
Earlier closure already fixed important inputs:
|
|
|
|
- `mod.barrel` is the single source of module visibility,
|
|
- only `pub` names may be imported from another module,
|
|
- local function names and imported function names with the same visible name are already being treated as collisions in this closure pass,
|
|
- and callable identity is determined by callable shape rather than parameter-label spelling alone.
|
|
|
|
## 2. Decision
|
|
|
|
PBS v1 adopts the following baseline for callable sets and cross-module linking:
|
|
|
|
1. `import { f } from @project:path;` imports the exported callable set named `f` from the target module.
|
|
2. The imported callable set for `f` consists only of those overload signatures of `f` that are exported through that module's `mod.barrel`.
|
|
3. Non-exported overloads in the target module do not participate in the imported callable set.
|
|
4. Two imports of the same visible callable name are tolerated when they resolve to the same canonical underlying callable-set origin after module resolution.
|
|
5. Such same-origin duplicate imports are redundant but not errors.
|
|
6. Two imports of the same visible callable name from different canonical origins are rejected immediately.
|
|
7. The program must not wait until a callsite to reject different-origin callable-name collisions.
|
|
8. A module-local function name and an imported function name with the same visible name are rejected immediately.
|
|
9. Automatic merging of callable sets across different origins is not permitted in this closure pass.
|
|
10. Ordinary overload resolution occurs only after one unambiguous visible callable set has already been formed.
|
|
|
|
## 3. Imported Callable Set
|
|
|
|
The meaning of:
|
|
|
|
```pbs
|
|
import { f } from @project:path;
|
|
```
|
|
|
|
is:
|
|
|
|
- resolve the target module,
|
|
- collect the exported callable entries named `f` from that module,
|
|
- form the callable set consisting only of those exported overloads,
|
|
- and make that callable set visible locally under the imported visible name.
|
|
|
|
This import does not:
|
|
|
|
- reach non-exported overloads,
|
|
- merge with hidden module-internal overloads,
|
|
- or import one overload at a time independently from the exported callable name.
|
|
|
|
## 4. Same-Origin Versus Different-Origin Imports
|
|
|
|
### 4.1 Same origin
|
|
|
|
If the same visible callable name is imported more than once and both imports resolve to the same canonical underlying callable-set origin:
|
|
|
|
- the duplicate import is tolerated,
|
|
- but it remains redundant.
|
|
|
|
### 4.2 Different origin
|
|
|
|
If the same visible callable name is imported from different canonical origins:
|
|
|
|
- the program is rejected immediately,
|
|
- and one of the imports must be removed or aliased.
|
|
|
|
The implementation must not:
|
|
|
|
- merge the callable sets,
|
|
- defer the conflict to overload resolution,
|
|
- or allow callsite context to decide which imported origin wins.
|
|
|
|
## 5. Local Versus Imported Callable Names
|
|
|
|
If a module-local function name and an imported function name are the same visible callable name:
|
|
|
|
- the program is rejected immediately,
|
|
- and the implementation must not merge the local and imported callable sets.
|
|
|
|
This preserves deterministic visibility and keeps callable origin traceable.
|
|
|
|
## 6. Barrel Boundary
|
|
|
|
`mod.barrel` defines the exact boundary of the callable set that may cross module boundaries.
|
|
|
|
Rules:
|
|
|
|
- only overloads exported through `mod.barrel` are part of the importable callable set,
|
|
- overloads with the same source-level function name but not exported through `mod.barrel` are invisible to importing modules,
|
|
- and imported callable-set visibility is therefore a direct consequence of the source module's barrel contract.
|
|
|
|
## 7. Overload Resolution Boundary
|
|
|
|
This decision deliberately separates:
|
|
|
|
- callable-set formation,
|
|
- and overload resolution at a callsite.
|
|
|
|
The implementation must first form one unambiguous visible callable set.
|
|
Only then may ordinary overload resolution operate on the candidate signatures of that set.
|
|
|
|
Callsite context must not be used to resolve ambiguity between different imported callable origins.
|
|
|
|
## 8. Invariants
|
|
|
|
- Imported callable visibility is bounded by barrel export.
|
|
- Different callable origins must not merge automatically.
|
|
- Same-origin duplicate imports may be tolerated as redundancy, not as new callable contributions.
|
|
- Local and imported function names do not coexist under one merged visible callable name in this closure pass.
|
|
- Overload resolution happens after visible callable-set formation, not instead of it.
|
|
|
|
## 9. Explicit Non-Decisions
|
|
|
|
This decision record does not yet close:
|
|
|
|
- per-overload import syntax,
|
|
- aliasing policy for callable imports beyond the already-closed generic alias rules,
|
|
- and any lowering consequences in `13. Lowering IRBackend Specification.md`.
|
|
|
|
## 10. Spec Impact
|
|
|
|
This decision should feed at least:
|
|
|
|
- `docs/general/specs/14. Name Resolution and Module Linking Specification.md`
|
|
- `docs/pbs/specs/12. Diagnostics Specification.md`
|
|
- `docs/general/specs/13. Conformance Test Specification.md`
|
|
|
|
It should also constrain future work in:
|
|
|
|
- `docs/pbs/specs/13. Lowering IRBackend Specification.md`
|
|
|
|
## 11. Validation Notes
|
|
|
|
The intended baseline is:
|
|
|
|
- callable imports operate on exported callable names,
|
|
- all exported overloads of that name come together from one module,
|
|
- same-origin duplicate imports are tolerated,
|
|
- different-origin same-name imports are rejected immediately,
|
|
- and local/import callable collisions are also rejected immediately.
|
|
|
|
Illustrative examples:
|
|
|
|
```pbs
|
|
import { f } from @a:m;
|
|
import { f } from @a:m;
|
|
```
|
|
|
|
This is tolerated as redundant same-origin duplication.
|
|
|
|
```pbs
|
|
import { f } from @a:m;
|
|
import { f } from @b:n;
|
|
```
|
|
|
|
This is rejected immediately because the visible callable names match but the canonical origins differ.
|
|
|
|
```pbs
|
|
fn f(a: int) -> int { ... }
|
|
import { f } from @a:m;
|
|
```
|
|
|
|
This is rejected as a local-versus-import callable collision.
|