self.report_proc_macro_stub(invoc.span());
return Err(Determinacy::Determined);
} else if let Def::NonMacroAttr(attr_kind) = def {
+ // Note that not only attributes, but anything in macro namespace can result in a
+ // `Def::NonMacroAttr` definition (e.g. `inline!()`), so we must report the error
+ // below for these cases.
let is_attr_invoc =
if let InvocationKind::Attr { .. } = invoc.kind { true } else { false };
let path = invoc.path().expect("no path for non-macro attr");
// 3. Builtin attributes (closed, controlled).
assert!(ns == TypeNS || ns == MacroNS);
- let force = force || record_used;
+ assert!(force || !record_used); // `record_used` implies `force`
ident = ident.modern();
// Names from inner scope that can't shadow names from outer scopes, e.g.
let determinacy = Determinacy::determined(force);
if determinacy == Determinacy::Determined && is_attr {
- // For attributes interpret determinate "no solution" as a custom attribute.
+ // For single-segment attributes interpret determinate "no resolution" as a custom
+ // attribute. (Lexical resolution implies the first segment and is_attr should imply
+ // the last segment, so we are certainly working with a single-segment attribute here.)
+ assert!(ns == MacroNS);
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Custom),
ty::Visibility::Public, ident.span, Mark::root())
.to_name_binding(self.arenas);
}
fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> {
+ if invoc.fragment_kind == AstFragmentKind::ForeignItems &&
+ !self.cx.ecfg.macros_in_extern_enabled() {
+ if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else {
+ emit_feature_err(&self.cx.parse_sess, "macros_in_extern",
+ invoc.span(), GateIssue::Language,
+ "macro invocations in `extern {}` blocks are experimental");
+ }
+ }
+
let result = match invoc.kind {
InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?,
InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?,
};
if let NonMacroAttr { mark_used: false } = *ext {} else {
+ // Macro attrs are always used when expanded,
+ // non-macro attrs are considered used when the field says so.
attr::mark_used(&attr);
}
invoc.expansion_data.mark.set_expn_info(ExpnInfo {
foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> {
let (attr, traits, foreign_item) = self.classify_item(foreign_item);
- let explain = if self.cx.ecfg.use_extern_macros_enabled() {
- feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN
- } else {
- feature_gate::EXPLAIN_MACROS_IN_EXTERN
- };
-
- if attr.is_some() || !traits.is_empty() {
- if !self.cx.ecfg.macros_in_extern_enabled() &&
- !self.cx.ecfg.custom_attribute_enabled() {
- if let Some(ref attr) = attr {
- emit_feature_err(&self.cx.parse_sess, "macros_in_extern", attr.span,
- GateIssue::Language, explain);
- }
- }
-
+ if attr.is_some() || !traits.is_empty() {
let item = Annotatable::ForeignItem(P(foreign_item));
return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems)
.make_foreign_items();
if let ast::ForeignItemKind::Macro(mac) = foreign_item.node {
self.check_attributes(&foreign_item.attrs);
-
- if !self.cx.ecfg.macros_in_extern_enabled() {
- emit_feature_err(&self.cx.parse_sess, "macros_in_extern", foreign_item.span,
- GateIssue::Language, explain);
- }
-
return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems)
.make_foreign_items();
}
fn enable_custom_derive = custom_derive,
fn enable_format_args_nl = format_args_nl,
fn macros_in_extern_enabled = macros_in_extern,
- fn custom_attribute_enabled = custom_attribute,
fn proc_macro_mod = proc_macro_mod,
fn proc_macro_gen = proc_macro_gen,
fn proc_macro_expr = proc_macro_expr,
pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str =
"using the `?` macro Kleene operator for \"at most one\" repetition is unstable";
-pub const EXPLAIN_MACROS_IN_EXTERN: &'static str =
- "macro invocations in `extern {}` blocks are experimental.";
-
-// mention proc-macros when enabled
-pub const EXPLAIN_PROC_MACROS_IN_EXTERN: &'static str =
- "macro and proc-macro invocations in `extern {}` blocks are experimental.";
-
struct PostExpansionVisitor<'a> {
context: &'a Context<'a>,
}
).emit();
} else {
set(&mut features, mi.span);
- feature_checker.collect(&features, mi.span);
features.declared_lang_features.push((name, mi.span, None));
}
continue
#![feature(use_extern_macros)]
#![emit_unchanged]
-//~^ ERROR: cannot find attribute macro `emit_unchanged` in this scope
+//~^ ERROR attribute `emit_unchanged` is currently unknown to the compiler
extern crate issue_41211;
use issue_41211::emit_unchanged;
#[link(name = "rust_test_helpers", kind = "static")]
extern {
#[no_output]
- //~^ ERROR macro and proc-macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
fn some_definitely_unknown_symbol_which_should_be_removed();
#[nop_attr]
- //~^ ERROR macro and proc-macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
fn rust_get_test_int() -> isize;
emit_input!(fn rust_dbg_extern_identity_u32(arg: u32) -> u32;);
- //~^ ERROR macro and proc-macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
}
+++ /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:attr_proc_macro.rs
-// ignore-tidy-linelength
-
-#![feature(custom_attribute)]
-//~^ ERROR Cannot use `#![feature(use_extern_macros)]` and `#![feature(custom_attribute)] at the same time
-
-extern crate attr_proc_macro;
-use attr_proc_macro::attr_proc_macro;
-
-#[attr_proc_macro]
-fn foo() {}
-
-fn main() {
- foo();
-}
#[link(name = "rust_test_helpers", kind = "static")]
extern {
returns_isize!(rust_get_test_int);
- //~^ ERROR macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
- //~^ ERROR macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
emits_nothing!();
- //~^ ERROR macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
}
#[align = 8]
fn f() { }
- #[vec(1, 2, 3)]
+ #[vector(1, 2, 3)]
fn g() { }
}
// aux-build:attr_proc_macro.rs
// aux-build:bang_proc_macro.rs
-#![feature(use_extern_macros)]
+#![feature(custom_attribute)]
#[macro_use]
extern crate derive_foo;
//~^ ERROR cannot find
struct Foo;
-#[attr_proc_macra]
-//~^ ERROR cannot find
+#[attr_proc_macra] // OK, interpreted as a custom attribute
struct Bar;
-#[FooWithLongNan]
-//~^ ERROR cannot find
+#[FooWithLongNan] // OK, interpreted as a custom attribute
struct Asdf;
#[derive(Dlone)]
LL | #[derive(FooWithLongNan)]
| ^^^^^^^^^^^^^^ help: try: `FooWithLongName`
-error: cannot find attribute macro `attr_proc_macra` in this scope
- --> $DIR/resolve-error.rs:40:3
- |
-LL | #[attr_proc_macra]
- | ^^^^^^^^^^^^^^^ help: try: `attr_proc_macro`
-
-error: cannot find attribute macro `FooWithLongNan` in this scope
- --> $DIR/resolve-error.rs:44:3
- |
-LL | #[FooWithLongNan]
- | ^^^^^^^^^^^^^^
-
error: cannot find derive macro `Dlone` in this scope
- --> $DIR/resolve-error.rs:48:10
+ --> $DIR/resolve-error.rs:46:10
|
LL | #[derive(Dlone)]
| ^^^^^ help: try: `Clone`
error: cannot find derive macro `Dlona` in this scope
- --> $DIR/resolve-error.rs:52:10
+ --> $DIR/resolve-error.rs:50:10
|
LL | #[derive(Dlona)]
| ^^^^^ help: try: `Clona`
error: cannot find derive macro `attr_proc_macra` in this scope
- --> $DIR/resolve-error.rs:56:10
+ --> $DIR/resolve-error.rs:54:10
|
LL | #[derive(attr_proc_macra)]
| ^^^^^^^^^^^^^^^
error: cannot find macro `FooWithLongNama!` in this scope
- --> $DIR/resolve-error.rs:61:5
+ --> $DIR/resolve-error.rs:59:5
|
LL | FooWithLongNama!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `FooWithLongNam`
error: cannot find macro `attr_proc_macra!` in this scope
- --> $DIR/resolve-error.rs:64:5
+ --> $DIR/resolve-error.rs:62:5
|
LL | attr_proc_macra!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `attr_proc_mac`
error: cannot find macro `Dlona!` in this scope
- --> $DIR/resolve-error.rs:67:5
+ --> $DIR/resolve-error.rs:65:5
|
LL | Dlona!();
| ^^^^^
error: cannot find macro `bang_proc_macrp!` in this scope
- --> $DIR/resolve-error.rs:70:5
+ --> $DIR/resolve-error.rs:68:5
|
LL | bang_proc_macrp!();
| ^^^^^^^^^^^^^^^ help: you could try the macro: `bang_proc_macro`
-error: aborting due to 10 previous errors
+error: aborting due to 8 previous errors
--- /dev/null
+// Copyright 2018 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.
+
+// Unresolved multi-segment attributes are not treated as custom.
+
+#![feature(custom_attribute, proc_macro_path_invoc)]
+
+mod existent {}
+
+#[existent::nonexistent] //~ ERROR failed to resolve. Could not find `nonexistent` in `existent`
+fn main() {}
--- /dev/null
+error[E0433]: failed to resolve. Could not find `nonexistent` in `existent`
+ --> $DIR/custom-attribute-multisegment.rs:17:13
+ |
+LL | #[existent::nonexistent] //~ ERROR failed to resolve. Could not find `nonexistent` in `existent`
+ | ^^^^^^^^^^^ Could not find `nonexistent` in `existent`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0433`.
#[link(name = "rust_test_helpers", kind = "static")]
extern {
returns_isize!(rust_get_test_int);
- //~^ ERROR macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
- //~^ ERROR macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
emits_nothing!();
- //~^ ERROR macro invocations in `extern {}` blocks are experimental.
+ //~^ ERROR macro invocations in `extern {}` blocks are experimental
}
-error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
--> $DIR/feature-gate-macros_in_extern.rs:29:5
|
LL | returns_isize!(rust_get_test_int);
|
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
-error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
--> $DIR/feature-gate-macros_in_extern.rs:31:5
|
LL | takes_u32_returns_u32!(rust_dbg_extern_identity_u32);
|
= help: add #![feature(macros_in_extern)] to the crate attributes to enable
-error[E0658]: macro and proc-macro invocations in `extern {}` blocks are experimental. (see issue #49476)
+error[E0658]: macro invocations in `extern {}` blocks are experimental (see issue #49476)
--> $DIR/feature-gate-macros_in_extern.rs:33:5
|
LL | emits_nothing!();