When declaring a declarative macro in an item it's only accessible inside it

This commit is contained in:
Esteban Küber 2019-08-15 18:58:20 -07:00
parent 7b0085a613
commit 8c07d7814d
4 changed files with 58 additions and 32 deletions

View File

@ -514,8 +514,11 @@ impl<'hir> Map<'hir> {
&self.forest.krate.attrs
}
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId)
{
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) {
self.get_if_module(module).expect("not a module")
}
pub fn get_if_module(&self, module: DefId) -> Option<(&'hir Mod, Span, HirId)> {
let hir_id = self.as_local_hir_id(module).unwrap();
self.read(hir_id);
match self.find_entry(hir_id).unwrap().node {
@ -523,9 +526,9 @@ impl<'hir> Map<'hir> {
span,
node: ItemKind::Mod(ref m),
..
}) => (m, span, hir_id),
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id),
_ => panic!("not a module")
}) => Some((m, span, hir_id)),
Node::Crate => Some((&self.forest.krate.module, self.forest.krate.span, hir_id)),
_ => None,
}
}

View File

@ -508,39 +508,45 @@ impl EmbargoVisitor<'tcx> {
}
}
fn update_macro_reachable_mod(
&mut self,
reachable_mod: hir::HirId,
defining_mod: DefId,
) {
let module_def_id = self.tcx.hir().local_def_id(reachable_mod);
let module = self.tcx.hir().get_module(module_def_id).0;
for item_id in &module.item_ids {
let hir_id = item_id.id;
let item_def_id = self.tcx.hir().local_def_id(hir_id);
if let Some(def_kind) = self.tcx.def_kind(item_def_id) {
let item = self.tcx.hir().expect_item(hir_id);
let vis = ty::Visibility::from_hir(&item.vis, hir_id, self.tcx);
self.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
fn update_macro_reachable_mod(&mut self, reachable_mod: hir::HirId, defining_mod: DefId) {
let set_vis = |this: &mut Self, hir_id: hir::HirId| {
let item_def_id = this.tcx.hir().local_def_id(hir_id);
if let Some(def_kind) = this.tcx.def_kind(item_def_id) {
let item = this.tcx.hir().expect_item(hir_id);
let vis = ty::Visibility::from_hir(&item.vis, hir_id, this.tcx);
this.update_macro_reachable_def(hir_id, def_kind, vis, defining_mod);
}
}
};
if let Some(exports) = self.tcx.module_exports(module_def_id) {
for export in exports {
if export.vis.is_accessible_from(defining_mod, self.tcx) {
if let Res::Def(def_kind, def_id) = export.res {
let vis = def_id_visibility(self.tcx, def_id).0;
if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
self.update_macro_reachable_def(
hir_id,
def_kind,
vis,
defining_mod,
);
let module_def_id = self.tcx.hir().local_def_id(reachable_mod);
if let Some((module, _, _)) = self.tcx.hir().get_if_module(module_def_id) {
for item_id in &module.item_ids {
let hir_id = item_id.id;
set_vis(self, hir_id);
}
if let Some(exports) = self.tcx.module_exports(module_def_id) {
for export in exports {
if export.vis.is_accessible_from(defining_mod, self.tcx) {
if let Res::Def(def_kind, def_id) = export.res {
let vis = def_id_visibility(self.tcx, def_id).0;
if let Some(hir_id) = self.tcx.hir().as_local_hir_id(def_id) {
self.update_macro_reachable_def(
hir_id,
def_kind,
vis,
defining_mod,
);
}
}
}
}
}
} else if let Some(hir::Node::Item(hir::Item {
hir_id,
..
})) = self.tcx.hir().get_if_local(module_def_id) { // #63164
// `macro` defined inside of an item is only visible inside of that item's scope.
set_vis(self, *hir_id);
}
}

View File

@ -0,0 +1,9 @@
#![feature(decl_macro)]
pub fn moo() {
pub macro ABC() {{}}
}
fn main() {
ABC!(); //~ ERROR cannot find macro `ABC!` in this scope
}

View File

@ -0,0 +1,8 @@
error: cannot find macro `ABC!` in this scope
--> $DIR/macro-in-fn.rs:8:5
|
LL | ABC!();
| ^^^
error: aborting due to previous error