mirror of
https://github.com/leanprover/lean4.git
synced 2026-03-17 18:34:06 +00:00
fix: symbol clashes between packages (#11082)
This PR prevents symbol clashes between (non-`@[export]`) definitions from different Lean packages. Previously, if two modules define a function with the same name and were transitively imported (even privately) by some downstream module, linking would fail due to a symbol clash. Similarly, if a user defined a symbol with the same name as one in the `Lean` library, Lean would use the core symbol even if one did not import `Lean`. This is solved by changing Lean's name mangling algorithm to include an optional package identifier. This identifier is provided by Lake via `--setup` when building a module. This information is weaved through the elaborator, interpreter, and compiler via a persistent environment extension that associates modules with their package identifier. With a package identifier, standard symbols have the form `lp_<pkg-id>_<mangled-def>`. Without one, the old scheme is used (i.e., `l_<mangled-def>`). Module initializers are also prefixed with package identifier (if any). For example, the initializer for a module `Foo` in a package `test` is now `initialize_test_Foo` (instead of `initialize_Foo`). Lake's default for native library names has also been adjusted accordingly, so that libraries can still, by default, be used as plugins. Thus, the default library name of the `lean_lib Foo` in `package test` will now be `libtest_Foo`. When using Lake to build the Lean core (i.e., `bootstrap = true`), no package identifier will be used. Thus, definitions in user packages can never have symbol clashes with core. Closes #222.
This commit is contained in:
@@ -129,8 +129,7 @@ For all other modules imported by `lean`, the initializer is run without `builti
|
||||
Thus `[init]` functions are run iff their module is imported, regardless of whether they have native code available or not, while `[builtin_init]` functions are only run for native executable or plugins, regardless of whether their module is imported or not.
|
||||
`lean` uses built-in initializers for e.g. registering basic parsers that should be available even without importing their module (which is necessary for bootstrapping).
|
||||
|
||||
The initializer for module `A.B` is called `initialize_A_B` and will automatically initialize any imported modules.
|
||||
Module initializers are idempotent (when run with the same `builtin` flag), but not thread-safe.
|
||||
The initializer for module `A.B` in a package `foo` is called `initialize_foo_A_B`. For modules in the Lean core (e.g., `Init.Prelude`), the initializer is called `initialize_Init_Prelude`. Module initializers will automatically initialize any imported modules. They are also idempotent (when run with the same `builtin` flag), but not thread-safe.
|
||||
|
||||
**Important for process-related functionality**: If your application needs to use process-related functions from libuv, such as `Std.Internal.IO.Process.getProcessTitle` and `Std.Internal.IO.Process.setProcessTitle`, you must call `lean_setup_args(argc, argv)` (which returns a potentially modified `argv` that must be used in place of the original) **before** calling `lean_initialize()` or `lean_initialize_runtime_module()`. This sets up process handling capabilities correctly, which is essential for certain system-level operations that Lean's runtime may depend on.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user