mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-02 13:07:37 +00:00
Auto merge of #53270 - petrochenkov:macuse-regr, r=alexcrichton
Fix a few regressions from enabling macro modularization The first commit restores the old behavior for some minor unstable stuff (`rustc_*` and `derive_*` attributes) and adds a new feature gate for arbitrary tokens in non-macro attributes. The second commit fixes https://github.com/rust-lang/rust/issues/53205 The third commit fixes https://github.com/rust-lang/rust/issues/53144. Same technique is used as for other things blocking expansion progress - if something causes indeterminacy too often, then prohibit it. In this case referring to crate-local macro-expanded `#[macro_export]` macros via module-relative paths is prohibited, see comments in code for more details. cc https://github.com/rust-lang/rust/pull/50911
This commit is contained in:
commit
d5a448b3f4
@ -789,7 +789,6 @@ impl<'a, 'b, 'cl> BuildReducedGraphVisitor<'a, 'b, 'cl> {
|
|||||||
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
|
fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
|
||||||
let mark = id.placeholder_to_mark();
|
let mark = id.placeholder_to_mark();
|
||||||
self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
|
self.resolver.current_module.unresolved_invocations.borrow_mut().insert(mark);
|
||||||
self.resolver.unresolved_invocations_macro_export.insert(mark);
|
|
||||||
let invocation = self.resolver.invocations[&mark];
|
let invocation = self.resolver.invocations[&mark];
|
||||||
invocation.module.set(self.resolver.current_module);
|
invocation.module.set(self.resolver.current_module);
|
||||||
invocation.legacy_scope.set(self.legacy_scope);
|
invocation.legacy_scope.set(self.legacy_scope);
|
||||||
|
@ -1385,6 +1385,8 @@ pub struct Resolver<'a, 'b: 'a> {
|
|||||||
use_injections: Vec<UseError<'a>>,
|
use_injections: Vec<UseError<'a>>,
|
||||||
/// `use` injections for proc macros wrongly imported with #[macro_use]
|
/// `use` injections for proc macros wrongly imported with #[macro_use]
|
||||||
proc_mac_errors: Vec<macros::ProcMacError>,
|
proc_mac_errors: Vec<macros::ProcMacError>,
|
||||||
|
/// crate-local macro expanded `macro_export` referred to by a module-relative path
|
||||||
|
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
|
||||||
|
|
||||||
gated_errors: FxHashSet<Span>,
|
gated_errors: FxHashSet<Span>,
|
||||||
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
|
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
|
||||||
@ -1432,9 +1434,6 @@ pub struct Resolver<'a, 'b: 'a> {
|
|||||||
|
|
||||||
/// Only supposed to be used by rustdoc, otherwise should be false.
|
/// Only supposed to be used by rustdoc, otherwise should be false.
|
||||||
pub ignore_extern_prelude_feature: bool,
|
pub ignore_extern_prelude_feature: bool,
|
||||||
|
|
||||||
/// Macro invocations in the whole crate that can expand into a `#[macro_export] macro_rules`.
|
|
||||||
unresolved_invocations_macro_export: FxHashSet<Mark>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Nothing really interesting here, it just provides memory for the rest of the crate.
|
/// Nothing really interesting here, it just provides memory for the rest of the crate.
|
||||||
@ -1706,6 +1705,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
proc_mac_errors: Vec::new(),
|
proc_mac_errors: Vec::new(),
|
||||||
gated_errors: FxHashSet(),
|
gated_errors: FxHashSet(),
|
||||||
disallowed_shadowing: Vec::new(),
|
disallowed_shadowing: Vec::new(),
|
||||||
|
macro_expanded_macro_export_errors: BTreeSet::new(),
|
||||||
|
|
||||||
arenas,
|
arenas,
|
||||||
dummy_binding: arenas.alloc_name_binding(NameBinding {
|
dummy_binding: arenas.alloc_name_binding(NameBinding {
|
||||||
@ -1737,7 +1737,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
current_type_ascription: Vec::new(),
|
current_type_ascription: Vec::new(),
|
||||||
injected_crate: None,
|
injected_crate: None,
|
||||||
ignore_extern_prelude_feature: false,
|
ignore_extern_prelude_feature: false,
|
||||||
unresolved_invocations_macro_export: FxHashSet(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4126,6 +4125,7 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
ns: Namespace,
|
ns: Namespace,
|
||||||
module: Module<'a>,
|
module: Module<'a>,
|
||||||
found_traits: &mut Vec<TraitCandidate>) {
|
found_traits: &mut Vec<TraitCandidate>) {
|
||||||
|
assert!(ns == TypeNS || ns == ValueNS);
|
||||||
let mut traits = module.traits.borrow_mut();
|
let mut traits = module.traits.borrow_mut();
|
||||||
if traits.is_none() {
|
if traits.is_none() {
|
||||||
let mut collected_traits = Vec::new();
|
let mut collected_traits = Vec::new();
|
||||||
@ -4371,6 +4371,14 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
|||||||
self.report_proc_macro_import(krate);
|
self.report_proc_macro_import(krate);
|
||||||
let mut reported_spans = FxHashSet();
|
let mut reported_spans = FxHashSet();
|
||||||
|
|
||||||
|
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
|
||||||
|
let msg = "macro-expanded `macro_export` macros from the current crate \
|
||||||
|
cannot be referred to by absolute paths";
|
||||||
|
self.session.struct_span_err(span_use, msg)
|
||||||
|
.span_note(span_def, "the macro is defined here")
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
|
||||||
for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
|
for &AmbiguityError { span, name, b1, b2, lexical } in &self.ambiguity_errors {
|
||||||
if !reported_spans.insert(span) { continue }
|
if !reported_spans.insert(span) { continue }
|
||||||
let participle = |binding: &NameBinding| {
|
let participle = |binding: &NameBinding| {
|
||||||
|
@ -28,6 +28,7 @@ use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
|
|||||||
use syntax::ext::hygiene::{self, Mark};
|
use syntax::ext::hygiene::{self, Mark};
|
||||||
use syntax::ext::tt::macro_rules;
|
use syntax::ext::tt::macro_rules;
|
||||||
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
|
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
|
||||||
|
use syntax::feature_gate::EXPLAIN_DERIVE_UNDERSCORE;
|
||||||
use syntax::fold::{self, Folder};
|
use syntax::fold::{self, Folder};
|
||||||
use syntax::parse::parser::PathStyle;
|
use syntax::parse::parser::PathStyle;
|
||||||
use syntax::parse::token::{self, Token};
|
use syntax::parse::token::{self, Token};
|
||||||
@ -195,9 +196,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
|
|||||||
|
|
||||||
self.current_module = invocation.module.get();
|
self.current_module = invocation.module.get();
|
||||||
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
|
self.current_module.unresolved_invocations.borrow_mut().remove(&mark);
|
||||||
self.unresolved_invocations_macro_export.remove(&mark);
|
|
||||||
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
|
self.current_module.unresolved_invocations.borrow_mut().extend(derives);
|
||||||
self.unresolved_invocations_macro_export.extend(derives);
|
|
||||||
for &derive in derives {
|
for &derive in derives {
|
||||||
self.invocations.insert(derive, invocation);
|
self.invocations.insert(derive, invocation);
|
||||||
}
|
}
|
||||||
@ -338,19 +337,37 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
|
|||||||
match attr_kind {
|
match attr_kind {
|
||||||
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
|
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
|
||||||
NonMacroAttrKind::Custom if is_attr_invoc => {
|
NonMacroAttrKind::Custom if is_attr_invoc => {
|
||||||
|
let features = self.session.features_untracked();
|
||||||
if attr_kind == NonMacroAttrKind::Tool &&
|
if attr_kind == NonMacroAttrKind::Tool &&
|
||||||
!self.session.features_untracked().tool_attributes {
|
!features.tool_attributes {
|
||||||
feature_err(&self.session.parse_sess, "tool_attributes",
|
feature_err(&self.session.parse_sess, "tool_attributes",
|
||||||
invoc.span(), GateIssue::Language,
|
invoc.span(), GateIssue::Language,
|
||||||
"tool attributes are unstable").emit();
|
"tool attributes are unstable").emit();
|
||||||
}
|
}
|
||||||
if attr_kind == NonMacroAttrKind::Custom &&
|
if attr_kind == NonMacroAttrKind::Custom {
|
||||||
!self.session.features_untracked().custom_attribute {
|
assert!(path.segments.len() == 1);
|
||||||
let msg = format!("The attribute `{}` is currently unknown to the compiler \
|
let name = path.segments[0].ident.name.as_str();
|
||||||
and may have meaning added to it in the future", path);
|
if name.starts_with("rustc_") {
|
||||||
|
if !features.rustc_attrs {
|
||||||
|
let msg = "unless otherwise specified, attributes with the prefix \
|
||||||
|
`rustc_` are reserved for internal compiler diagnostics";
|
||||||
|
feature_err(&self.session.parse_sess, "rustc_attrs", invoc.span(),
|
||||||
|
GateIssue::Language, &msg).emit();
|
||||||
|
}
|
||||||
|
} else if name.starts_with("derive_") {
|
||||||
|
if !features.custom_derive {
|
||||||
|
feature_err(&self.session.parse_sess, "custom_derive", invoc.span(),
|
||||||
|
GateIssue::Language, EXPLAIN_DERIVE_UNDERSCORE).emit();
|
||||||
|
}
|
||||||
|
} else if !features.custom_attribute {
|
||||||
|
let msg = format!("The attribute `{}` is currently unknown to the \
|
||||||
|
compiler and may have meaning added to it in the \
|
||||||
|
future", path);
|
||||||
feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
|
feature_err(&self.session.parse_sess, "custom_attribute", invoc.span(),
|
||||||
GateIssue::Language, &msg).emit();
|
GateIssue::Language, &msg).emit();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
|
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
|
||||||
mark_used: attr_kind == NonMacroAttrKind::Tool,
|
mark_used: attr_kind == NonMacroAttrKind::Tool,
|
||||||
})));
|
})));
|
||||||
@ -650,7 +667,10 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
WhereToResolve::BuiltinAttrs => {
|
WhereToResolve::BuiltinAttrs => {
|
||||||
if is_builtin_attr_name(ident.name) {
|
// FIXME: Only built-in attributes are not considered as candidates for
|
||||||
|
// non-attributes to fight off regressions on stable channel (#53205).
|
||||||
|
// We need to come up with some more principled approach instead.
|
||||||
|
if is_attr && is_builtin_attr_name(ident.name) {
|
||||||
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
|
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
|
||||||
ty::Visibility::Public, ident.span, Mark::root())
|
ty::Visibility::Public, ident.span, Mark::root())
|
||||||
.to_name_binding(self.arenas);
|
.to_name_binding(self.arenas);
|
||||||
|
@ -146,6 +146,14 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
|
.map_err(|_| Determined)?; // This happens when there is a cycle of imports
|
||||||
|
|
||||||
|
if let Some(binding) = resolution.binding {
|
||||||
|
if !restricted_shadowing && binding.expansion != Mark::root() {
|
||||||
|
if let NameBindingKind::Def(_, true) = binding.kind {
|
||||||
|
self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if record_used {
|
if record_used {
|
||||||
if let Some(binding) = resolution.binding {
|
if let Some(binding) = resolution.binding {
|
||||||
if let Some(shadowed_glob) = resolution.shadowed_glob {
|
if let Some(shadowed_glob) = resolution.shadowed_glob {
|
||||||
@ -211,9 +219,15 @@ impl<'a, 'crateloader> Resolver<'a, 'crateloader> {
|
|||||||
// if it cannot be shadowed by some new item/import expanded from a macro.
|
// if it cannot be shadowed by some new item/import expanded from a macro.
|
||||||
// This happens either if there are no unexpanded macros, or expanded names cannot
|
// This happens either if there are no unexpanded macros, or expanded names cannot
|
||||||
// shadow globs (that happens in macro namespace or with restricted shadowing).
|
// shadow globs (that happens in macro namespace or with restricted shadowing).
|
||||||
let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty() ||
|
//
|
||||||
(ns == MacroNS && ptr::eq(module, self.graph_root) &&
|
// Additionally, any macro in any module can plant names in the root module if it creates
|
||||||
!self.unresolved_invocations_macro_export.is_empty());
|
// `macro_export` macros, so the root module effectively has unresolved invocations if any
|
||||||
|
// module has unresolved invocations.
|
||||||
|
// However, it causes resolution/expansion to stuck too often (#53144), so, to make
|
||||||
|
// progress, we have to ignore those potential unresolved invocations from other modules
|
||||||
|
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
|
||||||
|
// shadowing is enabled, see `macro_expanded_macro_export_errors`).
|
||||||
|
let unexpanded_macros = !module.unresolved_invocations.borrow().is_empty();
|
||||||
if let Some(binding) = resolution.binding {
|
if let Some(binding) = resolution.binding {
|
||||||
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
|
if !unexpanded_macros || ns == MacroNS || restricted_shadowing {
|
||||||
return check_usable(self, binding);
|
return check_usable(self, binding);
|
||||||
|
@ -90,7 +90,7 @@ macro_rules! declare_features {
|
|||||||
self.macros_in_extern || self.proc_macro_path_invoc ||
|
self.macros_in_extern || self.proc_macro_path_invoc ||
|
||||||
self.proc_macro_mod || self.proc_macro_expr ||
|
self.proc_macro_mod || self.proc_macro_expr ||
|
||||||
self.proc_macro_non_items || self.proc_macro_gen ||
|
self.proc_macro_non_items || self.proc_macro_gen ||
|
||||||
self.stmt_expr_attributes
|
self.stmt_expr_attributes || self.unrestricted_attribute_tokens
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -504,6 +504,9 @@ declare_features! (
|
|||||||
// impl<I:Iterator> Iterator for &mut Iterator
|
// impl<I:Iterator> Iterator for &mut Iterator
|
||||||
// impl Debug for Foo<'_>
|
// impl Debug for Foo<'_>
|
||||||
(active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
|
(active, impl_header_lifetime_elision, "1.30.0", Some(15872), Some(Edition::Edition2018)),
|
||||||
|
|
||||||
|
// Support for arbitrary delimited token streams in non-macro attributes.
|
||||||
|
(active, unrestricted_attribute_tokens, "1.30.0", Some(44690), None),
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_features! (
|
declare_features! (
|
||||||
@ -721,8 +724,7 @@ pub fn is_builtin_attr_name(name: ast::Name) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
|
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
|
||||||
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name) ||
|
BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name)
|
||||||
attr.name().as_str().starts_with("rustc_")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attributes that have a special meaning to rustc or rustdoc
|
// Attributes that have a special meaning to rustc or rustdoc
|
||||||
@ -1521,27 +1523,29 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match attr.parse_meta(self.context.parse_sess) {
|
||||||
|
Ok(meta) => {
|
||||||
// allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
|
// allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
|
||||||
let mut allow_attr_literal = false;
|
let mut allow_attr_literal = false;
|
||||||
if attr.path == "repr" {
|
if attr.path == "repr" {
|
||||||
if let Some(content) = attr.meta_item_list() {
|
if let Some(content) = meta.meta_item_list() {
|
||||||
allow_attr_literal = content.iter().any(
|
allow_attr_literal = content.iter().any(
|
||||||
|c| c.check_name("align") || c.check_name("packed"));
|
|c| c.check_name("align") || c.check_name("packed"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.context.features.use_extern_macros() && attr::is_known(attr) {
|
if !allow_attr_literal && contains_novel_literal(&meta) {
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if !allow_attr_literal {
|
|
||||||
let meta = panictry!(attr.parse_meta(self.context.parse_sess));
|
|
||||||
if contains_novel_literal(&meta) {
|
|
||||||
gate_feature_post!(&self, attr_literals, attr.span,
|
gate_feature_post!(&self, attr_literals, attr.span,
|
||||||
"non-string literals in attributes, or string \
|
"non-string literals in attributes, or string \
|
||||||
literals in top-level positions, are experimental");
|
literals in top-level positions, are experimental");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(mut err) => {
|
||||||
|
err.cancel();
|
||||||
|
gate_feature_post!(&self, unrestricted_attribute_tokens, attr.span,
|
||||||
|
"arbitrary tokens in non-macro attributes are unstable");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_name(&mut self, sp: Span, name: ast::Name) {
|
fn visit_name(&mut self, sp: Span, name: ast::Name) {
|
||||||
|
@ -21,7 +21,7 @@ extern crate derive_b;
|
|||||||
#[C] //~ ERROR: The attribute `C` is currently unknown to the compiler
|
#[C] //~ ERROR: The attribute `C` is currently unknown to the compiler
|
||||||
#[B(D)]
|
#[B(D)]
|
||||||
#[B(E = "foo")]
|
#[B(E = "foo")]
|
||||||
#[B arbitrary tokens] //~ expected one of `(` or `=`, found `arbitrary`
|
#[B arbitrary tokens] //~ ERROR arbitrary tokens in non-macro attributes are unstable
|
||||||
struct B;
|
struct B;
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -11,37 +11,33 @@
|
|||||||
// Check that literals in attributes don't parse without the feature gate.
|
// Check that literals in attributes don't parse without the feature gate.
|
||||||
|
|
||||||
// gate-test-attr_literals
|
// gate-test-attr_literals
|
||||||
// gate-test-custom_attribute
|
|
||||||
|
|
||||||
#![feature(rustc_attrs)]
|
#![feature(custom_attribute)]
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr] // OK
|
||||||
#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(100)]
|
||||||
//~^ ERROR non-string literals in attributes
|
//~^ ERROR non-string literals in attributes
|
||||||
#[fake_attr(1, 2, 3)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(1, 2, 3)]
|
||||||
//~^ ERROR non-string literals in attributes
|
//~^ ERROR non-string literals in attributes
|
||||||
#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr("hello")]
|
||||||
//~^ ERROR string literals in top-level positions, are experimental
|
//~^ ERROR string literals in top-level positions, are experimental
|
||||||
#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(name = "hello")] // OK
|
||||||
#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(1, "hi", key = 12, true, false)]
|
||||||
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
|
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
|
||||||
#[fake_attr(key = "hello", val = 10)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(key = "hello", val = 10)]
|
||||||
//~^ ERROR non-string literals in attributes
|
//~^ ERROR non-string literals in attributes
|
||||||
#[fake_attr(key("hello"), val(10))] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(key("hello"), val(10))]
|
||||||
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
|
//~^ ERROR non-string literals in attributes, or string literals in top-level positions
|
||||||
#[fake_attr(enabled = true, disabled = false)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(enabled = true, disabled = false)]
|
||||||
//~^ ERROR non-string literals in attributes
|
//~^ ERROR non-string literals in attributes
|
||||||
#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(true)]
|
||||||
//~^ ERROR non-string literals in attributes
|
//~^ ERROR non-string literals in attributes
|
||||||
#[fake_attr(pi = 3.14159)] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(pi = 3.14159)]
|
||||||
//~^ ERROR non-string literals in attributes
|
//~^ ERROR non-string literals in attributes
|
||||||
#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
|
#[fake_attr(b"hi")]
|
||||||
//~^ ERROR string literals in top-level positions, are experimental
|
//~^ ERROR string literals in top-level positions, are experimental
|
||||||
#[fake_doc(r"doc")] //~ ERROR attribute `fake_doc` is currently unknown
|
#[fake_doc(r"doc")]
|
||||||
//~^ ERROR string literals in top-level positions, are experimental
|
//~^ ERROR string literals in top-level positions, are experimental
|
||||||
struct Q { }
|
struct Q { }
|
||||||
|
|
||||||
#[rustc_error]
|
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
#[doc = $not_there] //~ error: unexpected token: `$`
|
#[doc = $not_there] //~ ERROR arbitrary tokens in non-macro attributes are unstable
|
||||||
fn main() { }
|
fn main() { }
|
||||||
|
@ -9,5 +9,5 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
// asterisk is bogus
|
// asterisk is bogus
|
||||||
#[path*] //~ ERROR expected one of `(` or `=`
|
#[path*] //~ ERROR arbitrary tokens in non-macro attributes are unstable
|
||||||
mod m {}
|
mod m {}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
// aux-build:derive-b.rs
|
// aux-build:derive-b.rs
|
||||||
// ignore-stage1
|
// ignore-stage1
|
||||||
|
|
||||||
#![feature(proc_macro_path_invoc)]
|
#![feature(proc_macro_path_invoc, unrestricted_attribute_tokens)]
|
||||||
|
|
||||||
extern crate derive_b;
|
extern crate derive_b;
|
||||||
|
|
||||||
|
18
src/test/ui/feature-gate-rustc-attrs-1.rs
Normal file
18
src/test/ui/feature-gate-rustc-attrs-1.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2015 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.
|
||||||
|
|
||||||
|
// ignore-tidy-linelength
|
||||||
|
|
||||||
|
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
|
||||||
|
|
||||||
|
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
|
||||||
|
#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
|
||||||
|
|
||||||
|
fn main() {}
|
19
src/test/ui/feature-gate-rustc-attrs-1.stderr
Normal file
19
src/test/ui/feature-gate-rustc-attrs-1.stderr
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
|
||||||
|
--> $DIR/feature-gate-rustc-attrs-1.rs:15:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
|
||||||
|
--> $DIR/feature-gate-rustc-attrs-1.rs:16:1
|
||||||
|
|
|
||||||
|
LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
|
||||||
|
| ^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0658`.
|
@ -12,8 +12,6 @@
|
|||||||
|
|
||||||
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
|
// Test that `#[rustc_*]` attributes are gated by `rustc_attrs` feature gate.
|
||||||
|
|
||||||
#[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
|
|
||||||
#[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
|
|
||||||
#[rustc_foo]
|
#[rustc_foo]
|
||||||
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
|
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
|
||||||
|
|
||||||
|
@ -1,27 +1,11 @@
|
|||||||
error[E0658]: the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
|
|
||||||
--> $DIR/feature-gate-rustc-attrs.rs:15:1
|
|
||||||
|
|
|
||||||
LL | #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
|
|
||||||
| ^^^^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable (see issue #29642)
|
|
||||||
--> $DIR/feature-gate-rustc-attrs.rs:16:1
|
|
||||||
|
|
|
||||||
LL | #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
|
|
||||||
| ^^^^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
|
||||||
|
|
||||||
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
|
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics (see issue #29642)
|
||||||
--> $DIR/feature-gate-rustc-attrs.rs:17:1
|
--> $DIR/feature-gate-rustc-attrs.rs:15:1
|
||||||
|
|
|
|
||||||
LL | #[rustc_foo]
|
LL | #[rustc_foo]
|
||||||
| ^^^^^^^^^^^^
|
| ^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0658`.
|
For more information about this error, try `rustc --explain E0658`.
|
||||||
|
17
src/test/ui/feature-gate-unrestricted-attribute-tokens.rs
Normal file
17
src/test/ui/feature-gate-unrestricted-attribute-tokens.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#![feature(custom_attribute)]
|
||||||
|
|
||||||
|
#[my_attr(a b c d)]
|
||||||
|
//~^ ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
|
||||||
|
//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
|
||||||
|
//~| ERROR expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
|
||||||
|
fn main() {}
|
@ -0,0 +1,20 @@
|
|||||||
|
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `b`
|
||||||
|
--> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:13
|
||||||
|
|
|
||||||
|
LL | #[my_attr(a b c d)]
|
||||||
|
| ^ expected one of `(`, `)`, `,`, `::`, or `=` here
|
||||||
|
|
||||||
|
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `c`
|
||||||
|
--> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:15
|
||||||
|
|
|
||||||
|
LL | #[my_attr(a b c d)]
|
||||||
|
| ^ expected one of `(`, `)`, `,`, `::`, or `=` here
|
||||||
|
|
||||||
|
error: expected one of `(`, `)`, `,`, `::`, or `=`, found `d`
|
||||||
|
--> $DIR/feature-gate-unrestricted-attribute-tokens.rs:13:17
|
||||||
|
|
|
||||||
|
LL | #[my_attr(a b c d)]
|
||||||
|
| ^ expected one of `(`, `)`, `,`, `::`, or `=` here
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
32
src/test/ui/imports/local-modularized-tricky-fail-3.rs
Normal file
32
src/test/ui/imports/local-modularized-tricky-fail-3.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// Crate-local macro expanded `macro_export` macros cannot be accessed with module-relative paths.
|
||||||
|
|
||||||
|
#![feature(use_extern_macros)]
|
||||||
|
|
||||||
|
macro_rules! define_exported { () => {
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! exported {
|
||||||
|
() => ()
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
define_exported!();
|
||||||
|
|
||||||
|
mod m {
|
||||||
|
use exported;
|
||||||
|
//~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
::exported!();
|
||||||
|
//~^ ERROR macro-expanded `macro_export` macros from the current crate cannot
|
||||||
|
}
|
36
src/test/ui/imports/local-modularized-tricky-fail-3.stderr
Normal file
36
src/test/ui/imports/local-modularized-tricky-fail-3.stderr
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
|
||||||
|
--> $DIR/local-modularized-tricky-fail-3.rs:25:9
|
||||||
|
|
|
||||||
|
LL | use exported;
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the macro is defined here
|
||||||
|
--> $DIR/local-modularized-tricky-fail-3.rs:17:5
|
||||||
|
|
|
||||||
|
LL | / macro_rules! exported {
|
||||||
|
LL | | () => ()
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
...
|
||||||
|
LL | define_exported!();
|
||||||
|
| ------------------- in this macro invocation
|
||||||
|
|
||||||
|
error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths
|
||||||
|
--> $DIR/local-modularized-tricky-fail-3.rs:30:5
|
||||||
|
|
|
||||||
|
LL | ::exported!();
|
||||||
|
| ^^^^^^^^^^
|
||||||
|
|
|
||||||
|
note: the macro is defined here
|
||||||
|
--> $DIR/local-modularized-tricky-fail-3.rs:17:5
|
||||||
|
|
|
||||||
|
LL | / macro_rules! exported {
|
||||||
|
LL | | () => ()
|
||||||
|
LL | | }
|
||||||
|
| |_____^
|
||||||
|
...
|
||||||
|
LL | define_exported!();
|
||||||
|
| ------------------- in this macro invocation
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
@ -10,5 +10,5 @@
|
|||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
concat!(test!());
|
concat!(test!());
|
||||||
//~^ ERROR expected a macro, found built-in attribute
|
//~^ ERROR cannot find macro `test!` in this scope
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: expected a macro, found built-in attribute
|
error: cannot find macro `test!` in this scope
|
||||||
--> $DIR/issue-11692-2.rs:12:13
|
--> $DIR/issue-11692-2.rs:12:13
|
||||||
|
|
|
|
||||||
LL | concat!(test!());
|
LL | concat!(test!());
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
#![feature(use_extern_macros)]
|
#![feature(use_extern_macros)]
|
||||||
|
|
||||||
#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
|
#[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
|
||||||
struct S;
|
struct S;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
inline!(); //~ ERROR expected a macro, found built-in attribute
|
inline!(); //~ ERROR cannot find macro `inline!` in this scope
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
error: expected a macro, found built-in attribute
|
error: cannot find derive macro `inline` in this scope
|
||||||
--> $DIR/macro-path-prelude-fail-3.rs:13:10
|
--> $DIR/macro-path-prelude-fail-3.rs:13:10
|
||||||
|
|
|
|
||||||
LL | #[derive(inline)] //~ ERROR expected a macro, found built-in attribute
|
LL | #[derive(inline)] //~ ERROR cannot find derive macro `inline` in this scope
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: expected a macro, found built-in attribute
|
error: cannot find macro `inline!` in this scope
|
||||||
--> $DIR/macro-path-prelude-fail-3.rs:17:5
|
--> $DIR/macro-path-prelude-fail-3.rs:17:5
|
||||||
|
|
|
|
||||||
LL | inline!(); //~ ERROR expected a macro, found built-in attribute
|
LL | inline!(); //~ ERROR cannot find macro `inline!` in this scope
|
||||||
| ^^^^^^
|
| ^^^^^^ help: you could try the macro: `line`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
@ -21,7 +21,9 @@ add_macro_expanded_things_to_macro_prelude!();
|
|||||||
|
|
||||||
mod m1 {
|
mod m1 {
|
||||||
fn check() {
|
fn check() {
|
||||||
inline!(); //~ ERROR `inline` is ambiguous
|
inline!(); // OK. Theoretically ambiguous, but we do not consider built-in attributes
|
||||||
|
// as candidates for non-attribute macro invocations to avoid regressions
|
||||||
|
// on stable channel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,42 +1,21 @@
|
|||||||
error[E0659]: `inline` is ambiguous
|
|
||||||
--> $DIR/macro-path-prelude-shadowing.rs:24:9
|
|
||||||
|
|
|
||||||
LL | inline!(); //~ ERROR `inline` is ambiguous
|
|
||||||
| ^^^^^^
|
|
||||||
|
|
|
||||||
note: `inline` could refer to the name imported here
|
|
||||||
--> $DIR/macro-path-prelude-shadowing.rs:16:5
|
|
||||||
|
|
|
||||||
LL | #[macro_use]
|
|
||||||
| ^^^^^^^^^^^^
|
|
||||||
...
|
|
||||||
LL | add_macro_expanded_things_to_macro_prelude!();
|
|
||||||
| ---------------------------------------------- in this macro invocation
|
|
||||||
note: `inline` could also refer to the name defined here
|
|
||||||
--> $DIR/macro-path-prelude-shadowing.rs:24:9
|
|
||||||
|
|
|
||||||
LL | inline!(); //~ ERROR `inline` is ambiguous
|
|
||||||
| ^^^^^^
|
|
||||||
= note: macro-expanded macro imports do not shadow
|
|
||||||
|
|
||||||
error[E0659]: `std` is ambiguous
|
error[E0659]: `std` is ambiguous
|
||||||
--> $DIR/macro-path-prelude-shadowing.rs:37:9
|
--> $DIR/macro-path-prelude-shadowing.rs:39:9
|
||||||
|
|
|
|
||||||
LL | std::panic!(); //~ ERROR `std` is ambiguous
|
LL | std::panic!(); //~ ERROR `std` is ambiguous
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
|
|
||||||
note: `std` could refer to the name imported here
|
note: `std` could refer to the name imported here
|
||||||
--> $DIR/macro-path-prelude-shadowing.rs:35:9
|
--> $DIR/macro-path-prelude-shadowing.rs:37:9
|
||||||
|
|
|
|
||||||
LL | use m2::*; // glob-import user-defined `std`
|
LL | use m2::*; // glob-import user-defined `std`
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
note: `std` could also refer to the name defined here
|
note: `std` could also refer to the name defined here
|
||||||
--> $DIR/macro-path-prelude-shadowing.rs:37:9
|
--> $DIR/macro-path-prelude-shadowing.rs:39:9
|
||||||
|
|
|
|
||||||
LL | std::panic!(); //~ ERROR `std` is ambiguous
|
LL | std::panic!(); //~ ERROR `std` is ambiguous
|
||||||
| ^^^
|
| ^^^
|
||||||
= note: consider adding an explicit import of `std` to disambiguate
|
= note: consider adding an explicit import of `std` to disambiguate
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0659`.
|
For more information about this error, try `rustc --explain E0659`.
|
||||||
|
Loading…
Reference in New Issue
Block a user