Skip to content

Commit 57cc2a6

Browse files
committed
Auto merge of #13602 - lowr:fix/nameres-transitive-visibility, 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 #10991 Fixes #11473 Fixes #13252
2 parents 6f313ce + 19306c0 commit 57cc2a6

File tree

16 files changed

+145
-99
lines changed

16 files changed

+145
-99
lines changed

crates/hir-def/src/nameres/collector.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ impl Import {
212212

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

964965
fn update(
965966
&mut self,
967+
// The module for which `resolutions` have been resolve
966968
module_id: LocalModuleId,
967969
resolutions: &[(Option<Name>, PerNs)],
970+
// Visibility this import will have
968971
vis: Visibility,
969972
import_type: ImportType,
970973
) {
@@ -974,6 +977,7 @@ impl DefCollector<'_> {
974977

975978
fn update_recursive(
976979
&mut self,
980+
// The module for which `resolutions` have been resolve
977981
module_id: LocalModuleId,
978982
resolutions: &[(Option<Name>, PerNs)],
979983
// All resolutions are imported with this visibility; the visibilities in

crates/hir-def/src/nameres/path_resolution.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ impl DefMap {
7373
pub(crate) fn resolve_visibility(
7474
&self,
7575
db: &dyn DefDatabase,
76+
// module to import to
7677
original_module: LocalModuleId,
78+
// pub(path)
79+
// ^^^^ this
7780
visibility: &RawVisibility,
7881
) -> Option<Visibility> {
7982
let mut vis = match visibility {
@@ -115,6 +118,7 @@ impl DefMap {
115118
&self,
116119
db: &dyn DefDatabase,
117120
mode: ResolveMode,
121+
// module to import to
118122
mut original_module: LocalModuleId,
119123
path: &ModPath,
120124
shadow: BuiltinShadowMode,
@@ -361,6 +365,9 @@ impl DefMap {
361365
);
362366
}
363367
};
368+
369+
curr_per_ns = curr_per_ns
370+
.filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
364371
}
365372

366373
ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))

crates/hir-def/src/nameres/tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,9 @@ extern {
5858
"#,
5959
expect![[r#"
6060
crate
61-
E: t
61+
E: _
6262
S: t v
63-
V: t v
63+
V: _
6464
foo: t
6565
6666
crate::foo
@@ -307,7 +307,7 @@ pub struct FromLib;
307307
Bar: t v
308308
309309
crate::foo
310-
Bar: t v
310+
Bar: _
311311
FromLib: t v
312312
"#]],
313313
);

crates/hir-def/src/nameres/tests/globs.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ use foo::*;
119119
use foo::bar::*;
120120
121121
//- /foo/mod.rs
122-
mod bar;
122+
pub mod bar;
123123
fn Foo() {};
124124
pub struct Foo {};
125125
@@ -132,6 +132,7 @@ pub(crate) struct PubCrateStruct;
132132
crate
133133
Foo: t
134134
PubCrateStruct: t v
135+
bar: t
135136
foo: t
136137
137138
crate::foo
@@ -336,3 +337,33 @@ mod d {
336337
"#]],
337338
);
338339
}
340+
341+
#[test]
342+
fn glob_name_collision_check_visibility() {
343+
check(
344+
r#"
345+
mod event {
346+
mod serenity {
347+
pub fn Event() {}
348+
}
349+
use serenity::*;
350+
351+
pub struct Event {}
352+
}
353+
354+
use event::Event;
355+
"#,
356+
expect![[r#"
357+
crate
358+
Event: t
359+
event: t
360+
361+
crate::event
362+
Event: t v
363+
serenity: t
364+
365+
crate::event::serenity
366+
Event: v
367+
"#]],
368+
);
369+
}

crates/hir-def/src/nameres/tests/mod_resolution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ fn module_resolution_decl_inside_inline_module_in_crate_root() {
580580
//- /main.rs
581581
mod foo {
582582
#[path = "baz.rs"]
583-
mod bar;
583+
pub mod bar;
584584
}
585585
use self::foo::bar::Baz;
586586

crates/hir-ty/src/tests/method_resolution.rs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -164,16 +164,16 @@ fn infer_associated_method_with_modules() {
164164
check_infer(
165165
r#"
166166
mod a {
167-
struct A;
167+
pub struct A;
168168
impl A { pub fn thing() -> A { A {} }}
169169
}
170170
171171
mod b {
172-
struct B;
172+
pub struct B;
173173
impl B { pub fn thing() -> u32 { 99 }}
174174
175-
mod c {
176-
struct C;
175+
pub mod c {
176+
pub struct C;
177177
impl C { pub fn thing() -> C { C {} }}
178178
}
179179
}
@@ -186,22 +186,22 @@ fn infer_associated_method_with_modules() {
186186
}
187187
"#,
188188
expect![[r#"
189-
55..63 '{ A {} }': A
190-
57..61 'A {}': A
191-
125..131 '{ 99 }': u32
192-
127..129 '99': u32
193-
201..209 '{ C {} }': C
194-
203..207 'C {}': C
195-
240..324 '{ ...g(); }': ()
196-
250..251 'x': A
197-
254..265 'a::A::thing': fn thing() -> A
198-
254..267 'a::A::thing()': A
199-
277..278 'y': u32
200-
281..292 'b::B::thing': fn thing() -> u32
201-
281..294 'b::B::thing()': u32
202-
304..305 'z': C
203-
308..319 'c::C::thing': fn thing() -> C
204-
308..321 'c::C::thing()': C
189+
59..67 '{ A {} }': A
190+
61..65 'A {}': A
191+
133..139 '{ 99 }': u32
192+
135..137 '99': u32
193+
217..225 '{ C {} }': C
194+
219..223 'C {}': C
195+
256..340 '{ ...g(); }': ()
196+
266..267 'x': A
197+
270..281 'a::A::thing': fn thing() -> A
198+
270..283 'a::A::thing()': A
199+
293..294 'y': u32
200+
297..308 'b::B::thing': fn thing() -> u32
201+
297..310 'b::B::thing()': u32
202+
320..321 'z': C
203+
324..335 'c::C::thing': fn thing() -> C
204+
324..337 'c::C::thing()': C
205205
"#]],
206206
);
207207
}

crates/hir-ty/src/tests/simple.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ fn infer_paths() {
214214
fn a() -> u32 { 1 }
215215
216216
mod b {
217-
fn c() -> u32 { 1 }
217+
pub fn c() -> u32 { 1 }
218218
}
219219
220220
fn test() {
@@ -225,13 +225,13 @@ fn test() {
225225
expect![[r#"
226226
14..19 '{ 1 }': u32
227227
16..17 '1': u32
228-
47..52 '{ 1 }': u32
229-
49..50 '1': u32
230-
66..90 '{ ...c(); }': ()
231-
72..73 'a': fn a() -> u32
232-
72..75 'a()': u32
233-
81..85 'b::c': fn c() -> u32
234-
81..87 'b::c()': u32
228+
51..56 '{ 1 }': u32
229+
53..54 '1': u32
230+
70..94 '{ ...c(); }': ()
231+
76..77 'a': fn a() -> u32
232+
76..79 'a()': u32
233+
85..89 'b::c': fn c() -> u32
234+
85..91 'b::c()': u32
235235
"#]],
236236
);
237237
}
@@ -1856,7 +1856,7 @@ fn not_shadowing_module_by_primitive() {
18561856
check_types(
18571857
r#"
18581858
//- /str.rs
1859-
fn foo() -> u32 {0}
1859+
pub fn foo() -> u32 {0}
18601860
18611861
//- /main.rs
18621862
mod str;

crates/hir-ty/src/tests/traits.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,7 +1706,7 @@ fn where_clause_trait_in_scope_for_method_resolution() {
17061706
check_types(
17071707
r#"
17081708
mod foo {
1709-
trait Trait {
1709+
pub trait Trait {
17101710
fn foo(&self) -> u32 { 0 }
17111711
}
17121712
}
@@ -1723,7 +1723,7 @@ fn super_trait_method_resolution() {
17231723
check_infer(
17241724
r#"
17251725
mod foo {
1726-
trait SuperTrait {
1726+
pub trait SuperTrait {
17271727
fn foo(&self) -> u32 {}
17281728
}
17291729
}
@@ -1735,15 +1735,15 @@ fn test<T: Trait1, U: Trait2>(x: T, y: U) {
17351735
y.foo();
17361736
}"#,
17371737
expect![[r#"
1738-
49..53 'self': &Self
1739-
62..64 '{}': u32
1740-
181..182 'x': T
1741-
187..188 'y': U
1742-
193..222 '{ ...o(); }': ()
1743-
199..200 'x': T
1744-
199..206 'x.foo()': u32
1745-
212..213 'y': U
1746-
212..219 'y.foo()': u32
1738+
53..57 'self': &Self
1739+
66..68 '{}': u32
1740+
185..186 'x': T
1741+
191..192 'y': U
1742+
197..226 '{ ...o(); }': ()
1743+
203..204 'x': T
1744+
203..210 'x.foo()': u32
1745+
216..217 'y': U
1746+
216..223 'y.foo()': u32
17471747
"#]],
17481748
);
17491749
}
@@ -1754,7 +1754,7 @@ fn super_trait_impl_trait_method_resolution() {
17541754
r#"
17551755
//- minicore: sized
17561756
mod foo {
1757-
trait SuperTrait {
1757+
pub trait SuperTrait {
17581758
fn foo(&self) -> u32 {}
17591759
}
17601760
}
@@ -1764,12 +1764,12 @@ fn test(x: &impl Trait1) {
17641764
x.foo();
17651765
}"#,
17661766
expect![[r#"
1767-
49..53 'self': &Self
1768-
62..64 '{}': u32
1769-
115..116 'x': &impl Trait1
1770-
132..148 '{ ...o(); }': ()
1771-
138..139 'x': &impl Trait1
1772-
138..145 'x.foo()': u32
1767+
53..57 'self': &Self
1768+
66..68 '{}': u32
1769+
119..120 'x': &impl Trait1
1770+
136..152 '{ ...o(); }': ()
1771+
142..143 'x': &impl Trait1
1772+
142..149 'x.foo()': u32
17731773
"#]],
17741774
);
17751775
}

0 commit comments

Comments
 (0)