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 <jonasschievink@gmail.com>
This commit is contained in:
commit
cbec995822
@ -259,3 +259,32 @@ mod module {
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn underscore_import() {
|
||||
// This used to panic, because the default (private) visibility inside block expressions would
|
||||
// point into the containing `DefMap`, which visibilities should never be able to do.
|
||||
mark::check!(adjust_vis_in_block_def_map);
|
||||
check_at(
|
||||
r#"
|
||||
mod m {
|
||||
fn main() {
|
||||
use Tr as _;
|
||||
trait Tr {}
|
||||
$0
|
||||
}
|
||||
}
|
||||
"#,
|
||||
expect![[r#"
|
||||
block scope
|
||||
_: t
|
||||
Tr: t
|
||||
|
||||
crate
|
||||
m: t
|
||||
|
||||
crate::m
|
||||
main: v
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ pub(crate) fn resolve_visibility(
|
||||
original_module: LocalModuleId,
|
||||
visibility: &RawVisibility,
|
||||
) -> Option<Visibility> {
|
||||
match visibility {
|
||||
let mut vis = match visibility {
|
||||
RawVisibility::Module(path) => {
|
||||
let (result, remaining) =
|
||||
self.resolve_path(db, original_module, &path, BuiltinShadowMode::Module);
|
||||
@ -86,15 +86,28 @@ pub(crate) fn resolve_visibility(
|
||||
}
|
||||
let types = result.take_types()?;
|
||||
match types {
|
||||
ModuleDefId::ModuleId(m) => Some(Visibility::Module(m)),
|
||||
ModuleDefId::ModuleId(m) => Visibility::Module(m),
|
||||
_ => {
|
||||
// error: visibility needs to refer to module
|
||||
None
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
RawVisibility::Public => Some(Visibility::Public),
|
||||
RawVisibility::Public => Visibility::Public,
|
||||
};
|
||||
|
||||
// In block expressions, `self` normally refers to the containing non-block module, and
|
||||
// `super` to its parent (etc.). However, visibilities must only refer to a module in the
|
||||
// DefMap they're written in, so we restrict them when that happens.
|
||||
if let Visibility::Module(m) = vis {
|
||||
if self.block_id() != m.block {
|
||||
mark::hit!(adjust_vis_in_block_def_map);
|
||||
vis = Visibility::Module(self.module_id(self.root()));
|
||||
log::debug!("visibility {:?} points outside DefMap, adjusting to {:?}", m, vis);
|
||||
}
|
||||
}
|
||||
|
||||
Some(vis)
|
||||
}
|
||||
|
||||
// Returns Yes if we are sure that additions to `ItemMap` wouldn't change
|
||||
|
Loading…
Reference in New Issue
Block a user