aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-02-28 03:49:40 +0000
committerGitHub <[email protected]>2021-02-28 03:49:40 +0000
commitcbec9958220a7ce5d51289e2fc59c2eb0754ac87 (patch)
tree81a4a09539f49b5993a2315625b704c0a51943f3 /crates
parentf682627da4be4777fa0c1527398ef4136cd929b1 (diff)
parent6990b89b2650d8263dad348173f4f729d6753360 (diff)
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]>
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/body/tests/block.rs29
-rw-r--r--crates/hir_def/src/nameres/path_resolution.rs21
2 files changed, 46 insertions, 4 deletions
diff --git a/crates/hir_def/src/body/tests/block.rs b/crates/hir_def/src/body/tests/block.rs
index a5ec0883f..8bca72a17 100644
--- a/crates/hir_def/src/body/tests/block.rs
+++ b/crates/hir_def/src/body/tests/block.rs
@@ -259,3 +259,32 @@ fn main() {
259 "#]], 259 "#]],
260 ); 260 );
261} 261}
262
263#[test]
264fn 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#"
270mod 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}
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index fdcdc23ae..dd1db0094 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -77,7 +77,7 @@ impl DefMap {
77 original_module: LocalModuleId, 77 original_module: LocalModuleId,
78 visibility: &RawVisibility, 78 visibility: &RawVisibility,
79 ) -> Option<Visibility> { 79 ) -> Option<Visibility> {
80 match visibility { 80 let mut vis = match visibility {
81 RawVisibility::Module(path) => { 81 RawVisibility::Module(path) => {
82 let (result, remaining) = 82 let (result, remaining) =
83 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module); 83 self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
@@ -86,15 +86,28 @@ impl DefMap {
86 } 86 }
87 let types = result.take_types()?; 87 let types = result.take_types()?;
88 match types { 88 match types {
89 ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)), 89 ModuleDefId::ModuleId(m) => Visibility::Module(m),
90 _ => { 90 _ => {
91 // error: visibility needs to refer to module 91 // error: visibility needs to refer to module
92 None 92 return None;
93 } 93 }
94 } 94 }
95 } 95 }
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 }
97 } 108 }
109
110 Some(vis)
98 } 111 }
99 112
100 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change 113 // Returns Yes if we are sure that additions to `ItemMap` wouldn't change