Fix module visibility check (#6685)

## Description

Fixes #6673.

The module visibility check has been broken for some time. 

In some cases, like the one described in #6673, this has resulted in
modules being mistakenly regarded as inaccessible, even though they
ought to be accessible.

In other cases, private modules were mistakenly regarded as accessible.
For examples see the updated tests in the PR.

The check has now been fixed, and all tests have been updated
accordingly.

This bugfix can be regarded as a breaking change, because some modules
that were deemed accessible before may now be deemed inaccessible and
will require the addition of a `pub` keyword in front of the module
declaration.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] 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](https://github.com/FuelLabs/devrel-requests/issues/new/choose)
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

---------

Co-authored-by: Joshua Batty <joshpbatty@gmail.com>
Co-authored-by: IGI-111 <igi-111@protonmail.com>
This commit is contained in:
jjcnn 2024-11-15 05:59:45 +01:00 committed by GitHub
parent 3b07f499c2
commit 2b6fd7a535
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 140 additions and 121 deletions

View file

@ -2,6 +2,6 @@ library;
mod basic_enum;
mod enum_of_structs;
mod enum_of_enums;
pub mod enum_of_enums;
mod enums_avoid;
mod enums_preferred;

View file

@ -683,6 +683,10 @@ impl Root {
Ok(())
}
/// Check that all accessed modules in the src path are visible from the dst path.
/// If src and dst have a common ancestor module that is private, this privacy modifier is
/// ignored for visibility purposes, since src and dst are both behind that private visibility
/// modifier. Additionally, items in a private module are visible to its immediate parent.
fn check_module_privacy(
&self,
handler: &Handler,
@ -690,20 +694,33 @@ impl Root {
src: &ModulePath,
dst: &ModulePath,
) -> Result<(), ErrorEmitted> {
// you are always allowed to access your ancestor's symbols
if !is_ancestor(src, dst) {
// we don't check the first prefix because direct children are always accessible
for prefix in iter_prefixes(src).skip(1) {
let module = self.module.lookup_submodule(handler, engines, prefix)?;
if module.visibility().is_private() {
let prefix_last = prefix[prefix.len() - 1].clone();
handler.emit_err(CompileError::ImportPrivateModule {
span: prefix_last.span(),
name: prefix_last,
});
}
// Calculate the number of src prefixes whose privacy is ignored.
let mut ignored_prefixes = 0;
// Ignore visibility of common ancestors
ignored_prefixes += src
.iter()
.zip(dst)
.position(|(src_id, dst_id)| src_id != dst_id)
.unwrap_or(dst.len());
// Ignore visibility of direct submodules of the destination module
if dst.len() == ignored_prefixes {
ignored_prefixes += 1;
}
// Check visibility of remaining submodules in the source path
for prefix in iter_prefixes(src).skip(ignored_prefixes) {
let module = self.module.lookup_submodule(handler, engines, prefix)?;
if module.visibility().is_private() {
let prefix_last = prefix[prefix.len() - 1].clone();
handler.emit_err(CompileError::ImportPrivateModule {
span: prefix_last.span(),
name: prefix_last,
});
}
}
Ok(())
}

View file

@ -1,17 +1,17 @@
script;
mod items_1;
mod lib_1; // Aliased item reexports of items_1
mod items_2;
mod lib_2; // Aliased item reexports of items_2
mod items_3;
mod lib_3; // Aliased item reexports of items_3
mod items_4;
mod lib_4_1; // Aliased item reexports of items_4
mod lib_4_2; // Aliased item reexports of lib_4_1
mod items_5;
mod lib_5_1; // Aliased trait reexports from items_5
mod lib_5_2; // Aliased trait reexports from items_5
pub mod items_1;
pub mod lib_1; // Aliased item reexports of items_1
pub mod items_2;
pub mod lib_2; // Aliased item reexports of items_2
pub mod items_3;
pub mod lib_3; // Aliased item reexports of items_3
pub mod items_4;
pub mod lib_4_1; // Aliased item reexports of items_4
pub mod lib_4_2; // Aliased item reexports of lib_4_1
pub mod items_5;
pub mod lib_5_1; // Aliased trait reexports from items_5
pub mod lib_5_2; // Aliased trait reexports from items_5
mod tests; // All tests

View file

@ -1,8 +1,8 @@
script;
mod items_1;
mod lib_1_1; // Item reexports of items_1
mod lib_1_2; // Item reexports of items_1
pub mod items_1;
pub mod lib_1_1; // Item reexports of items_1
pub mod lib_1_2; // Item reexports of items_1
mod tests; // All tests

View file

@ -1,17 +1,17 @@
script;
mod items_1;
mod lib_1; // Item reexports of items_1
mod items_2_1;
mod items_2_2;
mod lib_2; // Item reexports of items_2_1 and items_2_2
mod items_3_1;
mod lib_3; // Item reexports of items_3_1 and items_3_2
mod items_4_1;
mod items_4_2;
mod items_4_3;
mod items_4_4;
mod lib_4; // Item reexports of items_4_1 and items_4_2
pub mod items_1;
pub mod lib_1; // Item reexports of items_1
pub mod items_2_1;
pub mod items_2_2;
pub mod lib_2; // Item reexports of items_2_1 and items_2_2
pub mod items_3_1;
pub mod lib_3; // Item reexports of items_3_1 and items_3_2
pub mod items_4_1;
pub mod items_4_2;
pub mod items_4_3;
pub mod items_4_4;
pub mod lib_4; // Item reexports of items_4_1 and items_4_2
mod tests; // All tests

View file

@ -1,9 +1,9 @@
script;
mod items_1;
mod lib_1; // Item reexports of items_1
mod items_2;
mod lib_2; // Item reexports of items_1
pub mod items_1;
pub mod lib_1; // Item reexports of items_1
pub mod items_2;
pub mod lib_2; // Item reexports of items_1
mod tests; // All tests

View file

@ -1,9 +1,11 @@
script;
mod items_1;
mod lib_1; // Item reexports of items_1
mod items_2;
mod lib_2; // Item reexports of items_1
pub mod items_1;
pub mod lib_1; // Item reexports of items_1
pub mod items_2;
pub mod lib_2; // Item reexports of items_2
pub mod items_3;
pub mod lib_3; // Item reexports of items_3
mod tests; // All tests

View file

@ -1,6 +1,6 @@
script;
mod r#enum;
pub mod r#enum;
mod utils;
fn main() {

View file

@ -1,6 +1,6 @@
script;
mod r#trait;
pub mod r#trait;
mod utils;
use r#trait::Trait;

View file

@ -4,9 +4,9 @@ script;
// but until then, multiple methods with the same name is undefined behavior.
// https://doc.rust-lang.org/rust-by-example/trait/disambiguating.html
mod my_double;
pub mod my_double;
mod my_point;
mod my_triple;
pub mod my_triple;
use my_point::MyPoint;
use my_triple::MyTriple;

View file

@ -1,7 +1,7 @@
script;
mod context;
mod asset;
pub mod asset;
mod utils;
use context::Context;

View file

@ -1,6 +1,6 @@
script;
mod data_structures;
pub mod data_structures;
mod eq_impls;
use eq_impls::*;

View file

@ -1,6 +1,6 @@
script;
mod lib;
pub mod lib;
mod top_level;
mod in_structs;

View file

@ -1,7 +1,7 @@
library;
mod a;
mod b;
pub mod a;
pub mod b;
fn main() -> u32 {
1

View file

@ -1,8 +1,8 @@
library;
mod c;
mod a;
mod b;
pub mod a;
pub mod b;
fn main() -> u32 {
1

View file

@ -1,15 +1,15 @@
script;
mod items_1;
mod lib_1; // Aliased item reexports of items_1
mod items_2;
mod lib_2; // Aliased item reexports of items_2
mod items_3;
mod lib_3_1; // Aliased item reexports of items_3
mod lib_3_2; // Aliased item reexports of lib_3_1
mod items_4;
mod lib_4_1; // Aliased item reexports of items_4
mod lib_4_2; // Aliased item reexports of items_4 with different aliases
pub mod items_1;
pub mod lib_1; // Aliased item reexports of items_1
pub mod items_2;
pub mod lib_2; // Aliased item reexports of items_2
pub mod items_3;
pub mod lib_3_1; // Aliased item reexports of items_3
pub mod lib_3_2; // Aliased item reexports of lib_3_1
pub mod items_4;
pub mod lib_4_1; // Aliased item reexports of items_4
pub mod lib_4_2; // Aliased item reexports of items_4 with different aliases
mod tests; // All tests

View file

@ -1,17 +1,17 @@
script;
mod items_1;
mod lib_1_1; // Item reexports of items_1
mod lib_1_2; // Item reexports of items_1
mod items_2;
mod lib_2_1; // Star reexports of items_2
mod lib_2_2; // Star reexports of items_2
mod items_3;
mod lib_3_1; // Star reexports of items_3
mod lib_3_2; // Item reexports of items_3
mod items_4;
mod lib_4_1; // Item reexports of items_4
mod lib_4_2; // Star reexports of items_4
pub mod items_1;
pub mod lib_1_1; // Item reexports of items_1
pub mod lib_1_2; // Item reexports of items_1
pub mod items_2;
pub mod lib_2_1; // Star reexports of items_2
pub mod lib_2_2; // Star reexports of items_2
pub mod items_3;
pub mod lib_3_1; // Star reexports of items_3
pub mod lib_3_2; // Item reexports of items_3
pub mod items_4;
pub mod lib_4_1; // Item reexports of items_4
pub mod lib_4_2; // Star reexports of items_4
mod tests; // All tests

View file

@ -1,15 +1,15 @@
script;
mod items_1;
mod lib_1_1; // Reexports of items_1
mod lib_1_2; // Reexports of lib_1_1
mod lib_2; // Reexports of std::hash::Hasher, which is not part of the std prelude
mod lib_3_1; // Reexports of std::hash::Hash, which is not part of the std prelude
mod lib_3_2; // Reexports of std::hash::Hash, which is not part of the std prelude
mod lib_4; // Reexport of std::registers::global_gas
mod lib_5; // Reexport of core::codec::*
//mod lib_6_1; // Reexports of std::address::Address from the std prelude
mod lib_6_2; // Reexports of std::address::Address directly from std::address
pub mod items_1;
pub mod lib_1_1; // Reexports of items_1
pub mod lib_1_2; // Reexports of lib_1_1
pub mod lib_2; // Reexports of std::hash::Hasher, which is not part of the std prelude
pub mod lib_3_1; // Reexports of std::hash::Hash, which is not part of the std prelude
pub mod lib_3_2; // Reexports of std::hash::Hash, which is not part of the std prelude
pub mod lib_4; // Reexport of std::registers::global_gas
pub mod lib_5; // Reexport of core::codec::*
//pub mod lib_6_1; // Reexports of std::address::Address from the std prelude
pub mod lib_6_2; // Reexports of std::address::Address directly from std::address
mod tests; // All tests

View file

@ -1,17 +1,17 @@
script;
mod items_1;
mod lib_1; // Item reexports of items_1
mod items_2_1;
mod items_2_2;
mod lib_2; // Item reexports of items_2_1 and items_2_2
mod items_3_1;
mod lib_3; // Item reexports of items_3_1 and items_3_2
mod items_4_1;
mod items_4_2;
mod items_4_3;
mod items_4_4;
mod lib_4; // Item reexports of items_4_1 and items_4_2
pub mod items_1;
pub mod lib_1; // Item reexports of items_1
pub mod items_2_1;
pub mod items_2_2;
pub mod lib_2; // Item reexports of items_2_1 and items_2_2
pub mod items_3_1;
pub mod lib_3; // Item reexports of items_3_1 and items_3_2
pub mod items_4_1;
pub mod items_4_2;
pub mod items_4_3;
pub mod items_4_4;
pub mod lib_4; // Item reexports of items_4_1 and items_4_2
mod tests; // All tests

View file

@ -1,9 +1,9 @@
script;
mod items_1;
mod lib_1; // Item reexports of items_1
mod items_2;
mod lib_2; // Item reexports of items_1
pub mod items_1;
pub mod lib_1; // Item reexports of items_1
pub mod items_2;
pub mod lib_2; // Item reexports of items_1
mod tests; // All tests

View file

@ -1,9 +1,9 @@
script;
mod items_1;
mod lib_1; // Item reexports of items_1
mod items_2;
mod lib_2; // Item reexports of items_2
pub mod items_1;
pub mod lib_1; // Item reexports of items_1
pub mod items_2;
pub mod lib_2; // Item reexports of items_2
mod tests; // All tests

View file

@ -1,11 +1,11 @@
script;
mod items_1;
mod lib_1_1; // Item reexports of items_1
mod lib_1_2; // Item imports without reexport of items_1
mod items_2;
mod lib_2_1; // Item imports without reexport of items_1
mod lib_2_2; // Item reexports of items_1
pub mod items_1;
pub mod lib_1_1; // Item reexports of items_1
pub mod lib_1_2; // Item imports without reexport of items_1
pub mod items_2;
pub mod lib_2_1; // Item imports without reexport of items_1
pub mod lib_2_2; // Item reexports of items_1
mod tests; // All tests

View file

@ -1,6 +1,6 @@
script;
mod r#trait;
pub mod r#trait;
mod foo;
use ::foo::*;

View file

@ -1,6 +1,6 @@
script;
mod data_structures;
pub mod data_structures;
mod tests;
use tests::*;

View file

@ -1,6 +1,6 @@
script;
mod data_structures;
pub mod data_structures;
mod tests;
use tests::*;

View file

@ -1,6 +1,6 @@
contract;
mod data_structures;
pub mod data_structures;
mod interface;
use interface::MyContract;