Stdlib seal (prelude immutability)¶
Phase: 4s (security). Status: implemented in lic check / lic build.
Goal¶
User modules cannot redefine or hijack names owned by the language prelude or shipped std/ modules. This blocks decorator hijack, builtin substitution, and duplicate top-level confusion.
Rules¶
- Prelude types (
int,list,dict,tuple,Option,simd, …) — no usertypealias with the same unqualified name. - Prelude procs (
echo) — no userdefwith the same name. - Std module exports — symbols defined in
std/**/*.li(e.g.__execution_decorators_doc) cannot be redefined in user code. - Reserved decorators —
parallel,cpu, … remain blocked fordecorator def(see execution-decorators spec); shared table incompiler/types/prelude.cpp. - Duplicates — two top-level
defortypewith the same name in one file →duplicate_definition.
Diagnostics¶
| Code | Meaning |
|---|---|
stdlib_symbol_shadow: NAME | User definition clashes with prelude or std export |
duplicate_definition: NAME | Repeated top-level definition |
reserved_name: NAME | User decorator def steals std decorator name |
Implementation¶
li::check_stdlib_sealin compiler/types/prelude.cpp, called from compiler/lic/main.cpp on the entry module and from compiler/types/import_resolve.cpp for each resolved import.- Manifest sync: scripts/gen-stdlib-manifest.sh.
Tests¶
li-tests/stdlib_seal/ — wired in CI security and master-plan gates.
Import graph (4s closed slice)¶
check_stdlib_sealruns on the entry module and on every file loaded byresolve_imports(load_module_recursiveinimport_resolve.cpp).- Cyclic imports fail with
import_cycle: <path>(li-tests/modules/import_cycle_a.li).
Future (8a)¶
Imported std/* bindings are read-only in the importer; re-export cannot override sealed names.