Auto merge of #53461 - petrochenkov:pmu, r=alexcrichton
resolve: Do not error on access to proc macros imported with `#[macro_use]` This error is artificial, but previously, when `#[macro_use] extern crate x;` was stable, but non-derive proc macros were not, it worked like kind of a feature gate. Now both features are stable, so the error is no longer necessary. This PR simplifies how `#[macro_use] extern crate x;` works - it takes all items from macro namespace of `x`'s root and puts them into macro prelude from which they all can now be accessed.
This commit is contained in:
commit
cb6d2dfa89
6 changed files with 2 additions and 83 deletions
|
@ -1429,8 +1429,6 @@ pub struct Resolver<'a, 'b: 'a> {
|
||||||
ambiguity_errors: Vec<AmbiguityError<'a>>,
|
ambiguity_errors: Vec<AmbiguityError<'a>>,
|
||||||
/// `use` injections are delayed for better placement and deduplication
|
/// `use` injections are delayed for better placement and deduplication
|
||||||
use_injections: Vec<UseError<'a>>,
|
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
|
/// crate-local macro expanded `macro_export` referred to by a module-relative path
|
||||||
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
|
macro_expanded_macro_export_errors: BTreeSet<(Span, Span)>,
|
||||||
|
|
||||||
|
@ -1458,9 +1456,6 @@ pub struct Resolver<'a, 'b: 'a> {
|
||||||
/// Avoid duplicated errors for "name already defined".
|
/// Avoid duplicated errors for "name already defined".
|
||||||
name_already_seen: FxHashMap<Name, Span>,
|
name_already_seen: FxHashMap<Name, Span>,
|
||||||
|
|
||||||
/// A set of procedural macros imported by `#[macro_use]` that have already been warned about
|
|
||||||
warned_proc_macros: FxHashSet<Name>,
|
|
||||||
|
|
||||||
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
|
potentially_unused_imports: Vec<&'a ImportDirective<'a>>,
|
||||||
|
|
||||||
/// This table maps struct IDs into struct constructor IDs,
|
/// This table maps struct IDs into struct constructor IDs,
|
||||||
|
@ -1744,7 +1739,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
privacy_errors: Vec::new(),
|
privacy_errors: Vec::new(),
|
||||||
ambiguity_errors: Vec::new(),
|
ambiguity_errors: Vec::new(),
|
||||||
use_injections: Vec::new(),
|
use_injections: Vec::new(),
|
||||||
proc_mac_errors: Vec::new(),
|
|
||||||
macro_expanded_macro_export_errors: BTreeSet::new(),
|
macro_expanded_macro_export_errors: BTreeSet::new(),
|
||||||
|
|
||||||
arenas,
|
arenas,
|
||||||
|
@ -1766,7 +1760,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
local_macro_def_scopes: FxHashMap(),
|
local_macro_def_scopes: FxHashMap(),
|
||||||
name_already_seen: FxHashMap(),
|
name_already_seen: FxHashMap(),
|
||||||
whitelisted_legacy_custom_derives: Vec::new(),
|
whitelisted_legacy_custom_derives: Vec::new(),
|
||||||
warned_proc_macros: FxHashSet(),
|
|
||||||
potentially_unused_imports: Vec::new(),
|
potentially_unused_imports: Vec::new(),
|
||||||
struct_constructors: DefIdMap(),
|
struct_constructors: DefIdMap(),
|
||||||
found_unresolved_macro: false,
|
found_unresolved_macro: false,
|
||||||
|
@ -4602,7 +4595,6 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
|
||||||
|
|
||||||
fn report_errors(&mut self, krate: &Crate) {
|
fn report_errors(&mut self, krate: &Crate) {
|
||||||
self.report_with_use_injections(krate);
|
self.report_with_use_injections(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 {
|
for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
|
||||||
|
|
|
@ -19,7 +19,6 @@ use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, DefIndex,
|
||||||
use rustc::hir::def::{Def, NonMacroAttrKind};
|
use rustc::hir::def::{Def, NonMacroAttrKind};
|
||||||
use rustc::hir::map::{self, DefCollector};
|
use rustc::hir::map::{self, DefCollector};
|
||||||
use rustc::{ty, lint};
|
use rustc::{ty, lint};
|
||||||
use rustc::middle::cstore::CrateStore;
|
|
||||||
use syntax::ast::{self, Name, Ident};
|
use syntax::ast::{self, Name, Ident};
|
||||||
use syntax::attr;
|
use syntax::attr;
|
||||||
use syntax::errors::DiagnosticBuilder;
|
use syntax::errors::DiagnosticBuilder;
|
||||||
|
@ -110,14 +109,6 @@ pub struct ParentScope<'a> {
|
||||||
crate derives: Vec<ast::Path>,
|
crate derives: Vec<ast::Path>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ProcMacError {
|
|
||||||
crate_name: Symbol,
|
|
||||||
name: Symbol,
|
|
||||||
module: ast::NodeId,
|
|
||||||
use_span: Span,
|
|
||||||
warn_msg: &'static str,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Macro namespace is separated into two sub-namespaces, one for bang macros and
|
// Macro namespace is separated into two sub-namespaces, one for bang macros and
|
||||||
// one for attribute-like macros (attributes, derives).
|
// one for attribute-like macros (attributes, derives).
|
||||||
// We ignore resolutions from one sub-namespace when searching names in scope for another.
|
// We ignore resolutions from one sub-namespace when searching names in scope for another.
|
||||||
|
@ -980,7 +971,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
check_consistency(self, binding.def_ignoring_ambiguity());
|
check_consistency(self, binding.def_ignoring_ambiguity());
|
||||||
if from_prelude {
|
if from_prelude {
|
||||||
self.record_use(ident, MacroNS, binding);
|
self.record_use(ident, MacroNS, binding);
|
||||||
self.err_if_macro_use_proc_macro(ident.name, span, binding);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1132,69 +1122,6 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error if `ext` is a Macros 1.1 procedural macro being imported by `#[macro_use]`
|
|
||||||
fn err_if_macro_use_proc_macro(&mut self, name: Name, use_span: Span,
|
|
||||||
binding: &NameBinding<'a>) {
|
|
||||||
let krate = match binding.def() {
|
|
||||||
Def::NonMacroAttr(..) | Def::Err => return,
|
|
||||||
Def::Macro(def_id, _) => def_id.krate,
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Plugin-based syntax extensions are exempt from this check
|
|
||||||
if krate == CrateNum::BuiltinMacros { return; }
|
|
||||||
|
|
||||||
let ext = binding.get_macro(self);
|
|
||||||
|
|
||||||
match *ext {
|
|
||||||
// If `ext` is a procedural macro, check if we've already warned about it
|
|
||||||
SyntaxExtension::AttrProcMacro(..) | SyntaxExtension::ProcMacro { .. } =>
|
|
||||||
if !self.warned_proc_macros.insert(name) { return; },
|
|
||||||
_ => return,
|
|
||||||
}
|
|
||||||
|
|
||||||
let warn_msg = match *ext {
|
|
||||||
SyntaxExtension::AttrProcMacro(..) =>
|
|
||||||
"attribute procedural macros cannot be imported with `#[macro_use]`",
|
|
||||||
SyntaxExtension::ProcMacro { .. } =>
|
|
||||||
"procedural macros cannot be imported with `#[macro_use]`",
|
|
||||||
_ => return,
|
|
||||||
};
|
|
||||||
|
|
||||||
let def_id = self.current_module.normal_ancestor_id;
|
|
||||||
let node_id = self.definitions.as_local_node_id(def_id).unwrap();
|
|
||||||
|
|
||||||
self.proc_mac_errors.push(ProcMacError {
|
|
||||||
crate_name: self.cstore.crate_name_untracked(krate),
|
|
||||||
name,
|
|
||||||
module: node_id,
|
|
||||||
use_span,
|
|
||||||
warn_msg,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn report_proc_macro_import(&mut self, krate: &ast::Crate) {
|
|
||||||
for err in self.proc_mac_errors.drain(..) {
|
|
||||||
let (span, found_use) = ::UsePlacementFinder::check(krate, err.module);
|
|
||||||
|
|
||||||
if let Some(span) = span {
|
|
||||||
let found_use = if found_use { "" } else { "\n" };
|
|
||||||
self.session.struct_span_err(err.use_span, err.warn_msg)
|
|
||||||
.span_suggestion_with_applicability(
|
|
||||||
span,
|
|
||||||
"instead, import the procedural macro like any other item",
|
|
||||||
format!("use {}::{};{}", err.crate_name, err.name, found_use),
|
|
||||||
Applicability::MachineApplicable
|
|
||||||
).emit();
|
|
||||||
} else {
|
|
||||||
self.session.struct_span_err(err.use_span, err.warn_msg)
|
|
||||||
.help(&format!("instead, import the procedural macro like any other item: \
|
|
||||||
`use {}::{};`", err.crate_name, err.name))
|
|
||||||
.emit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) {
|
fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) {
|
||||||
if !self.session.features_untracked().custom_derive {
|
if !self.session.features_untracked().custom_derive {
|
||||||
let sess = &self.session.parse_sess;
|
let sess = &self.session.parse_sess;
|
||||||
|
|
|
@ -8,12 +8,12 @@
|
||||||
// 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.
|
||||||
|
|
||||||
|
// compile-pass
|
||||||
// aux-build:attr_proc_macro.rs
|
// aux-build:attr_proc_macro.rs
|
||||||
|
|
||||||
#[macro_use] extern crate attr_proc_macro;
|
#[macro_use] extern crate attr_proc_macro;
|
||||||
|
|
||||||
#[attr_proc_macro]
|
#[attr_proc_macro]
|
||||||
//~^ ERROR: attribute procedural macros cannot be imported with `#[macro_use]`
|
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
|
@ -8,6 +8,7 @@
|
||||||
// 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.
|
||||||
|
|
||||||
|
// compile-pass
|
||||||
// aux-build:bang_proc_macro.rs
|
// aux-build:bang_proc_macro.rs
|
||||||
|
|
||||||
#![feature(proc_macro_non_items)]
|
#![feature(proc_macro_non_items)]
|
||||||
|
@ -17,5 +18,4 @@ extern crate bang_proc_macro;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
bang_proc_macro!(println!("Hello, world!"));
|
bang_proc_macro!(println!("Hello, world!"));
|
||||||
//~^ ERROR: procedural macros cannot be imported with `#[macro_use]`
|
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue