Skip to content

Commit

Permalink
Auto merge of rust-lang#13602 - lowr:fix/nameres-transitive-visibilit…
Browse files Browse the repository at this point in the history
…y, r=Veykril

fix: check visibility of each path segment

Upon path resolution, we have not been checking if every def pointed to by each segment of the path is visible from the original module. This leads to incorrect import resolutions, in particular when one uses glob imports and names collide.

There is decent amount of changes in this PR because:
- some of our tests were not correct in terms of visibility
  - I left several basic nameres tests as-is (with expect test updated) since I thought it would be nice to ensure we don't resolve defs that are not visible.
- `fix_visibility` assist relied on `Semantics::resolve_path()`, which uses the name resolution procedure I'm fixing and wouldn't be able to "see through" the items with strict visibility with this patch

The first commit is the gist of the fix itself.

Fixes rust-lang#10991
Fixes rust-lang#11473
Fixes rust-lang#13252
  • Loading branch information
bors committed Nov 11, 2022
2 parents 6f313ce + 19306c0 commit 57cc2a6
Show file tree
Hide file tree
Showing 16 changed files with 145 additions and 99 deletions.
4 changes: 4 additions & 0 deletions crates/hir-def/src/nameres/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ impl Import {

#[derive(Debug, Eq, PartialEq)]
struct ImportDirective {
/// The module this import directive is in.
module_id: LocalModuleId,
import: Import,
status: PartialResolvedImport,
Expand Down Expand Up @@ -963,8 +964,10 @@ impl DefCollector<'_> {

fn update(
&mut self,
// The module for which `resolutions` have been resolve
module_id: LocalModuleId,
resolutions: &[(Option<Name>, PerNs)],
// Visibility this import will have
vis: Visibility,
import_type: ImportType,
) {
Expand All @@ -974,6 +977,7 @@ impl DefCollector<'_> {

fn update_recursive(
&mut self,
// The module for which `resolutions` have been resolve
module_id: LocalModuleId,
resolutions: &[(Option<Name>, PerNs)],
// All resolutions are imported with this visibility; the visibilities in
Expand Down
7 changes: 7 additions & 0 deletions crates/hir-def/src/nameres/path_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ impl DefMap {
pub(crate) fn resolve_visibility(
&self,
db: &dyn DefDatabase,
// module to import to
original_module: LocalModuleId,
// pub(path)
// ^^^^ this
visibility: &RawVisibility,
) -> Option<Visibility> {
let mut vis = match visibility {
Expand Down Expand Up @@ -115,6 +118,7 @@ impl DefMap {
&self,
db: &dyn DefDatabase,
mode: ResolveMode,
// module to import to
mut original_module: LocalModuleId,
path: &ModPath,
shadow: BuiltinShadowMode,
Expand Down Expand Up @@ -361,6 +365,9 @@ impl DefMap {
);
}
};

curr_per_ns = curr_per_ns
.filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
}

ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
Expand Down
6 changes: 3 additions & 3 deletions crates/hir-def/src/nameres/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ extern {
"#,
expect![[r#"
crate
E: t
E: _
S: t v
V: t v
V: _
foo: t
crate::foo
Expand Down Expand Up @@ -307,7 +307,7 @@ pub struct FromLib;
Bar: t v
crate::foo
Bar: t v
Bar: _
FromLib: t v
"#]],
);
Expand Down
33 changes: 32 additions & 1 deletion crates/hir-def/src/nameres/tests/globs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ use foo::*;
use foo::bar::*;
//- /foo/mod.rs
mod bar;
pub mod bar;
fn Foo() {};
pub struct Foo {};
Expand All @@ -132,6 +132,7 @@ pub(crate) struct PubCrateStruct;
crate
Foo: t
PubCrateStruct: t v
bar: t
foo: t
crate::foo
Expand Down Expand Up @@ -336,3 +337,33 @@ mod d {
"#]],
);
}

#[test]
fn glob_name_collision_check_visibility() {
check(
r#"
mod event {
mod serenity {
pub fn Event() {}
}
use serenity::*;
pub struct Event {}
}
use event::Event;
"#,
expect![[r#"
crate
Event: t
event: t
crate::event
Event: t v
serenity: t
crate::event::serenity
Event: v
"#]],
);
}
2 changes: 1 addition & 1 deletion crates/hir-def/src/nameres/tests/mod_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
//- /main.rs
mod foo {
#[path = "baz.rs"]
mod bar;
pub mod bar;
}
use self::foo::bar::Baz;
Expand Down
40 changes: 20 additions & 20 deletions crates/hir-ty/src/tests/method_resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,16 @@ fn infer_associated_method_with_modules() {
check_infer(
r#"
mod a {
struct A;
pub struct A;
impl A { pub fn thing() -> A { A {} }}
}
mod b {
struct B;
pub struct B;
impl B { pub fn thing() -> u32 { 99 }}
mod c {
struct C;
pub mod c {
pub struct C;
impl C { pub fn thing() -> C { C {} }}
}
}
Expand All @@ -186,22 +186,22 @@ fn infer_associated_method_with_modules() {
}
"#,
expect![[r#"
55..63 '{ A {} }': A
57..61 'A {}': A
125..131 '{ 99 }': u32
127..129 '99': u32
201..209 '{ C {} }': C
203..207 'C {}': C
240..324 '{ ...g(); }': ()
250..251 'x': A
254..265 'a::A::thing': fn thing() -> A
254..267 'a::A::thing()': A
277..278 'y': u32
281..292 'b::B::thing': fn thing() -> u32
281..294 'b::B::thing()': u32
304..305 'z': C
308..319 'c::C::thing': fn thing() -> C
308..321 'c::C::thing()': C
59..67 '{ A {} }': A
61..65 'A {}': A
133..139 '{ 99 }': u32
135..137 '99': u32
217..225 '{ C {} }': C
219..223 'C {}': C
256..340 '{ ...g(); }': ()
266..267 'x': A
270..281 'a::A::thing': fn thing() -> A
270..283 'a::A::thing()': A
293..294 'y': u32
297..308 'b::B::thing': fn thing() -> u32
297..310 'b::B::thing()': u32
320..321 'z': C
324..335 'c::C::thing': fn thing() -> C
324..337 'c::C::thing()': C
"#]],
);
}
Expand Down
18 changes: 9 additions & 9 deletions crates/hir-ty/src/tests/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ fn infer_paths() {
fn a() -> u32 { 1 }
mod b {
fn c() -> u32 { 1 }
pub fn c() -> u32 { 1 }
}
fn test() {
Expand All @@ -225,13 +225,13 @@ fn test() {
expect![[r#"
14..19 '{ 1 }': u32
16..17 '1': u32
47..52 '{ 1 }': u32
49..50 '1': u32
66..90 '{ ...c(); }': ()
72..73 'a': fn a() -> u32
72..75 'a()': u32
81..85 'b::c': fn c() -> u32
81..87 'b::c()': u32
51..56 '{ 1 }': u32
53..54 '1': u32
70..94 '{ ...c(); }': ()
76..77 'a': fn a() -> u32
76..79 'a()': u32
85..89 'b::c': fn c() -> u32
85..91 'b::c()': u32
"#]],
);
}
Expand Down Expand Up @@ -1856,7 +1856,7 @@ fn not_shadowing_module_by_primitive() {
check_types(
r#"
//- /str.rs
fn foo() -> u32 {0}
pub fn foo() -> u32 {0}
//- /main.rs
mod str;
Expand Down
36 changes: 18 additions & 18 deletions crates/hir-ty/src/tests/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1706,7 +1706,7 @@ fn where_clause_trait_in_scope_for_method_resolution() {
check_types(
r#"
mod foo {
trait Trait {
pub trait Trait {
fn foo(&self) -> u32 { 0 }
}
}
Expand All @@ -1723,7 +1723,7 @@ fn super_trait_method_resolution() {
check_infer(
r#"
mod foo {
trait SuperTrait {
pub trait SuperTrait {
fn foo(&self) -> u32 {}
}
}
Expand All @@ -1735,15 +1735,15 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
y.foo();
}"#,
expect![[r#"
49..53 'self': &Self
62..64 '{}': u32
181..182 'x': T
187..188 'y': U
193..222 '{ ...o(); }': ()
199..200 'x': T
199..206 'x.foo()': u32
212..213 'y': U
212..219 'y.foo()': u32
53..57 'self': &Self
66..68 '{}': u32
185..186 'x': T
191..192 'y': U
197..226 '{ ...o(); }': ()
203..204 'x': T
203..210 'x.foo()': u32
216..217 'y': U
216..223 'y.foo()': u32
"#]],
);
}
Expand All @@ -1754,7 +1754,7 @@ fn super_trait_impl_trait_method_resolution() {
r#"
//- minicore: sized
mod foo {
trait SuperTrait {
pub trait SuperTrait {
fn foo(&self) -> u32 {}
}
}
Expand All @@ -1764,12 +1764,12 @@ fn test(x: &impl Trait1) {
x.foo();
}"#,
expect![[r#"
49..53 'self': &Self
62..64 '{}': u32
115..116 'x': &impl Trait1
132..148 '{ ...o(); }': ()
138..139 'x': &impl Trait1
138..145 'x.foo()': u32
53..57 'self': &Self
66..68 '{}': u32
119..120 'x': &impl Trait1
136..152 '{ ...o(); }': ()
142..143 'x': &impl Trait1
142..149 'x.foo()': u32
"#]],
);
}
Expand Down
Loading

0 comments on commit 57cc2a6

Please sign in to comment.