about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_driver/driver.rs10
-rw-r--r--src/librustc_resolve/lib.rs5
-rw-r--r--src/librustc_resolve/macros.rs125
-rw-r--r--src/libsyntax/ext/base.rs44
-rw-r--r--src/libsyntax/ext/expand.rs14
-rw-r--r--src/test/compile-fail-fulldeps/gated-quote.rs45
-rw-r--r--src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs3
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs23
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs23
-rw-r--r--src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs44
-rw-r--r--src/test/compile-fail/deriving-primitive.rs2
-rw-r--r--src/test/compile-fail/empty-macro-use.rs3
-rw-r--r--src/test/compile-fail/ext-nonexistent.rs2
-rw-r--r--src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs6
-rw-r--r--src/test/compile-fail/issue-11692-1.rs14
-rw-r--r--src/test/compile-fail/issue-11692-2.rs (renamed from src/test/compile-fail/issue-11692.rs)6
-rw-r--r--src/test/compile-fail/issue-19734.rs5
-rw-r--r--src/test/compile-fail/macro-error.rs1
-rw-r--r--src/test/compile-fail/macro-expansion-tests.rs6
-rw-r--r--src/test/compile-fail/macro-name-typo.rs5
-rw-r--r--src/test/compile-fail/macro-no-implicit-reexport.rs3
-rw-r--r--src/test/compile-fail/macro-reexport-not-locally-visible.rs3
-rw-r--r--src/test/compile-fail/macro-use-wrong-name.rs3
-rw-r--r--src/test/compile-fail/macro_undefined.rs10
-rw-r--r--src/test/compile-fail/macros-nonfatal-errors.rs5
-rw-r--r--src/test/compile-fail/missing-macro-use.rs3
-rw-r--r--src/test/compile-fail/self_type_keyword.rs10
27 files changed, 300 insertions, 123 deletions
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 4fe3730bbe2..de789d5686f 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -726,6 +726,8 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
         });
     }
 
+    after_expand(&krate)?;
+
     if sess.opts.debugging_opts.input_stats {
         println!("Post-expansion node count: {}", count_nodes(&krate));
     }
@@ -751,14 +753,14 @@ pub fn phase_2_configure_and_expand<F>(sess: &Session,
          || ast_validation::check_crate(sess, &krate));
 
     time(time_passes, "name resolution", || -> CompileResult {
-        // Since import resolution will eventually happen in expansion,
-        // don't perform `after_expand` until after import resolution.
-        after_expand(&krate)?;
-
         resolver.resolve_crate(&krate);
         Ok(())
     })?;
 
+    if resolver.found_unresolved_macro {
+        sess.parse_sess.span_diagnostic.abort_if_errors();
+    }
+
     // Needs to go *after* expansion to be able to check the results of macro expansion.
     time(time_passes, "complete gated feature checking", || {
         sess.track_errors(|| {
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 676ff98e602..fa3c12624c6 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -51,6 +51,7 @@ use syntax::ext::hygiene::{Mark, SyntaxContext};
 use syntax::ast::{self, Name, NodeId, Ident, SpannedIdent, FloatTy, IntTy, UintTy};
 use syntax::ext::base::SyntaxExtension;
 use syntax::ext::base::Determinacy::{Determined, Undetermined};
+use syntax::ext::base::MacroKind;
 use syntax::symbol::{Symbol, keywords};
 use syntax::util::lev_distance::find_best_match_for_name;
 
@@ -785,7 +786,7 @@ pub struct ModuleData<'a> {
     normal_ancestor_id: DefId,
 
     resolutions: RefCell<FxHashMap<(Ident, Namespace), &'a RefCell<NameResolution<'a>>>>,
-    legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span)>>,
+    legacy_macro_resolutions: RefCell<Vec<(Mark, Ident, Span, MacroKind)>>,
     macro_resolutions: RefCell<Vec<(Box<[Ident]>, Span)>>,
 
     // Macro invocations that can expand into items in this module.
@@ -1117,6 +1118,7 @@ pub struct Resolver<'a> {
     macro_map: FxHashMap<DefId, Rc<SyntaxExtension>>,
     macro_exports: Vec<Export>,
     pub whitelisted_legacy_custom_derives: Vec<Name>,
+    pub found_unresolved_macro: bool,
 
     // Maps the `Mark` of an expansion to its containing module or block.
     invocations: FxHashMap<Mark, &'a InvocationData<'a>>,
@@ -1315,6 +1317,7 @@ impl<'a> Resolver<'a> {
             warned_proc_macros: FxHashSet(),
             potentially_unused_imports: Vec::new(),
             struct_constructors: DefIdMap(),
+            found_unresolved_macro: false,
         }
     }
 
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 97d3e6c9e43..880f5f388d0 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -24,6 +24,7 @@ use syntax::attr;
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Determinacy, MultiModifier, MultiDecorator};
 use syntax::ext::base::{NormalTT, Resolver as SyntaxResolver, SyntaxExtension};
+use syntax::ext::base::MacroKind;
 use syntax::ext::expand::{Expansion, mark_tts};
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
@@ -236,8 +237,8 @@ impl<'a> base::Resolver for Resolver<'a> {
         None
     }
 
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-                     -> Result<Rc<SyntaxExtension>, Determinacy> {
+    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
+                     force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
         let ast::Path { ref segments, span } = *path;
         if segments.iter().any(|segment| segment.parameters.is_some()) {
             let kind =
@@ -256,6 +257,7 @@ impl<'a> base::Resolver for Resolver<'a> {
                 let msg = "non-ident macro paths are experimental";
                 let feature = "use_extern_macros";
                 emit_feature_err(&self.session.parse_sess, feature, span, GateIssue::Language, msg);
+                self.found_unresolved_macro = true;
                 return Err(Determinacy::Determined);
             }
 
@@ -266,7 +268,10 @@ impl<'a> base::Resolver for Resolver<'a> {
                 },
                 PathResult::Module(..) => unreachable!(),
                 PathResult::Indeterminate if !force => return Err(Determinacy::Undetermined),
-                _ => Err(Determinacy::Determined),
+                _ => {
+                    self.found_unresolved_macro = true;
+                    Err(Determinacy::Determined)
+                },
             };
             self.current_module.macro_resolutions.borrow_mut()
                 .push((path.into_boxed_slice(), span));
@@ -279,40 +284,19 @@ impl<'a> base::Resolver for Resolver<'a> {
             Some(MacroBinding::Modern(binding)) => Ok(binding.get_macro(self)),
             None => match self.resolve_lexical_macro_path_segment(path[0], MacroNS, None) {
                 Ok(binding) => Ok(binding.get_macro(self)),
-                Err(Determinacy::Undetermined) if !force => return Err(Determinacy::Undetermined),
-                _ => {
-                    let msg = format!("macro undefined: `{}`", name);
-                    let mut err = self.session.struct_span_err(span, &msg);
-                    self.suggest_macro_name(&name.as_str(), &mut err);
-                    err.emit();
-                    return Err(Determinacy::Determined);
-                },
+                Err(Determinacy::Undetermined) if !force =>
+                    return Err(Determinacy::Undetermined),
+                Err(_) => {
+                    self.found_unresolved_macro = true;
+                    Err(Determinacy::Determined)
+                }
             },
         };
 
-        if self.use_extern_macros {
-            self.current_module.legacy_macro_resolutions.borrow_mut().push((scope, path[0], span));
-        }
-        result
-    }
+        self.current_module.legacy_macro_resolutions.borrow_mut()
+            .push((scope, path[0], span, kind));
 
-    fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-                            -> Result<Rc<SyntaxExtension>, Determinacy> {
-        let ast::Path { span, .. } = *path;
-        match self.resolve_macro(scope, path, false) {
-            Ok(ext) => match *ext {
-                SyntaxExtension::BuiltinDerive(..) |
-                SyntaxExtension::ProcMacroDerive(..) => Ok(ext),
-                _ => Err(Determinacy::Determined),
-            },
-            Err(Determinacy::Undetermined) if force => {
-                let msg = format!("cannot find derive macro `{}` in this scope", path);
-                let mut err = self.session.struct_span_err(span, &msg);
-                err.emit();
-                Err(Determinacy::Determined)
-            },
-            Err(err) => Err(err),
-        }
+        result
     }
 }
 
@@ -438,37 +422,74 @@ impl<'a> Resolver<'a> {
             }
         }
 
-        for &(mark, ident, span) in module.legacy_macro_resolutions.borrow().iter() {
+        for &(mark, ident, span, kind) in module.legacy_macro_resolutions.borrow().iter() {
             let legacy_scope = &self.invocations[&mark].legacy_scope;
             let legacy_resolution = self.resolve_legacy_scope(legacy_scope, ident.name, true);
             let resolution = self.resolve_lexical_macro_path_segment(ident, MacroNS, Some(span));
-            let (legacy_resolution, resolution) = match (legacy_resolution, resolution) {
-                (Some(legacy_resolution), Ok(resolution)) => (legacy_resolution, resolution),
+            match (legacy_resolution, resolution) {
+                (Some(legacy_resolution), Ok(resolution)) => {
+                    let (legacy_span, participle) = match legacy_resolution {
+                        MacroBinding::Modern(binding)
+                            if binding.def() == resolution.def() => continue,
+                        MacroBinding::Modern(binding) => (binding.span, "imported"),
+                        MacroBinding::Legacy(binding) => (binding.span, "defined"),
+                    };
+                    let msg1 = format!("`{}` could refer to the macro {} here", ident, participle);
+                    let msg2 = format!("`{}` could also refer to the macro imported here", ident);
+                    self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
+                        .span_note(legacy_span, &msg1)
+                        .span_note(resolution.span, &msg2)
+                        .emit();
+                },
                 (Some(MacroBinding::Modern(binding)), Err(_)) => {
                     self.record_use(ident, MacroNS, binding, span);
                     self.err_if_macro_use_proc_macro(ident.name, span, binding);
-                    continue
                 },
-                _ => continue,
-            };
-            let (legacy_span, participle) = match legacy_resolution {
-                MacroBinding::Modern(binding) if binding.def() == resolution.def() => continue,
-                MacroBinding::Modern(binding) => (binding.span, "imported"),
-                MacroBinding::Legacy(binding) => (binding.span, "defined"),
+                (None, Err(_)) => {
+                    let msg = match kind {
+                        MacroKind::Bang =>
+                            format!("cannot find macro `{}!` in this scope", ident),
+                        MacroKind::Attr =>
+                            format!("cannot find attribute macro `{}` in this scope", ident),
+                        MacroKind::Derive =>
+                            format!("cannot find derive macro `{}` in this scope", ident),
+                    };
+                    let mut err = self.session.struct_span_err(span, &msg);
+                    self.suggest_macro_name(&ident.name.as_str(), kind, &mut err);
+                    err.emit();
+                },
+                _ => {},
             };
-            let msg1 = format!("`{}` could refer to the macro {} here", ident, participle);
-            let msg2 = format!("`{}` could also refer to the macro imported here", ident);
-            self.session.struct_span_err(span, &format!("`{}` is ambiguous", ident))
-                .span_note(legacy_span, &msg1)
-                .span_note(resolution.span, &msg2)
-                .emit();
         }
     }
 
-    fn suggest_macro_name(&mut self, name: &str, err: &mut DiagnosticBuilder<'a>) {
-        if let Some(suggestion) = find_best_match_for_name(self.macro_names.iter(), name, None) {
+    fn suggest_macro_name(&mut self, name: &str, kind: MacroKind,
+                          err: &mut DiagnosticBuilder<'a>) {
+        let suggestion = match kind {
+            MacroKind::Bang =>
+                find_best_match_for_name(self.macro_names.iter(), name, None),
+            MacroKind::Attr |
+            MacroKind::Derive => {
+                // Find a suggestion from the legacy namespace.
+                // FIXME: get_macro needs an &mut Resolver, can we do it without cloning?
+                let builtin_macros = self.builtin_macros.clone();
+                let names = builtin_macros.iter().filter_map(|(name, binding)| {
+                    if binding.get_macro(self).kind() == kind {
+                        Some(name)
+                    } else {
+                        None
+                    }
+                });
+                find_best_match_for_name(names, name, None)
+            }
+        };
+        if let Some(suggestion) = suggestion {
             if suggestion != name {
-                err.help(&format!("did you mean `{}!`?", suggestion));
+                if let MacroKind::Bang = kind {
+                    err.help(&format!("did you mean `{}!`?", suggestion));
+                } else {
+                    err.help(&format!("did you mean `{}`?", suggestion));
+                }
             } else {
                 err.help(&format!("have you added the `#[macro_use]` on the module/import?"));
             }
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index b5afd0c453a..b61ab74687b 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -474,6 +474,17 @@ impl MacResult for DummyResult {
 pub type BuiltinDeriveFn =
     for<'cx> fn(&'cx mut ExtCtxt, Span, &MetaItem, &Annotatable, &mut FnMut(Annotatable));
 
+/// Represents different kinds of macro invocations that can be resolved.
+#[derive(Clone, Copy, PartialEq, Eq)]
+pub enum MacroKind {
+    /// A bang macro - foo!()
+    Bang,
+    /// An attribute macro - #[foo]
+    Attr,
+    /// A derive attribute macro - #[derive(Foo)]
+    Derive,
+}
+
 /// An enum representing the different kinds of syntax extensions.
 pub enum SyntaxExtension {
     /// A syntax extension that is attached to an item and creates new items
@@ -520,6 +531,25 @@ pub enum SyntaxExtension {
     BuiltinDerive(BuiltinDeriveFn),
 }
 
+impl SyntaxExtension {
+    /// Return which kind of macro calls this syntax extension.
+    pub fn kind(&self) -> MacroKind {
+        match *self {
+            SyntaxExtension::NormalTT(..) |
+            SyntaxExtension::IdentTT(..) |
+            SyntaxExtension::ProcMacro(..) =>
+                MacroKind::Bang,
+            SyntaxExtension::MultiDecorator(..) |
+            SyntaxExtension::MultiModifier(..) |
+            SyntaxExtension::AttrProcMacro(..) =>
+                MacroKind::Attr,
+            SyntaxExtension::ProcMacroDerive(..) |
+            SyntaxExtension::BuiltinDerive(..) =>
+                MacroKind::Derive,
+        }
+    }
+}
+
 pub type NamedSyntaxExtension = (Name, SyntaxExtension);
 
 pub trait Resolver {
@@ -535,10 +565,8 @@ pub trait Resolver {
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
     fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>) -> Option<Attribute>;
-    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-                     -> Result<Rc<SyntaxExtension>, Determinacy>;
-    fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
-                            -> Result<Rc<SyntaxExtension>, Determinacy>;
+    fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind,
+                     force: bool) -> Result<Rc<SyntaxExtension>, Determinacy>;
 }
 
 #[derive(Copy, Clone, Debug)]
@@ -561,12 +589,8 @@ impl Resolver for DummyResolver {
 
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>) -> Option<Attribute> { None }
-    fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
-                     -> Result<Rc<SyntaxExtension>, Determinacy> {
-        Err(Determinacy::Determined)
-    }
-    fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool)
-                            -> Result<Rc<SyntaxExtension>, Determinacy> {
+    fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind,
+                     _force: bool) -> Result<Rc<SyntaxExtension>, Determinacy> {
         Err(Determinacy::Determined)
     }
 }
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index d011d7c2a1c..38494378f72 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -282,8 +282,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                         let mark = Mark::fresh();
                         derives.push(mark);
                         let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-                        let item = match self.cx.resolver
-                                             .resolve_macro(Mark::root(), &path, false) {
+                        let item = match self.cx.resolver.resolve_macro(
+                                Mark::root(), &path, MacroKind::Derive, false) {
                             Ok(ext) => match *ext {
                                 SyntaxExtension::BuiltinDerive(..) => item_with_markers.clone(),
                                 _ => item.clone(),
@@ -369,12 +369,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                      -> Result<Option<Rc<SyntaxExtension>>, Determinacy> {
         let (attr, traits, item) = match invoc.kind {
             InvocationKind::Bang { ref mac, .. } => {
-                return self.cx.resolver.resolve_macro(scope, &mac.node.path, force).map(Some);
+                return self.cx.resolver.resolve_macro(scope, &mac.node.path,
+                                                      MacroKind::Bang, force).map(Some);
             }
             InvocationKind::Attr { attr: None, .. } => return Ok(None),
             InvocationKind::Derive { name, span, .. } => {
                 let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-                return self.cx.resolver.resolve_derive_macro(scope, &path, force).map(Some);
+                return self.cx.resolver.resolve_macro(scope, &path,
+                                                      MacroKind::Derive, force).map(Some)
             }
             InvocationKind::Attr { ref mut attr, ref traits, ref mut item } => (attr, traits, item),
         };
@@ -385,7 +387,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         };
 
         let mut determined = true;
-        match self.cx.resolver.resolve_macro(scope, &path, force) {
+        match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Attr, force) {
             Ok(ext) => return Ok(Some(ext)),
             Err(Determinacy::Undetermined) => determined = false,
             Err(Determinacy::Determined) if force => return Err(Determinacy::Determined),
@@ -394,7 +396,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
         for &(name, span) in traits {
             let path = ast::Path::from_ident(span, Ident::with_empty_ctxt(name));
-            match self.cx.resolver.resolve_macro(scope, &path, force) {
+            match self.cx.resolver.resolve_macro(scope, &path, MacroKind::Derive, force) {
                 Ok(ext) => if let SyntaxExtension::ProcMacroDerive(_, ref inert_attrs) = *ext {
                     if inert_attrs.contains(&attr_name) {
                         // FIXME(jseyfried) Avoid `mem::replace` here.
diff --git a/src/test/compile-fail-fulldeps/gated-quote.rs b/src/test/compile-fail-fulldeps/gated-quote.rs
index 3480bd895bf..726af9864b4 100644
--- a/src/test/compile-fail-fulldeps/gated-quote.rs
+++ b/src/test/compile-fail-fulldeps/gated-quote.rs
@@ -25,32 +25,45 @@ extern crate syntax;
 
 use syntax::ast;
 use syntax::parse;
-use syntax_pos::Span;
 
 struct ParseSess;
 
 impl ParseSess {
     fn cfg(&self) -> ast::CrateConfig { loop { } }
     fn parse_sess<'a>(&'a self) -> &'a parse::ParseSess { loop { } }
-    fn call_site(&self) -> Span { loop { } }
+    fn call_site(&self) -> () { loop { } }
     fn ident_of(&self, st: &str) -> ast::Ident { loop { } }
     fn name_of(&self, st: &str) -> ast::Name { loop { } }
 }
 
 pub fn main() {
     let ecx = &ParseSess;
-    let x = quote_tokens!(ecx, 3);    //~ ERROR macro undefined: `quote_tokens`
-    let x = quote_expr!(ecx, 3);      //~ ERROR macro undefined: `quote_expr`
-    let x = quote_ty!(ecx, 3);        //~ ERROR macro undefined: `quote_ty`
-    let x = quote_method!(ecx, 3);    //~ ERROR macro undefined: `quote_method`
-    let x = quote_item!(ecx, 3);      //~ ERROR macro undefined: `quote_item`
-    let x = quote_pat!(ecx, 3);       //~ ERROR macro undefined: `quote_pat`
-    let x = quote_arm!(ecx, 3);       //~ ERROR macro undefined: `quote_arm`
-    let x = quote_stmt!(ecx, 3);      //~ ERROR macro undefined: `quote_stmt`
-    let x = quote_matcher!(ecx, 3);   //~ ERROR macro undefined: `quote_matcher`
-    let x = quote_attr!(ecx, 3);      //~ ERROR macro undefined: `quote_attr`
-    let x = quote_arg!(ecx, 3);       //~ ERROR macro undefined: `quote_arg`
-    let x = quote_block!(ecx, 3);     //~ ERROR macro undefined: `quote_block`
-    let x = quote_meta_item!(ecx, 3); //~ ERROR macro undefined: `quote_meta_item`
-    let x = quote_path!(ecx, 3);      //~ ERROR macro undefined: `quote_path`
+    let x = quote_tokens!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_tokens!` in this scope
+    let x = quote_expr!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_expr!` in this scope
+    let x = quote_ty!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_ty!` in this scope
+    let x = quote_method!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_method!` in this scope
+    let x = quote_item!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_item!` in this scope
+    let x = quote_pat!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_pat!` in this scope
+    let x = quote_arm!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_arm!` in this scope
+    let x = quote_stmt!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_stmt!` in this scope
+    let x = quote_matcher!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_matcher!` in this scope
+    let x = quote_attr!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_attr!` in this scope
+    let x = quote_arg!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_arg!` in this scope
+    let x = quote_block!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_block!` in this scope
+    let x = quote_meta_item!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_meta_item!` in this scope
+    let x = quote_path!(ecx, 3);
+    //~^ ERROR cannot find macro `quote_path!` in this scope
 }
diff --git a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
index d5d8d7b6ef8..886b6247c0a 100644
--- a/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
+++ b/src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
@@ -14,5 +14,6 @@
 extern crate macro_crate_test;
 
 fn main() {
-    assert_eq!(3, unexported_macro!()); //~ ERROR macro undefined: `unexported_macro`
+    unexported_macro!();
+    //~^ ERROR cannot find macro `unexported_macro!` in this scope
 }
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs
new file mode 100644
index 00000000000..719fbdb15ef
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Clona)]
+pub fn derive_clonea(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs
new file mode 100644
index 00000000000..64dcf72ba20
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs
@@ -0,0 +1,23 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// force-host
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(FooWithLongName)]
+pub fn derive_foo(input: TokenStream) -> TokenStream {
+    "".parse().unwrap()
+}
diff --git a/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs b/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
new file mode 100644
index 00000000000..c9a36920a19
--- /dev/null
+++ b/src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs
@@ -0,0 +1,44 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:derive-foo.rs
+// aux-build:derive-clona.rs
+// aux-build:attr_proc_macro.rs
+
+#![feature(proc_macro)]
+
+#[macro_use]
+extern crate derive_foo;
+#[macro_use]
+extern crate derive_clona;
+extern crate attr_proc_macro;
+
+use attr_proc_macro::attr_proc_macro;
+
+#[derive(FooWithLongNam)]
+//~^ ERROR cannot find derive macro `FooWithLongNam` in this scope
+//~^^ HELP did you mean `FooWithLongName`?
+struct Foo;
+
+#[attr_proc_macra]
+//~^ ERROR cannot find attribute macro `attr_proc_macra` in this scope
+struct Bar;
+
+#[derive(Dlone)]
+//~^ ERROR cannot find derive macro `Dlone` in this scope
+//~^^ HELP did you mean `Clone`?
+struct A;
+
+#[derive(Dlona)]
+//~^ ERROR cannot find derive macro `Dlona` in this scope
+//~^^ HELP did you mean `Clona`?
+struct B;
+
+fn main() {}
diff --git a/src/test/compile-fail/deriving-primitive.rs b/src/test/compile-fail/deriving-primitive.rs
index 97a39a46c19..04fdee5e3ed 100644
--- a/src/test/compile-fail/deriving-primitive.rs
+++ b/src/test/compile-fail/deriving-primitive.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[derive(FromPrimitive)] //~ERROR cannot find derive macro `FromPrimitive` in this scope
+#[derive(FromPrimitive)] //~ ERROR cannot find derive macro `FromPrimitive` in this scope
 enum Foo {}
 
 fn main() {}
diff --git a/src/test/compile-fail/empty-macro-use.rs b/src/test/compile-fail/empty-macro-use.rs
index d8cf23d1ff0..823a7426079 100644
--- a/src/test/compile-fail/empty-macro-use.rs
+++ b/src/test/compile-fail/empty-macro-use.rs
@@ -14,5 +14,6 @@
 extern crate two_macros;
 
 pub fn main() {
-    macro_two!();  //~ ERROR macro undefined
+    macro_two!();
+    //~^ ERROR cannot find macro
 }
diff --git a/src/test/compile-fail/ext-nonexistent.rs b/src/test/compile-fail/ext-nonexistent.rs
index 3727d91d5ea..a5bf7960624 100644
--- a/src/test/compile-fail/ext-nonexistent.rs
+++ b/src/test/compile-fail/ext-nonexistent.rs
@@ -8,5 +8,5 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:macro undefined
+// error-pattern:cannot find macro
 fn main() { iamnotanextensionthatexists!(""); }
diff --git a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs b/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs
index 03c3960a1ef..bbdf248780f 100644
--- a/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs
+++ b/src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs
@@ -12,12 +12,12 @@
 // gate
 
 __register_diagnostic!(E0001);
-//~^ ERROR macro undefined: `__register_diagnostic`
+//~^ ERROR cannot find macro `__register_diagnostic!` in this scope
 
 fn main() {
     __diagnostic_used!(E0001);
-    //~^ ERROR macro undefined: `__diagnostic_used`
+    //~^ ERROR cannot find macro `__diagnostic_used!` in this scope
 }
 
 __build_diagnostic_array!(DIAGNOSTICS);
-//~^ ERROR macro undefined: `__build_diagnostic_array`
+//~^ ERROR cannot find macro `__build_diagnostic_array!` in this scope
diff --git a/src/test/compile-fail/issue-11692-1.rs b/src/test/compile-fail/issue-11692-1.rs
new file mode 100644
index 00000000000..f577aad04e6
--- /dev/null
+++ b/src/test/compile-fail/issue-11692-1.rs
@@ -0,0 +1,14 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    print!(test!());
+    //~^ ERROR: format argument must be a string literal
+}
diff --git a/src/test/compile-fail/issue-11692.rs b/src/test/compile-fail/issue-11692-2.rs
index 7819fd4c1ab..acac2d151fe 100644
--- a/src/test/compile-fail/issue-11692.rs
+++ b/src/test/compile-fail/issue-11692-2.rs
@@ -9,10 +9,6 @@
 // except according to those terms.
 
 fn main() {
-    print!(test!());
-    //~^ ERROR: macro undefined: `test`
-    //~^^ ERROR: format argument must be a string literal
-
     concat!(test!());
-    //~^ ERROR: macro undefined: `test`
+    //~^ ERROR cannot find macro `test!` in this scope
 }
diff --git a/src/test/compile-fail/issue-19734.rs b/src/test/compile-fail/issue-19734.rs
index fe0648c3713..a3820d20aac 100644
--- a/src/test/compile-fail/issue-19734.rs
+++ b/src/test/compile-fail/issue-19734.rs
@@ -10,6 +10,9 @@
 
 fn main() {}
 
+struct Type;
+
 impl Type {
-    undef!(); //~ ERROR macro undefined: `undef`
+    undef!();
+    //~^ ERROR cannot find macro `undef!` in this scope
 }
diff --git a/src/test/compile-fail/macro-error.rs b/src/test/compile-fail/macro-error.rs
index 3512b21961a..78f95e365c4 100644
--- a/src/test/compile-fail/macro-error.rs
+++ b/src/test/compile-fail/macro-error.rs
@@ -16,5 +16,4 @@ fn main() {
     foo!(0); // Check that we report errors at macro definition, not expansion.
 
     let _: cfg!(foo) = (); //~ ERROR non-type macro in type position
-    derive!(); //~ ERROR macro undefined: `derive`
 }
diff --git a/src/test/compile-fail/macro-expansion-tests.rs b/src/test/compile-fail/macro-expansion-tests.rs
index a064e69bc6d..ada06b0b3f4 100644
--- a/src/test/compile-fail/macro-expansion-tests.rs
+++ b/src/test/compile-fail/macro-expansion-tests.rs
@@ -12,14 +12,16 @@ mod macros_cant_escape_fns {
     fn f() {
         macro_rules! m { () => { 3 + 4 } }
     }
-    fn g() -> i32 { m!() } //~ ERROR macro undefined
+    fn g() -> i32 { m!() }
+    //~^ ERROR cannot find macro
 }
 
 mod macros_cant_escape_mods {
     mod f {
         macro_rules! m { () => { 3 + 4 } }
     }
-    fn g() -> i32 { m!() } //~ ERROR macro undefined
+    fn g() -> i32 { m!() }
+    //~^ ERROR cannot find macro
 }
 
 mod macros_can_escape_flattened_mods_test {
diff --git a/src/test/compile-fail/macro-name-typo.rs b/src/test/compile-fail/macro-name-typo.rs
index e1f7d9b65d1..4840205fee4 100644
--- a/src/test/compile-fail/macro-name-typo.rs
+++ b/src/test/compile-fail/macro-name-typo.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    printlx!("oh noes!"); //~ ERROR macro undefined
-    //~^ HELP did you mean `println!`?
+    printlx!("oh noes!");
+    //~^ ERROR cannot find macro
+    //~^^ HELP did you mean `println!`?
 }
diff --git a/src/test/compile-fail/macro-no-implicit-reexport.rs b/src/test/compile-fail/macro-no-implicit-reexport.rs
index cd6640f8b6d..07467e06eb2 100644
--- a/src/test/compile-fail/macro-no-implicit-reexport.rs
+++ b/src/test/compile-fail/macro-no-implicit-reexport.rs
@@ -15,5 +15,6 @@
 extern crate macro_non_reexport_2;
 
 fn main() {
-    assert_eq!(reexported!(), 3);  //~ ERROR macro undefined
+    assert_eq!(reexported!(), 3);
+    //~^ ERROR cannot find macro `reexported!` in this scope
 }
diff --git a/src/test/compile-fail/macro-reexport-not-locally-visible.rs b/src/test/compile-fail/macro-reexport-not-locally-visible.rs
index ca334d9fd2d..54a74b0e134 100644
--- a/src/test/compile-fail/macro-reexport-not-locally-visible.rs
+++ b/src/test/compile-fail/macro-reexport-not-locally-visible.rs
@@ -17,5 +17,6 @@
 extern crate macro_reexport_1;
 
 fn main() {
-    assert_eq!(reexported!(), 3);  //~ ERROR macro undefined
+    assert_eq!(reexported!(), 3);
+    //~^ ERROR cannot find macro
 }
diff --git a/src/test/compile-fail/macro-use-wrong-name.rs b/src/test/compile-fail/macro-use-wrong-name.rs
index 4dc65434dc7..143ecb4ce5e 100644
--- a/src/test/compile-fail/macro-use-wrong-name.rs
+++ b/src/test/compile-fail/macro-use-wrong-name.rs
@@ -14,5 +14,6 @@
 extern crate two_macros;
 
 pub fn main() {
-    macro_two!();  //~ ERROR macro undefined
+    macro_two!();
+    //~^ ERROR cannot find macro
 }
diff --git a/src/test/compile-fail/macro_undefined.rs b/src/test/compile-fail/macro_undefined.rs
index d35428efacc..00c8d44f306 100644
--- a/src/test/compile-fail/macro_undefined.rs
+++ b/src/test/compile-fail/macro_undefined.rs
@@ -18,8 +18,10 @@ mod m {
 }
 
 fn main() {
-    k!(); //~ ERROR macro undefined: `k`
-          //~^ HELP did you mean `kl!`?
-    kl!(); //~ ERROR macro undefined: `kl`
-           //~^ HELP have you added the `#[macro_use]` on the module/import?
+    k!();
+    //~^ ERROR cannot find macro `k!` in this scope
+    //~^^ HELP did you mean `kl!`?
+    kl!();
+    //~^ ERROR cannot find macro `kl!` in this scope
+    //~^^ HELP have you added the `#[macro_use]` on the module/import?
 }
diff --git a/src/test/compile-fail/macros-nonfatal-errors.rs b/src/test/compile-fail/macros-nonfatal-errors.rs
index 3f710af8ac9..7046ee12b50 100644
--- a/src/test/compile-fail/macros-nonfatal-errors.rs
+++ b/src/test/compile-fail/macros-nonfatal-errors.rs
@@ -14,15 +14,10 @@
 #![feature(asm)]
 #![feature(trace_macros, concat_idents)]
 
-#[derive(Zero)] //~ ERROR
-struct CantDeriveThis;
-
 #[derive(Default)] //~ ERROR
 enum OrDeriveThis {}
 
 fn main() {
-    doesnt_exist!(); //~ ERROR
-
     asm!(invalid); //~ ERROR
 
     concat_idents!("not", "idents"); //~ ERROR
diff --git a/src/test/compile-fail/missing-macro-use.rs b/src/test/compile-fail/missing-macro-use.rs
index bbce9c21287..bfe49ea0009 100644
--- a/src/test/compile-fail/missing-macro-use.rs
+++ b/src/test/compile-fail/missing-macro-use.rs
@@ -13,5 +13,6 @@
 extern crate two_macros;
 
 pub fn main() {
-    macro_two!();  //~ ERROR macro undefined
+    macro_two!();
+    //~^ ERROR cannot find macro `macro_two!` in this scope
 }
diff --git a/src/test/compile-fail/self_type_keyword.rs b/src/test/compile-fail/self_type_keyword.rs
index b3ab96b79c4..20d2e2ca9cf 100644
--- a/src/test/compile-fail/self_type_keyword.rs
+++ b/src/test/compile-fail/self_type_keyword.rs
@@ -10,12 +10,16 @@
 
 // compile-flags: -Z continue-parse-after-error
 
-struct Self;
-//~^ ERROR expected identifier, found keyword `Self`
+mod foo {
+  struct Self;
+  //~^ ERROR expected identifier, found keyword `Self`
+}
 
 struct Bar<'Self>;
 //~^ ERROR lifetimes cannot use keyword names
 
+struct Foo;
+
 pub fn main() {
     match 15 {
         ref Self => (),
@@ -25,7 +29,7 @@ pub fn main() {
         ref mut Self => (),
         //~^ ERROR expected identifier, found keyword `Self`
         Self!() => (),
-        //~^ ERROR macro undefined: `Self`
+        //~^ ERROR cannot find macro `Self!` in this scope
         Foo { Self } => (),
         //~^ ERROR expected identifier, found keyword `Self`
     }