Skip to content

Commit cbec995

Browse files
Merge #7801
7801: Restrict visibilities to the containing DefMap r=jonas-schievink a=jonas-schievink Visibilities must always point into the DefMap where they are used, but in a block expression `self` resolves to the *containing* non-block module, which is in a different DefMap. Restrict visibilities accordingly, turning them into basically `pub(block)`, which Rust has no syntax for. bors r+ Co-authored-by: Jonas Schievink <[email protected]>
2 parents f682627 + 6990b89 commit cbec995

File tree

2 files changed

+46
-4
lines changed

2 files changed

+46
-4
lines changed

crates/hir_def/src/body/tests/block.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,32 @@ fn main() {
259259
"#]],
260260
);
261261
}
262+
263+
#[test]
264+
fn underscore_import() {
265+
// This used to panic, because the default (private) visibility inside block expressions would
266+
// point into the containing `DefMap`, which visibilities should never be able to do.
267+
mark::check!(adjust_vis_in_block_def_map);
268+
check_at(
269+
r#"
270+
mod m {
271+
fn main() {
272+
use Tr as _;
273+
trait Tr {}
274+
$0
275+
}
276+
}
277+
"#,
278+
expect![[r#"
279+
block scope
280+
_: t
281+
Tr: t
282+
283+
crate
284+
m: t
285+
286+
crate::m
287+
main: v
288+
"#]],
289+
);
290+
}

crates/hir_def/src/nameres/path_resolution.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl DefMap {
7777
original_module: LocalModuleId,
7878
visibility: &RawVisibility,
7979
) -> Option<Visibility> {
80-
match visibility {
80+
let mut vis = match visibility {
8181
RawVisibility::Module(path) => {
8282
let (result, remaining) =
8383
self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
@@ -86,15 +86,28 @@ impl DefMap {
8686
}
8787
let types = result.take_types()?;
8888
match types {
89-
ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)),
89+
ModuleDefId::ModuleId(m) => Visibility::Module(m),
9090
_ => {
9191
// error: visibility needs to refer to module
92-
None
92+
return None;
9393
}
9494
}
9595
}
96-
RawVisibility::Public => Some(Visibility::Public),
96+
RawVisibility::Public => Visibility::Public,
97+
};
98+
99+
// In block expressions, `self` normally refers to the containing non-block module, and
100+
// `super` to its parent (etc.). However, visibilities must only refer to a module in the
101+
// DefMap they're written in, so we restrict them when that happens.
102+
if let Visibility::Module(m) = vis {
103+
if self.block_id() != m.block {
104+
mark::hit!(adjust_vis_in_block_def_map);
105+
vis = Visibility::Module(self.module_id(self.root()));
106+
log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
107+
}
97108
}
109+
110+
Some(vis)
98111
}
99112

100113
// Returns Yes if we are sure that additions to `ItemMap` wouldn't change

0 commit comments

Comments
 (0)