From 2d91e7aab8e91410d504ebfa48d16fca36b04614 Mon Sep 17 00:00:00 2001 From: Josh Driver Date: Mon, 6 Feb 2017 22:14:38 +1030 Subject: [PATCH] Refactor macro resolution errors + add derive macro suggestions --- src/librustc_driver/driver.rs | 10 +- src/librustc_resolve/lib.rs | 5 +- src/librustc_resolve/macros.rs | 125 ++++++++++-------- src/libsyntax/ext/base.rs | 44 ++++-- src/libsyntax/ext/expand.rs | 14 +- src/test/compile-fail-fulldeps/gated-quote.rs | 45 ++++--- .../macro-crate-unexported-macro.rs | 3 +- .../proc-macro/auxiliary/derive-clona.rs | 23 ++++ .../proc-macro/auxiliary/derive-foo.rs | 23 ++++ .../proc-macro/resolve-error.rs | 44 ++++++ src/test/compile-fail/deriving-primitive.rs | 2 +- src/test/compile-fail/empty-macro-use.rs | 3 +- src/test/compile-fail/ext-nonexistent.rs | 2 +- .../feature-gate-rustc-diagnostic-macros.rs | 6 +- src/test/compile-fail/issue-11692-1.rs | 14 ++ .../{issue-11692.rs => issue-11692-2.rs} | 6 +- src/test/compile-fail/issue-19734.rs | 5 +- src/test/compile-fail/macro-error.rs | 1 - .../compile-fail/macro-expansion-tests.rs | 6 +- src/test/compile-fail/macro-name-typo.rs | 5 +- .../macro-no-implicit-reexport.rs | 3 +- .../macro-reexport-not-locally-visible.rs | 3 +- src/test/compile-fail/macro-use-wrong-name.rs | 3 +- src/test/compile-fail/macro_undefined.rs | 10 +- .../compile-fail/macros-nonfatal-errors.rs | 5 - src/test/compile-fail/missing-macro-use.rs | 3 +- src/test/compile-fail/self_type_keyword.rs | 10 +- 27 files changed, 300 insertions(+), 123 deletions(-) create mode 100644 src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-clona.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/auxiliary/derive-foo.rs create mode 100644 src/test/compile-fail-fulldeps/proc-macro/resolve-error.rs create mode 100644 src/test/compile-fail/issue-11692-1.rs rename src/test/compile-fail/{issue-11692.rs => issue-11692-2.rs} (75%) diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 4fe3730bbe249..de789d5686fcf 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -726,6 +726,8 @@ pub fn phase_2_configure_and_expand(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(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 676ff98e602d6..fa3c12624c67e 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>>>, - legacy_macro_resolutions: RefCell>, + legacy_macro_resolutions: RefCell>, macro_resolutions: RefCell, Span)>>, // Macro invocations that can expand into items in this module. @@ -1117,6 +1118,7 @@ pub struct Resolver<'a> { macro_map: FxHashMap>, macro_exports: Vec, pub whitelisted_legacy_custom_derives: Vec, + pub found_unresolved_macro: bool, // Maps the `Mark` of an expansion to its containing module or block. invocations: FxHashMap>, @@ -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 97d3e6c9e43d9..880f5f388d060 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, Determinacy> { + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, + force: bool) -> Result, 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, 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 b5afd0c453a1e..b61ab74687bb7 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) -> Option; - fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) - -> Result, Determinacy>; - fn resolve_derive_macro(&mut self, scope: Mark, path: &ast::Path, force: bool) - -> Result, Determinacy>; + fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, + force: bool) -> Result, 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) -> Option { None } - fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) - -> Result, Determinacy> { - Err(Determinacy::Determined) - } - fn resolve_derive_macro(&mut self, _scope: Mark, _path: &ast::Path, _force: bool) - -> Result, Determinacy> { + fn resolve_macro(&mut self, _scope: Mark, _path: &ast::Path, _kind: MacroKind, + _force: bool) -> Result, Determinacy> { Err(Determinacy::Determined) } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d011d7c2a1c44..38494378f72ad 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>, 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 3480bd895bf1c..726af9864b482 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 d5d8d7b6ef85a..886b6247c0a3d 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 0000000000000..719fbdb15ef2a --- /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 or the MIT license +// , 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 0000000000000..64dcf72ba2029 --- /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 or the MIT license +// , 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 0000000000000..c9a36920a19e4 --- /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 or the MIT license +// , 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 97a39a46c19a8..04fdee5e3edf6 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 d8cf23d1ff0bb..823a7426079aa 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 3727d91d5ead4..a5bf796062487 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 03c3960a1efe2..bbdf248780f33 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 0000000000000..f577aad04e620 --- /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 or the MIT license +// , 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 similarity index 75% rename from src/test/compile-fail/issue-11692.rs rename to src/test/compile-fail/issue-11692-2.rs index 7819fd4c1abc7..acac2d151fe9a 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 fe0648c3713ff..a3820d20aac5b 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 3512b21961a14..78f95e365c44b 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 a064e69bc6d59..ada06b0b3f452 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 e1f7d9b65d116..4840205fee4c3 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 cd6640f8b6dda..07467e06eb2df 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 ca334d9fd2d78..54a74b0e13431 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 4dc65434dc7e1..143ecb4ce5e0a 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 d35428efaccb3..00c8d44f30602 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 3f710af8ac9a8..7046ee12b50e5 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 bbce9c2128757..bfe49ea000972 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 b3ab96b79c492..20d2e2ca9cfa1 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` }