diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index b0fec11bf5813a6e1e32de417f7f0b8af567b0ea..d680b2d9f7d745112bdaede946922cf5f4ae3aec 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -329,6 +329,9 @@ fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool) 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"); @@ -604,7 +607,7 @@ pub fn resolve_lexical_macro_path_segment(&mut self, // 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. @@ -789,7 +792,10 @@ enum WhereToResolve<'a> { 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); diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 72e0abfea8bd0621e177c532b3a5fb9f7676da06..12941a85669876c456c6595f774a9a502615ad14 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -516,6 +516,15 @@ fn fully_configure(&mut self, item: Annotatable) -> Annotatable { } fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option { + 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)?, @@ -549,6 +558,8 @@ fn expand_attr_invoc(&mut self, }; 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 { @@ -1482,21 +1493,7 @@ fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem) -> SmallVector { 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(); @@ -1504,12 +1501,6 @@ fn fold_foreign_item(&mut self, 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(); } @@ -1671,7 +1662,6 @@ fn enable_allow_internal_unstable = allow_internal_unstable, 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, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index a7a29edf0a04fbfaa166119d1307ab3ad7ee9415..119505896d69ad99e2773c4b58205b7d56f7c56d 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1354,13 +1354,6 @@ fn leveled_feature_err<'a>(sess: &'a ParseSess, feature: &str, span: Span, issue 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>, } @@ -1969,7 +1962,6 @@ fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) { ).emit(); } else { set(&mut features, mi.span); - feature_checker.collect(&features, mi.span); features.declared_lang_features.push((name, mi.span, None)); } continue diff --git a/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs b/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs index 8fced7d8c70da134a6a9d9988ec86be2e83cc477..f71d4b86f1e0147f40878fce5c509e519abdf654 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/issue-41211.rs @@ -15,7 +15,7 @@ #![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; diff --git a/src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs b/src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs index 9a35dc0edc4484b66d4bfb3550539b4476f0660c..e418ecc114cc1112a16e7494773a9fce987df938 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/macros-in-extern.rs @@ -26,13 +26,13 @@ fn main() { #[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 } diff --git a/src/test/compile-fail/macros-in-extern.rs b/src/test/compile-fail/macros-in-extern.rs index b6e273881ccd62636a50a64d95e1314ca4b5d0ed..40053853b15a7e2802fba2c2b88ee41abb346b6a 100644 --- a/src/test/compile-fail/macros-in-extern.rs +++ b/src/test/compile-fail/macros-in-extern.rs @@ -34,9 +34,9 @@ fn main() { #[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 } diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs index ba8c580cb0a01d1f5753ad737663b3aafb49ad72..ce157e3632c70a5f67f07331e0f9ad23e43fc3a3 100644 --- a/src/test/pretty/attr-literals.rs +++ b/src/test/pretty/attr-literals.rs @@ -18,6 +18,6 @@ fn main() { #[align = 8] fn f() { } - #[vec(1, 2, 3)] + #[vector(1, 2, 3)] fn g() { } } diff --git a/src/test/ui-fulldeps/resolve-error.rs b/src/test/ui-fulldeps/resolve-error.rs index df9b263534f605804276b984876b9bea5f0be208..1940151357c8f82a478b434f6943ce8e0394623f 100644 --- a/src/test/ui-fulldeps/resolve-error.rs +++ b/src/test/ui-fulldeps/resolve-error.rs @@ -13,7 +13,7 @@ // 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; @@ -37,12 +37,10 @@ //~^ 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)] diff --git a/src/test/ui-fulldeps/resolve-error.stderr b/src/test/ui-fulldeps/resolve-error.stderr index caa7966461487211532de3f7e9d41194b2c283bf..278409c688ab9dcfa581b523f3578aa17ed13062 100644 --- a/src/test/ui-fulldeps/resolve-error.stderr +++ b/src/test/ui-fulldeps/resolve-error.stderr @@ -4,59 +4,47 @@ error: cannot find derive macro `FooWithLongNan` in this scope 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 diff --git a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-custom-attr-mutex.rs b/src/test/ui/custom-attribute-multisegment.rs similarity index 51% rename from src/test/compile-fail-fulldeps/proc-macro/proc-macro-custom-attr-mutex.rs rename to src/test/ui/custom-attribute-multisegment.rs index 8640aa2387fd12c1336a6314e31d0fd9fc999388..ad8e0e76e14137511b0b0599eb31eb1add49bbcd 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/proc-macro-custom-attr-mutex.rs +++ b/src/test/ui/custom-attribute-multisegment.rs @@ -1,4 +1,4 @@ -// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// 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. // @@ -8,18 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// aux-build:attr_proc_macro.rs -// ignore-tidy-linelength +// Unresolved multi-segment attributes are not treated as custom. -#![feature(custom_attribute)] -//~^ ERROR Cannot use `#![feature(use_extern_macros)]` and `#![feature(custom_attribute)] at the same time +#![feature(custom_attribute, proc_macro_path_invoc)] -extern crate attr_proc_macro; -use attr_proc_macro::attr_proc_macro; +mod existent {} -#[attr_proc_macro] -fn foo() {} - -fn main() { - foo(); -} +#[existent::nonexistent] //~ ERROR failed to resolve. Could not find `nonexistent` in `existent` +fn main() {} diff --git a/src/test/ui/custom-attribute-multisegment.stderr b/src/test/ui/custom-attribute-multisegment.stderr new file mode 100644 index 0000000000000000000000000000000000000000..ff72d1c36d85244f2e93998d5330afea914043cd --- /dev/null +++ b/src/test/ui/custom-attribute-multisegment.stderr @@ -0,0 +1,9 @@ +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`. diff --git a/src/test/ui/feature-gate-macros_in_extern.rs b/src/test/ui/feature-gate-macros_in_extern.rs index 5271f75b6328cd895de19e060f2abaaff2815838..77080e3c348f99390781f48e54d0925a895311df 100644 --- a/src/test/ui/feature-gate-macros_in_extern.rs +++ b/src/test/ui/feature-gate-macros_in_extern.rs @@ -27,9 +27,9 @@ #[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 } diff --git a/src/test/ui/feature-gate-macros_in_extern.stderr b/src/test/ui/feature-gate-macros_in_extern.stderr index 5d7e01fbbb752d895d42b4468c9abfffaa5cefb5..23b63078dbf8e7c0126e210b042b40dad5a7d949 100644 --- a/src/test/ui/feature-gate-macros_in_extern.stderr +++ b/src/test/ui/feature-gate-macros_in_extern.stderr @@ -1,4 +1,4 @@ -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); @@ -6,7 +6,7 @@ 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); @@ -14,7 +14,7 @@ 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!();