});
}
+ after_expand(&krate)?;
+
if sess.opts.debugging_opts.input_stats {
println!("Post-expansion node count: {}", count_nodes(&krate));
}
|| 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(|| {
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;
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.
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>>,
warned_proc_macros: FxHashSet(),
potentially_unused_imports: Vec::new(),
struct_constructors: DefIdMap(),
+ found_unresolved_macro: false,
}
}
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;
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 =
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);
}
},
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));
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
}
}
}
}
- 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?"));
}
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
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 {
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)]
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)
}
}
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(),
-> 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),
};
};
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),
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.
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
}
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
}
--- /dev/null
+// 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()
+}
--- /dev/null
+// 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()
+}
--- /dev/null
+// 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() {}
// 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() {}
extern crate two_macros;
pub fn main() {
- macro_two!(); //~ ERROR macro undefined
+ macro_two!();
+ //~^ ERROR cannot find macro
}
// 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!(""); }
// 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
--- /dev/null
+// 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
+}
--- /dev/null
+// 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
+}
+++ /dev/null
-// 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`
-}
fn main() {}
+struct Type;
+
impl Type {
- undef!(); //~ ERROR macro undefined: `undef`
+ undef!();
+ //~^ ERROR cannot find macro `undef!` in this scope
}
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`
}
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 {
// 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!`?
}
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
}
extern crate macro_reexport_1;
fn main() {
- assert_eq!(reexported!(), 3); //~ ERROR macro undefined
+ assert_eq!(reexported!(), 3);
+ //~^ ERROR cannot find macro
}
extern crate two_macros;
pub fn main() {
- macro_two!(); //~ ERROR macro undefined
+ macro_two!();
+ //~^ ERROR cannot find macro
}
}
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?
}
#![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
extern crate two_macros;
pub fn main() {
- macro_two!(); //~ ERROR macro undefined
+ macro_two!();
+ //~^ ERROR cannot find macro `macro_two!` in this scope
}
// 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 => (),
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`
}