]> git.lizzy.rs Git - rust.git/commitdiff
Refactor macro resolution errors + add derive macro suggestions
authorJosh Driver <keeperofdakeys@gmail.com>
Mon, 6 Feb 2017 11:44:38 +0000 (22:14 +1030)
committerJosh Driver <keeperofdakeys@gmail.com>
Thu, 16 Feb 2017 11:33:15 +0000 (22:03 +1030)
28 files changed:
src/librustc_driver/driver.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/macros.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/expand.rs
src/test/compile-fail-fulldeps/gated-quote.rs
src/test/compile-fail-fulldeps/macro-crate-unexported-macro.rs
src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs [new file with mode: 0644]
src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs [new file with mode: 0644]
src/test/compile-fail/deriving-primitive.rs
src/test/compile-fail/empty-macro-use.rs
src/test/compile-fail/ext-nonexistent.rs
src/test/compile-fail/feature-gate-rustc-diagnostic-macros.rs
src/test/compile-fail/issue-11692-1.rs [new file with mode: 0644]
src/test/compile-fail/issue-11692-2.rs [new file with mode: 0644]
src/test/compile-fail/issue-11692.rs [deleted file]
src/test/compile-fail/issue-19734.rs
src/test/compile-fail/macro-error.rs
src/test/compile-fail/macro-expansion-tests.rs
src/test/compile-fail/macro-name-typo.rs
src/test/compile-fail/macro-no-implicit-reexport.rs
src/test/compile-fail/macro-reexport-not-locally-visible.rs
src/test/compile-fail/macro-use-wrong-name.rs
src/test/compile-fail/macro_undefined.rs
src/test/compile-fail/macros-nonfatal-errors.rs
src/test/compile-fail/missing-macro-use.rs
src/test/compile-fail/self_type_keyword.rs

index 4fe3730bbe24985c88a6e0dd61d51a634750e0e2..de789d5686fcfb81024bb8ebf8e66bfd4f66686d 100644 (file)
@@ -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(|| {
index 676ff98e602d6714fe1204b2f625583f874a594d..fa3c12624c67ebbd38ddf6187977d0fdef64d910 100644 (file)
@@ -51,6 +51,7 @@
 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 @@ pub fn new(session: &'a Session,
             warned_proc_macros: FxHashSet(),
             potentially_unused_imports: Vec::new(),
             struct_constructors: DefIdMap(),
+            found_unresolved_macro: false,
         }
     }
 
index 97d3e6c9e43d93c8d35f74aa9bd3e1f21b76c9e1..880f5f388d0601ff45b34ea137a5566c797d6e1d 100644 (file)
@@ -24,6 +24,7 @@
 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 @@ fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<ast::Attribute>)
         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 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                 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 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
                 },
                 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 @@ fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool)
             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 @@ pub fn finalize_current_module_macro_resolutions(&mut self) {
             }
         }
 
-        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?"));
             }
index b5afd0c453a1ef894f3a1cdca5f3422bae893444..b61ab74687bb79c3f15eacbad1d569e995956783 100644 (file)
@@ -474,6 +474,17 @@ fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
 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 @@ fn add_expansions_at_stmt(&mut self, _id: ast::NodeId, _macros: Vec<Mark>) {}
 
     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)
     }
 }
index d011d7c2a1c447c7ea7444e3031b6785ab484ee8..38494378f72ada31a9c25fb4d64b2d182a97c1ae 100644 (file)
@@ -282,8 +282,8 @@ fn expand(&mut self, expansion: Expansion) -> Expansion {
                         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 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
                      -> 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 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
         };
 
         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 @@ fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
 
         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.
index 3480bd895bf1cabb56602da59851abc89de9fd03..726af9864b48215022022f436320d276c500a516 100644 (file)
 
 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
 }
index d5d8d7b6ef85a7d5398adea7057e85da980ca7ce..886b6247c0a3d97df9961f2589bfbdbffbe6b664 100644 (file)
@@ -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 (file)
index 0000000..719fbdb
--- /dev/null
@@ -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 (file)
index 0000000..64dcf72
--- /dev/null
@@ -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 (file)
index 0000000..c9a3692
--- /dev/null
@@ -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() {}
index 97a39a46c19a81774f5e06f1b45118b65c7253da..04fdee5e3edf616bff0fceebe063aa3668df6924 100644 (file)
@@ -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() {}
index d8cf23d1ff0bbbf00b9f1751f19a7c4dab5f9d20..823a7426079aaedd454e5ff60141dca77746db60 100644 (file)
@@ -14,5 +14,6 @@
 extern crate two_macros;
 
 pub fn main() {
-    macro_two!();  //~ ERROR macro undefined
+    macro_two!();
+    //~^ ERROR cannot find macro
 }
index 3727d91d5ead4d9157514183d9145fb9cae00593..a5bf79606248753e8f92877c667c08c203995bdf 100644 (file)
@@ -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!(""); }
index 03c3960a1efe2696f6a372e905dac74b95cb8792..bbdf248780f3397c473f9e59d267e7e3590ba8ce 100644 (file)
 // 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 (file)
index 0000000..f577aad
--- /dev/null
@@ -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-2.rs b/src/test/compile-fail/issue-11692-2.rs
new file mode 100644 (file)
index 0000000..acac2d1
--- /dev/null
@@ -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() {
+    concat!(test!());
+    //~^ ERROR cannot find macro `test!` in this scope
+}
diff --git a/src/test/compile-fail/issue-11692.rs b/src/test/compile-fail/issue-11692.rs
deleted file mode 100644 (file)
index 7819fd4..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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: macro undefined: `test`
-    //~^^ ERROR: format argument must be a string literal
-
-    concat!(test!());
-    //~^ ERROR: macro undefined: `test`
-}
index fe0648c3713ffc9144ef3d68053c5e53a8e90e7b..a3820d20aac5b0813d55d7769ac30ecd044fcb91 100644 (file)
@@ -10,6 +10,9 @@
 
 fn main() {}
 
+struct Type;
+
 impl Type {
-    undef!(); //~ ERROR macro undefined: `undef`
+    undef!();
+    //~^ ERROR cannot find macro `undef!` in this scope
 }
index 3512b21961a1419618238cdb9318c310f4cb6091..78f95e365c44b7ef8510c649a35b1fe0ebf0d038 100644 (file)
@@ -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`
 }
index a064e69bc6d59f3f661edc468b3b7ceb91a42e8d..ada06b0b3f452cdb3c97859e3ba551d05d4d706b 100644 (file)
@@ -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 {
index e1f7d9b65d116a5f15fda2732196a40090f071de..4840205fee4c368a0f2f786e587ba0f3a2d995b2 100644 (file)
@@ -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!`?
 }
index cd6640f8b6dda2ad6f700816cbfb6fda352c6405..07467e06eb2df9346f1272b56466899c110c50db 100644 (file)
@@ -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
 }
index ca334d9fd2d78d331b3a1fef8b8a72c17b6f2fc0..54a74b0e134315b99bd1dfb12b49696a23b864bb 100644 (file)
@@ -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
 }
index 4dc65434dc7e15d66d66855b7a19f89d60cdade2..143ecb4ce5e0a0ebea0583b7d630ae4519149ada 100644 (file)
@@ -14,5 +14,6 @@
 extern crate two_macros;
 
 pub fn main() {
-    macro_two!();  //~ ERROR macro undefined
+    macro_two!();
+    //~^ ERROR cannot find macro
 }
index d35428efaccb3b5fd93073e707892c7644484c01..00c8d44f3060240cc6a715329a8d03af3e34ea25 100644 (file)
@@ -18,8 +18,10 @@ macro_rules! kl {
 }
 
 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?
 }
index 3f710af8ac9a883f0c31ac5161e2828b3998771f..7046ee12b50e563de83d718f08bf88486667e51a 100644 (file)
 #![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
index bbce9c21287575dc5291433bfc33ec24432a8fa5..bfe49ea00097251e4d0639043750a199f16e2729 100644 (file)
@@ -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
 }
index b3ab96b79c4925747d50e862c051b1797637ec96..20d2e2ca9cfa1264961d65c59cd1760247bb7355 100644 (file)
 
 // 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`
     }