fn visit_invoc(&mut self, id: ast::NodeId) -> &'b InvocationData<'b> {
let mark = id.placeholder_to_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];
invocation.module.set(self.resolver.current_module);
invocation.legacy_scope.set(self.legacy_scope);
use_injections: Vec<UseError<'a>>,
/// `use` injections for proc macros wrongly imported with #[macro_use]
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>,
disallowed_shadowing: Vec<&'a LegacyBinding<'a>>,
/// Only supposed to be used by rustdoc, otherwise should be false.
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.
proc_mac_errors: Vec::new(),
gated_errors: FxHashSet(),
disallowed_shadowing: Vec::new(),
+ macro_expanded_macro_export_errors: BTreeSet::new(),
arenas,
dummy_binding: arenas.alloc_name_binding(NameBinding {
current_type_ascription: Vec::new(),
injected_crate: None,
ignore_extern_prelude_feature: false,
- unresolved_invocations_macro_export: FxHashSet(),
}
}
ns: Namespace,
module: Module<'a>,
found_traits: &mut Vec<TraitCandidate>) {
+ assert!(ns == TypeNS || ns == ValueNS);
let mut traits = module.traits.borrow_mut();
if traits.is_none() {
let mut collected_traits = Vec::new();
self.report_proc_macro_import(krate);
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 {
if !reported_spans.insert(span) { continue }
let participle = |binding: &NameBinding| {
use syntax::ext::hygiene::{self, Mark};
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::EXPLAIN_DERIVE_UNDERSCORE;
use syntax::fold::{self, Folder};
use syntax::parse::parser::PathStyle;
use syntax::parse::token::{self, Token};
self.current_module = invocation.module.get();
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.unresolved_invocations_macro_export.extend(derives);
for &derive in derives {
self.invocations.insert(derive, invocation);
}
match attr_kind {
NonMacroAttrKind::Tool | NonMacroAttrKind::DeriveHelper |
NonMacroAttrKind::Custom if is_attr_invoc => {
+ let features = self.session.features_untracked();
if attr_kind == NonMacroAttrKind::Tool &&
- !self.session.features_untracked().tool_attributes {
+ !features.tool_attributes {
feature_err(&self.session.parse_sess, "tool_attributes",
invoc.span(), GateIssue::Language,
"tool attributes are unstable").emit();
}
- if attr_kind == NonMacroAttrKind::Custom &&
- !self.session.features_untracked().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(),
- GateIssue::Language, &msg).emit();
+ if attr_kind == NonMacroAttrKind::Custom {
+ assert!(path.segments.len() == 1);
+ let name = path.segments[0].ident.name.as_str();
+ 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(),
+ GateIssue::Language, &msg).emit();
+ }
}
+
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr {
mark_used: attr_kind == NonMacroAttrKind::Tool,
})));
}
}
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),
ty::Visibility::Public, ident.span, Mark::root())
.to_name_binding(self.arenas);
.try_borrow_mut()
.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 let Some(binding) = resolution.binding {
if let Some(shadowed_glob) = resolution.shadowed_glob {
// 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
// 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) &&
- !self.unresolved_invocations_macro_export.is_empty());
+ //
+ // Additionally, any macro in any module can plant names in the root module if it creates
+ // `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 !unexpanded_macros || ns == MacroNS || restricted_shadowing {
return check_usable(self, binding);
self.macros_in_extern || self.proc_macro_path_invoc ||
self.proc_macro_mod || self.proc_macro_expr ||
self.proc_macro_non_items || self.proc_macro_gen ||
- self.stmt_expr_attributes
+ self.stmt_expr_attributes || self.unrestricted_attribute_tokens
}
}
};
// impl<I:Iterator> Iterator for &mut Iterator
// impl Debug for Foo<'_>
(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! (
}
pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
- BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name) ||
- attr.name().as_str().starts_with("rustc_")
+ BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name)
}
// Attributes that have a special meaning to rustc or rustdoc
}
}
- // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
- let mut allow_attr_literal = false;
- if attr.path == "repr" {
- if let Some(content) = attr.meta_item_list() {
- allow_attr_literal = content.iter().any(
- |c| c.check_name("align") || c.check_name("packed"));
- }
- }
-
- if self.context.features.use_extern_macros() && attr::is_known(attr) {
- return
- }
+ match attr.parse_meta(self.context.parse_sess) {
+ Ok(meta) => {
+ // allow attr_literals in #[repr(align(x))] and #[repr(packed(n))]
+ let mut allow_attr_literal = false;
+ if attr.path == "repr" {
+ if let Some(content) = meta.meta_item_list() {
+ allow_attr_literal = content.iter().any(
+ |c| c.check_name("align") || c.check_name("packed"));
+ }
+ }
- 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,
- "non-string literals in attributes, or string \
- literals in top-level positions, are experimental");
+ if !allow_attr_literal && contains_novel_literal(&meta) {
+ gate_feature_post!(&self, attr_literals, attr.span,
+ "non-string literals in attributes, or string \
+ 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");
}
}
}
#[C] //~ ERROR: The attribute `C` is currently unknown to the compiler
#[B(D)]
#[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;
fn main() {}
// Check that literals in attributes don't parse without the feature gate.
// gate-test-attr_literals
-// gate-test-custom_attribute
-#![feature(rustc_attrs)]
-#![allow(dead_code)]
-#![allow(unused_variables)]
+#![feature(custom_attribute)]
-#[fake_attr] //~ ERROR attribute `fake_attr` is currently unknown
-#[fake_attr(100)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr] // OK
+#[fake_attr(100)]
//~^ 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
-#[fake_attr("hello")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr("hello")]
//~^ ERROR string literals in top-level positions, are experimental
-#[fake_attr(name = "hello")] //~ ERROR attribute `fake_attr` is currently unknown
-#[fake_attr(1, "hi", key = 12, true, false)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(name = "hello")] // OK
+#[fake_attr(1, "hi", key = 12, true, false)]
//~^ 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
-#[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
-#[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
-#[fake_attr(true)] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(true)]
//~^ 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
-#[fake_attr(b"hi")] //~ ERROR attribute `fake_attr` is currently unknown
+#[fake_attr(b"hi")]
//~^ 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
struct Q { }
-#[rustc_error]
fn main() { }
// option. This file may not be copied, modified, or distributed
// 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() { }
// except according to those terms.
// asterisk is bogus
-#[path*] //~ ERROR expected one of `(` or `=`
+#[path*] //~ ERROR arbitrary tokens in non-macro attributes are unstable
mod m {}
// aux-build:derive-b.rs
// ignore-stage1
-#![feature(proc_macro_path_invoc)]
+#![feature(proc_macro_path_invoc, unrestricted_attribute_tokens)]
extern crate derive_b;
--- /dev/null
+// 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() {}
--- /dev/null
+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`.
// 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]
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
-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)
- --> $DIR/feature-gate-rustc-attrs.rs:17:1
+ --> $DIR/feature-gate-rustc-attrs.rs:15:1
|
LL | #[rustc_foo]
| ^^^^^^^^^^^^
|
= 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`.
--- /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.
+
+#![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() {}
--- /dev/null
+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
+
--- /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.
+
+// 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
+}
--- /dev/null
+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
+
fn main() {
concat!(test!());
- //~^ ERROR expected a macro, found built-in attribute
+ //~^ ERROR cannot find macro `test!` in this scope
}
-error: expected a macro, found built-in attribute
+error: cannot find macro `test!` in this scope
--> $DIR/issue-11692-2.rs:12:13
|
LL | concat!(test!());
#![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;
fn main() {
- inline!(); //~ ERROR expected a macro, found built-in attribute
+ inline!(); //~ ERROR cannot find macro `inline!` in this scope
}
-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
|
-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
|
-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
mod m1 {
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
}
}
-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
- --> $DIR/macro-path-prelude-shadowing.rs:37:9
+ --> $DIR/macro-path-prelude-shadowing.rs:39:9
|
LL | std::panic!(); //~ ERROR `std` is ambiguous
| ^^^^^^^^^^
|
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`
| ^^^^^
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
| ^^^
= 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`.