Refactor the module structure of the namespace module
Description
Partial fix of #5498 .
The namespace module is used to represents the environment of bindings during compilation.
Until now we have treated external libraries as submodules of each module in the program being compiled. This leads to some illegal paths suddenly becoming legal. Additionally, the namespace module suffers from excessive cloning because external modules get cloned each time a new module is compiled. The treatment also means that path resolution must take into account whether a module is external or not.
This PR streamlines the module structure and the paths used in the environment. External modules are now represented separately from the current package, and path resolution is changed to take this separation into account. This allows us to eleminate a significant part of the excessive cloning, though there is still some cloning happening in the AST.
Current state:
- The namespace module builds
- Usage of the namespace module needs to be changed to use the new interface.
Checklist
- [ ] I have linked to any relevant issues.
- [ ] I have commented my code, particularly in hard-to-understand areas.
- [ ] I have updated the documentation where relevant (API docs, the reference, and the Sway book).
- [ ] If my change requires substantial documentation changes, I have requested support from the DevRel team
- [ ] I have added tests that prove my fix is effective or that my feature works.
- [ ] I have added (or requested a maintainer to add) the necessary
Breaking*orNew Featurelabels where relevant. - [ ] I have done my best to ensure that my PR adheres to the Fuel Labs Code Review Standards.
- [ ] I have requested a review from the relevant team or maintainers.
CodSpeed Performance Report
Merging #6291 will improve performances by 22.73%
Comparing jjcnn/move-external-modules-to-root (2feb7e2) with master (37235f2)
Summary
âš¡ 4 improvements
✅ 18 untouched benchmarks
Benchmarks breakdown
| Benchmark | master |
jjcnn/move-external-modules-to-root |
Change | |
|---|---|---|---|---|
| âš¡ | compile |
5.5 s | 4.8 s | +15.44% |
| âš¡ | did_change_with_caching |
527.6 ms | 475.1 ms | +11.06% |
| âš¡ | completion |
23.7 ms | 20.9 ms | +13.36% |
| âš¡ | hover |
4.3 ms | 3.5 ms | +22.73% |
I highly appreciate the effort put into the comprehensive PR description! :pray: :heart:
After going through the PR I'm convinced that the remaining issues (such as not being able to import through dependencies) are high priority follow ups.
Imports work fine I think, as does importing via reexports.
The potential problem is something like this:
- Library
Adeclares a traitTin its root module. The (full and canonical) path toTisA::T. - Library
BhasAa dependency. In its root module it reexportsA::T, thus makingTvisible to any ofB's dependents through the (full but not canonical) pathB::T. - Program
ChasBas a dependency, but notA. It importsTviaBusing the pathB::T, and implements it for a type. Theimplis inserted into the trait map using the canonical path toT, which isA::T. However,A::Tis not a meaningful path when seen fromC, becauseCdoes not haveAas a dependency.
I think of this as a bug with how we (I) implemented reexports, but to be honest I'm not sure how much of a problem it is. There's a risk of a name clash, if C has a dependency called A which does not refer to the same library as the one B depends on, but I'm not even sure the package manager can handle the situation where two different libraries in the dependency graph have the same name.
Hmm, that still seems worthy of a prompt fix, but it's indeed not as bad as I thought.
Nice stuff, left just a minor issue, looks like some pretty decent gains here too :+1: