Skip to content
Permalink
Browse files

resolve/expand: Catch macro kind mismatches early in resolve

This way we are processing all of them in a single point, rather than separately for each syntax extension kind.
Also, the standard expected/found wording is used.
  • Loading branch information...
petrochenkov committed Jul 3, 2019
1 parent f16993d commit 3041ec61185d6f9795ff16cc345e8f11b06edbbf
@@ -348,7 +348,18 @@ impl<'a> Resolver<'a> {
_ => panic!("expected `DefKind::Macro` or `Res::NonMacroAttr`"),
};

Ok((res, self.get_macro(res)))
let ext = self.get_macro(res);
Ok(if ext.macro_kind() != kind {
let expected = if kind == MacroKind::Attr { "attribute" } else { kind.descr() };
let msg = format!("expected {}, found {} `{}`", expected, res.descr(), path);
self.session.struct_span_err(path.span, &msg)
.span_label(path.span, format!("not {} {}", kind.article(), expected))
.emit();
// Return dummy syntax extensions for unexpected macro kinds for better recovery.
(Res::Err, self.dummy_ext(kind))
} else {
(res, ext)
})
}

fn report_unknown_attribute(&self, span: Span, name: &str, msg: &str, feature: Symbol) {
@@ -323,12 +323,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
progress = true;
let ExpansionData { depth, mark, .. } = invoc.expansion_data;
self.cx.current_expansion = invoc.expansion_data.clone();

self.cx.current_expansion.mark = scope;

// FIXME(jseyfried): Refactor out the following logic
let (expanded_fragment, new_invocations) = if let Some(ext) = ext {
let (invoc_fragment_kind, invoc_span) = (invoc.fragment_kind, invoc.span());
let fragment = self.expand_invoc(invoc, &*ext).unwrap_or_else(|| {
let fragment = self.expand_invoc(invoc, &ext).unwrap_or_else(|| {
invoc_fragment_kind.dummy(invoc_span).unwrap()
});
self.collect_invocations(fragment, &[])
@@ -551,17 +551,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
self.gate_proc_macro_expansion(attr.span, &res);
res
}
SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
self.cx.span_err(attr.span, &format!("`{}` is a derive macro", attr.path));
self.cx.trace_macros_diag();
invoc.fragment_kind.dummy(attr.span)
}
_ => {
let msg = &format!("macro `{}` may not be used in attributes", attr.path);
self.cx.span_err(attr.span, msg);
self.cx.trace_macros_diag();
invoc.fragment_kind.dummy(attr.span)
}
_ => unreachable!()
}
}

@@ -671,21 +661,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let tok_result = expander.expand(self.cx, span, mac.node.stream());
kind.make_from(tok_result)
}

SyntaxExtensionKind::Attr(..) |
SyntaxExtensionKind::LegacyAttr(..) |
SyntaxExtensionKind::NonMacroAttr { .. } => {
self.cx.span_err(path.span,
&format!("`{}` can only be used in attributes", path));
self.cx.trace_macros_diag();
kind.dummy(span)
}

SyntaxExtensionKind::Derive(..) | SyntaxExtensionKind::LegacyDerive(..) => {
self.cx.span_err(path.span, &format!("`{}` is a derive macro", path));
self.cx.trace_macros_diag();
kind.dummy(span)
}
_ => unreachable!()
};

if opt_expanded.is_some() {
@@ -747,12 +723,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let items = expander.expand(self.cx, span, &meta, item);
Some(invoc.fragment_kind.expect_from_annotatables(items))
}
_ => {
let msg = &format!("macro `{}` may not be used for derive attributes", path);
self.cx.span_err(path.span, msg);
self.cx.trace_macros_diag();
invoc.fragment_kind.dummy(path.span)
}
_ => unreachable!()
}
}

@@ -7,12 +7,12 @@ mod unknown { pub macro rustc() {} }

#[rustc::unknown]
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
//~| ERROR macro `rustc::unknown` may not be used in attributes
//~| ERROR expected attribute, found macro `rustc::unknown`
fn f() {}

#[unknown::rustc]
//~^ ERROR attributes starting with `rustc` are reserved for use by the `rustc` compiler
//~| ERROR macro `unknown::rustc` may not be used in attributes
//~| ERROR expected attribute, found macro `unknown::rustc`
fn g() {}

#[rustc_dummy]
@@ -7,11 +7,11 @@ LL | #[rustc::unknown]
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable

error: macro `rustc::unknown` may not be used in attributes
--> $DIR/feature-gate-rustc-attrs.rs:8:1
error: expected attribute, found macro `rustc::unknown`
--> $DIR/feature-gate-rustc-attrs.rs:8:3
|
LL | #[rustc::unknown]
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ not an attribute

error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
--> $DIR/feature-gate-rustc-attrs.rs:13:12
@@ -22,11 +22,11 @@ LL | #[unknown::rustc]
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add `#![feature(rustc_attrs)]` to the crate attributes to enable

error: macro `unknown::rustc` may not be used in attributes
--> $DIR/feature-gate-rustc-attrs.rs:13:1
error: expected attribute, found macro `unknown::rustc`
--> $DIR/feature-gate-rustc-attrs.rs:13:3
|
LL | #[unknown::rustc]
| ^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^ not an attribute

error[E0658]: attributes starting with `rustc` are reserved for use by the `rustc` compiler
--> $DIR/feature-gate-rustc-attrs.rs:20:3
@@ -1,4 +1,4 @@
#[derive(inline)] //~ ERROR macro `inline` may not be used for derive attributes
#[derive(inline)] //~ ERROR expected derive macro, found built-in attribute `inline`
struct S;

fn main() {}
@@ -1,8 +1,8 @@
error: macro `inline` may not be used for derive attributes
error: expected derive macro, found built-in attribute `inline`
--> $DIR/macro-path-prelude-fail-4.rs:1:10
|
LL | #[derive(inline)]
| ^^^^^^
| ^^^^^^ not a derive macro

error: aborting due to previous error

@@ -26,23 +26,31 @@ fn check_bang1() {
}
fn check_bang2() {
my_macro_attr!(); //~ ERROR cannot find macro `my_macro_attr!` in this scope
crate::my_macro_attr!(); //~ ERROR can't use a procedural macro from the same crate that defines
//~| ERROR expected macro, found attribute macro `crate::my_macro_attr`
}
fn check_bang3() {
MyTrait!(); //~ ERROR cannot find macro `MyTrait!` in this scope
crate::MyTrait!(); //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected macro, found derive macro `crate::MyTrait`
}

#[my_macro] //~ ERROR attribute `my_macro` is currently unknown
#[crate::my_macro] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR expected attribute, found macro `crate::my_macro`
fn check_attr1() {}
#[my_macro_attr] //~ ERROR can't use a procedural macro from the same crate that defines it
fn check_attr2() {}
#[MyTrait] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR `MyTrait` is a derive macro
//~| ERROR expected attribute, found derive macro `MyTrait`
fn check_attr3() {}

#[derive(my_macro)] //~ ERROR cannot find derive macro `my_macro` in this scope
#[derive(crate::my_macro)] //~ ERROR can't use a procedural macro from the same crate that defines
//~| ERROR expected derive macro, found macro `crate::my_macro`
struct CheckDerive1;
#[derive(my_macro_attr)] //~ ERROR can't use a procedural macro from the same crate that defines it
//~| ERROR macro `my_macro_attr` may not be used for derive attributes
//~| ERROR expected derive macro, found attribute macro `my_macro_attr`
struct CheckDerive2;
#[derive(MyTrait)] //~ ERROR can't use a procedural macro from the same crate that defines it
struct CheckDerive3;
@@ -5,52 +5,100 @@ LL | my_macro!();
| ^^^^^^^^

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:36:3
--> $DIR/macro-namespace-reserved-2.rs:29:5
|
LL | crate::my_macro_attr!();
| ^^^^^^^^^^^^^^^^^^^^

error: expected macro, found attribute macro `crate::my_macro_attr`
--> $DIR/macro-namespace-reserved-2.rs:29:5
|
LL | crate::my_macro_attr!();
| ^^^^^^^^^^^^^^^^^^^^ not a macro

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:34:5
|
LL | crate::MyTrait!();
| ^^^^^^^^^^^^^^

error: expected macro, found derive macro `crate::MyTrait`
--> $DIR/macro-namespace-reserved-2.rs:34:5
|
LL | crate::MyTrait!();
| ^^^^^^^^^^^^^^ not a macro

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:42:3
|
LL | #[my_macro_attr]
| ^^^^^^^^^^^^^

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:38:3
--> $DIR/macro-namespace-reserved-2.rs:44:3
|
LL | #[MyTrait]
| ^^^^^^^

error: `MyTrait` is a derive macro
--> $DIR/macro-namespace-reserved-2.rs:38:1
error: expected attribute, found derive macro `MyTrait`
--> $DIR/macro-namespace-reserved-2.rs:44:3
|
LL | #[MyTrait]
| ^^^^^^^^^^
| ^^^^^^^ not an attribute

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:44:10
--> $DIR/macro-namespace-reserved-2.rs:49:10
|
LL | #[derive(crate::my_macro)]
| ^^^^^^^^^^^^^^^

error: expected derive macro, found macro `crate::my_macro`
--> $DIR/macro-namespace-reserved-2.rs:49:10
|
LL | #[derive(crate::my_macro)]
| ^^^^^^^^^^^^^^^ not a derive macro

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:52:10
|
LL | #[derive(my_macro_attr)]
| ^^^^^^^^^^^^^

error: macro `my_macro_attr` may not be used for derive attributes
--> $DIR/macro-namespace-reserved-2.rs:44:10
error: expected derive macro, found attribute macro `my_macro_attr`
--> $DIR/macro-namespace-reserved-2.rs:52:10
|
LL | #[derive(my_macro_attr)]
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ not a derive macro

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:47:10
--> $DIR/macro-namespace-reserved-2.rs:55:10
|
LL | #[derive(MyTrait)]
| ^^^^^^^

error[E0658]: The attribute `my_macro` is currently unknown to the compiler and may have meaning added to it in the future
--> $DIR/macro-namespace-reserved-2.rs:34:3
--> $DIR/macro-namespace-reserved-2.rs:38:3
|
LL | #[my_macro]
| ^^^^^^^^
|
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
= help: add #![feature(custom_attribute)] to the crate attributes to enable

error: can't use a procedural macro from the same crate that defines it
--> $DIR/macro-namespace-reserved-2.rs:39:3
|
LL | #[crate::my_macro]
| ^^^^^^^^^^^^^^^

error: expected attribute, found macro `crate::my_macro`
--> $DIR/macro-namespace-reserved-2.rs:39:3
|
LL | #[crate::my_macro]
| ^^^^^^^^^^^^^^^ not an attribute

error: cannot find derive macro `my_macro` in this scope
--> $DIR/macro-namespace-reserved-2.rs:42:10
--> $DIR/macro-namespace-reserved-2.rs:48:10
|
LL | #[derive(my_macro)]
| ^^^^^^^^
@@ -62,11 +110,11 @@ LL | my_macro_attr!();
| ^^^^^^^^^^^^^

error: cannot find macro `MyTrait!` in this scope
--> $DIR/macro-namespace-reserved-2.rs:31:5
--> $DIR/macro-namespace-reserved-2.rs:33:5
|
LL | MyTrait!();
| ^^^^^^^

error: aborting due to 11 previous errors
error: aborting due to 19 previous errors

For more information about this error, try `rustc --explain E0658`.
@@ -1,6 +1,6 @@
#[derive(rustfmt::skip)] //~ ERROR macro `rustfmt::skip` may not be used for derive attributes
#[derive(rustfmt::skip)] //~ ERROR expected derive macro, found tool attribute `rustfmt::skip`
struct S;

fn main() {
rustfmt::skip!(); //~ ERROR `rustfmt::skip` can only be used in attributes
rustfmt::skip!(); //~ ERROR expected macro, found tool attribute `rustfmt::skip`
}
@@ -1,14 +1,14 @@
error: macro `rustfmt::skip` may not be used for derive attributes
error: expected derive macro, found tool attribute `rustfmt::skip`
--> $DIR/tool-attributes-misplaced-2.rs:1:10
|
LL | #[derive(rustfmt::skip)]
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ not a derive macro

error: `rustfmt::skip` can only be used in attributes
error: expected macro, found tool attribute `rustfmt::skip`
--> $DIR/tool-attributes-misplaced-2.rs:5:5
|
LL | rustfmt::skip!();
| ^^^^^^^^^^^^^
| ^^^^^^^^^^^^^ not a macro

error: aborting due to 2 previous errors

0 comments on commit 3041ec6

Please sign in to comment.
You can’t perform that action at this time.