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.
35 lines
1.4 KiB
Bash
Executable file
35 lines
1.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
|
|
# The test covers the behavior of transitively importing multiple modules
|
|
# that have a definition with the same name.
|
|
|
|
# The native symbols Lean emits are prefixed with a package identifier
|
|
# received from Lake. Thus, symbol clashes should not occur between packages.
|
|
# However, they can still occur within them.
|
|
|
|
# Related Issues:
|
|
# https://github.com/leanprover/lean4/issues/222
|
|
|
|
# In the example in this directory, packages `fooA` and `fooB` both define `foo`.
|
|
# `useA` privately imports and uses `fooA`, and `useB` private imports and uses
|
|
# `fooB`. The executable `TestUse` then imports and uses `useA` and `useB`.
|
|
|
|
# Similarly, modules `Test.BarA` and `Test.BarB` both define `bar`.
|
|
# Modules `UseBarA` and `UseBarB` use them (privately), and `TestLocalUse`
|
|
# imports both.
|
|
|
|
source ../../lake/tests/common.sh
|
|
|
|
./clean.sh
|
|
|
|
# Test the behavior when multiple copies of the same definition (`foo`)
|
|
# are seen by Lean (e.g., via importing two modules which define them).
|
|
test_err "environment already contains 'foo'" build TestFoo
|
|
|
|
# Test the behavior when multiple copies of the same definition (`foo`) exist
|
|
# in different packages but are not visible to any one module.
|
|
test_out "fooA; fooB" exe TestUse
|
|
|
|
# Test the behavior when multiple copies of the same definition (`foo`) exist
|
|
# in the same package but are not visible to any one module.
|
|
test_err "lp_test_bar" build TestLocalUse
|