Skip to main content
Next (unreleased) · docs dcb1384b · core c3a5528b · built 2026-10-27 12:07 UTC

Construction finds module-level values and their schemes by name

Limitation​

Construction resolves locals, nested generic functions, struct fields, types, aspects and top-level declarations by identity. Module-level values (functions, builtins, top-level let/var) are still found by name: ConstructCtx::module_values and module_fn_decls are seeded from the inference output SchemeEnv, a HashMap<String, TypeScheme>, and a callee reads its scheme from it by spelling. The two maps are exempted in check_no_semantic_name_lookup.py's scan with this record as the retirement condition.

The blocker is a path callee such as List::new: path normalization stamps no symbol on a Type::method path, so the use site has no identity to look the scheme up by. Measured over the integration corpus, about 15,000 of the SchemeEnv entries built are such joined keys, against imported names (~58%) and std::core items (~40%), which can carry an id from where they are produced.

Impact​

Internal. A module-level value whose spelling is shadowed or aliased is resolved correctly today by the name resolver's own tables before construction; the name-keyed read happens after that, on a spelling the resolver already accepted.

Affects​

Resolution​

Resolved by metel-core#1604 (PRs #1608, #1609, #1610). Type::member static constructors are read from the registry by the type's SymbolId and the member name (List::new was the only joined key construction ever read: 150 reads over the integration corpus, all List::new/List::from). The inference output now also yields the module's schemes keyed by the declaration they belong to (SchemeIds): a function or closure under the binder recorded for its declaration span, an import or std::core entry under the SymbolId its name denotes in the module's scope. ConstructCtx::module_values and module_fn_decls are keyed by BindingId, a use site reaches a scheme through the binding the identity pass resolved it to, and the runtime TypeCtx carries the same table, so a reconstructed generic body reads it too. The two exemptions in check_no_semantic_name_lookup.py's scan are gone, and the name-keyed scheme_env is no longer carried past inference's own export step. The path normalization step the original plan named turned out unnecessary: an impl-method symbol embeds the impl's type arguments, which a written Type::method path cannot reconstruct, and the registry already keys methods by owner identity.