Skip to content

Commit 345e7c3

Browse files
committed
resolve: Make sure indeterminate and inconsistent macro resolutions always generate errors
1 parent 74d0939 commit 345e7c3

File tree

4 files changed

+69
-17
lines changed

4 files changed

+69
-17
lines changed

src/librustc/hir/def.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl Def {
210210
Def::Upvar(..) => "closure capture",
211211
Def::Label(..) => "label",
212212
Def::SelfTy(..) => "self type",
213-
Def::Macro(..) => "macro",
213+
Def::Macro(.., macro_kind) => macro_kind.descr(),
214214
Def::GlobalAsm(..) => "global asm",
215215
Def::Err => "unresolved item",
216216
}

src/librustc_resolve/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1000,7 +1000,7 @@ pub struct ModuleData<'a> {
10001000
normal_ancestor_id: DefId,
10011001

10021002
resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
1003-
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span, MacroKind)>>,
1003+
legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, MacroKind, Option<Def>)>>,
10041004
macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
10051005

10061006
// Macro invocations that can expand into items in this module.

src/librustc_resolve/macros.rs

+57-15
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ impl<'a> MacroBinding<'a> {
107107
MacroBinding::Legacy(_) => panic!("unexpected MacroBinding::Legacy"),
108108
}
109109
}
110+
111+
pub fn def_ignoring_ambiguity(self) -> Def {
112+
match self {
113+
MacroBinding::Legacy(binding) => Def::Macro(binding.def_id, MacroKind::Bang),
114+
MacroBinding::Global(binding) | MacroBinding::Modern(binding) =>
115+
binding.def_ignoring_ambiguity(),
116+
}
117+
}
110118
}
111119

112120
impl<'a> base::Resolver for Resolver<'a> {
@@ -476,7 +484,7 @@ impl<'a> Resolver<'a> {
476484
};
477485

478486
self.current_module.nearest_item_scope().legacy_macro_resolutions.borrow_mut()
479-
.push((scope, path[0], span, kind));
487+
.push((scope, path[0], kind, result.ok()));
480488

481489
result
482490
}
@@ -622,10 +630,33 @@ impl<'a> Resolver<'a> {
622630
}
623631
}
624632

625-
for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() {
633+
for &(mark, ident, kind, def) in module.legacy_macro_resolutions.borrow().iter() {
634+
let span = ident.span;
626635
let legacy_scope = &self.invocations[&mark].legacy_scope;
627636
let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident, true);
628637
let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, true, span);
638+
639+
let check_consistency = |this: &Self, binding: MacroBinding| {
640+
if let Some(def) = def {
641+
if this.ambiguity_errors.is_empty() && this.disallowed_shadowing.is_empty() &&
642+
binding.def_ignoring_ambiguity() != def {
643+
// Make sure compilation does not succeed if preferred macro resolution
644+
// has changed after the macro had been expanded. In theory all such
645+
// situations should be reported as ambiguity errors, so this is span-bug.
646+
span_bug!(span, "inconsistent resolution for a macro");
647+
}
648+
} else {
649+
// It's possible that the macro was unresolved (indeterminate) and silently
650+
// expanded into a dummy fragment for recovery during expansion.
651+
// Now, post-expansion, the resolution may succeed, but we can't change the
652+
// past and need to report an error.
653+
let msg =
654+
format!("cannot determine resolution for the {} `{}`", kind.descr(), ident);
655+
let msg_note = "import resolution is stuck, try simplifying macro imports";
656+
this.session.struct_span_err(span, &msg).note(msg_note).emit();
657+
}
658+
};
659+
629660
match (legacy_resolution, resolution) {
630661
(Some(MacroBinding::Legacy(legacy_binding)), Ok(MacroBinding::Modern(binding))) => {
631662
let msg1 = format!("`{}` could refer to the macro defined here", ident);
@@ -635,24 +666,35 @@ impl<'a> Resolver<'a> {
635666
.span_note(binding.span, &msg2)
636667
.emit();
637668
},
638-
(Some(MacroBinding::Global(binding)), Ok(MacroBinding::Global(_))) => {
639-
self.record_use(ident, MacroNS, binding, span);
640-
self.err_if_macro_use_proc_macro(ident.name, span, binding);
641-
},
642669
(None, Err(_)) => {
643-
let msg = match kind {
644-
MacroKind::Bang =>
645-
format!("cannot find macro `{}!` in this scope", ident),
646-
MacroKind::Attr =>
647-
format!("cannot find attribute macro `{}` in this scope", ident),
648-
MacroKind::Derive =>
649-
format!("cannot find derive macro `{}` in this scope", ident),
650-
};
670+
assert!(def.is_none());
671+
let bang = if kind == MacroKind::Bang { "!" } else { "" };
672+
let msg =
673+
format!("cannot find {} `{}{}` in this scope", kind.descr(), ident, bang);
651674
let mut err = self.session.struct_span_err(span, &msg);
652675
self.suggest_macro_name(&ident.as_str(), kind, &mut err, span);
653676
err.emit();
654677
},
655-
_ => {},
678+
(Some(MacroBinding::Modern(_)), _) | (_, Ok(MacroBinding::Legacy(_))) => {
679+
span_bug!(span, "impossible macro resolution result");
680+
}
681+
// OK, unambiguous resolution
682+
(Some(binding), Err(_)) | (None, Ok(binding)) |
683+
// OK, legacy wins over global even if their definitions are different
684+
(Some(binding @ MacroBinding::Legacy(_)), Ok(MacroBinding::Global(_))) |
685+
// OK, modern wins over global even if their definitions are different
686+
(Some(MacroBinding::Global(_)), Ok(binding @ MacroBinding::Modern(_))) => {
687+
check_consistency(self, binding);
688+
}
689+
(Some(MacroBinding::Global(binding1)), Ok(MacroBinding::Global(binding2))) => {
690+
if binding1.def() != binding2.def() {
691+
span_bug!(span, "mismatch between same global macro resolutions");
692+
}
693+
check_consistency(self, MacroBinding::Global(binding1));
694+
695+
self.record_use(ident, MacroNS, binding1, span);
696+
self.err_if_macro_use_proc_macro(ident.name, span, binding1);
697+
},
656698
};
657699
}
658700
}

src/libsyntax/ext/base.rs

+10
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,16 @@ pub enum MacroKind {
572572
Derive,
573573
}
574574

575+
impl MacroKind {
576+
pub fn descr(self) -> &'static str {
577+
match self {
578+
MacroKind::Bang => "macro",
579+
MacroKind::Attr => "attribute macro",
580+
MacroKind::Derive => "derive macro",
581+
}
582+
}
583+
}
584+
575585
/// An enum representing the different kinds of syntax extensions.
576586
pub enum SyntaxExtension {
577587
/// A syntax extension that is attached to an item and creates new items

0 commit comments

Comments
 (0)