Discern between various kinds of non-macro attributes

This commit is contained in:
Vadim Petrochenkov 2018-08-03 02:05:00 +03:00
parent b239743753
commit 467a7ab2b1
14 changed files with 73 additions and 40 deletions

View File

@ -28,6 +28,18 @@ pub enum CtorKind {
Fictive,
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum NonMacroAttrKind {
/// Single-segment attribute defined by the language (`#[inline]`)
Builtin,
/// Multi-segment custom attribute living in a "tool module" (`#[rustfmt::skip]`).
Tool,
/// Single-segment custom attribute registered by a derive macro (`#[serde(default)]`).
DeriveHelper,
/// Single-segment custom attribute not registered in any way (`#[my_attr]`).
Custom,
}
#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Def {
// Type namespace
@ -68,7 +80,7 @@ pub enum Def {
// Macro namespace
Macro(DefId, MacroKind),
NonMacroAttr, // e.g. `#[inline]` or `#[rustfmt::skip]`
NonMacroAttr(NonMacroAttrKind), // e.g. `#[inline]` or `#[rustfmt::skip]`
GlobalAsm(DefId),
@ -242,6 +254,17 @@ impl CtorKind {
}
}
impl NonMacroAttrKind {
fn descr(self) -> &'static str {
match self {
NonMacroAttrKind::Builtin => "built-in attribute",
NonMacroAttrKind::Tool => "tool attribute",
NonMacroAttrKind::DeriveHelper => "derive helper attribute",
NonMacroAttrKind::Custom => "custom attribute",
}
}
}
impl Def {
pub fn def_id(&self) -> DefId {
match *self {
@ -262,7 +285,7 @@ impl Def {
Def::PrimTy(..) |
Def::SelfTy(..) |
Def::ToolMod |
Def::NonMacroAttr |
Def::NonMacroAttr(..) |
Def::Err => {
bug!("attempted .def_id() on invalid def: {:?}", self)
}
@ -304,7 +327,7 @@ impl Def {
Def::Macro(.., macro_kind) => macro_kind.descr(),
Def::GlobalAsm(..) => "global asm",
Def::ToolMod => "tool module",
Def::NonMacroAttr => "non-macro attribute",
Def::NonMacroAttr(attr_kind) => attr_kind.descr(),
Def::Err => "unresolved item",
}
}

View File

@ -988,6 +988,13 @@ impl_stable_hash_for!(enum hir::def::CtorKind {
Fictive
});
impl_stable_hash_for!(enum hir::def::NonMacroAttrKind {
Builtin,
Tool,
DeriveHelper,
Custom,
});
impl_stable_hash_for!(enum hir::def::Def {
Mod(def_id),
Struct(def_id),
@ -1017,7 +1024,7 @@ impl_stable_hash_for!(enum hir::def::Def {
Macro(def_id, macro_kind),
GlobalAsm(def_id),
ToolMod,
NonMacroAttr,
NonMacroAttr(attr_kind),
Err
});

View File

@ -630,8 +630,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
pub fn get_macro(&mut self, def: Def) -> Lrc<SyntaxExtension> {
let def_id = match def {
Def::Macro(def_id, ..) => def_id,
Def::NonMacroAttr => return Lrc::new(SyntaxExtension::NonMacroAttr),
_ => panic!("Expected Def::Macro(..) or Def::NonMacroAttr"),
Def::NonMacroAttr(..) => return Lrc::new(SyntaxExtension::NonMacroAttr),
_ => panic!("expected `Def::Macro` or `Def::NonMacroAttr`"),
};
if let Some(ext) = self.macro_map.get(&def_id) {
return ext.clone();

View File

@ -3514,7 +3514,8 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
if let Some(next_module) = binding.module() {
module = Some(next_module);
} else if def == Def::ToolMod && i + 1 != path.len() {
return PathResult::NonModule(PathResolution::new(Def::NonMacroAttr))
let def = Def::NonMacroAttr(NonMacroAttrKind::Tool);
return PathResult::NonModule(PathResolution::new(def));
} else if def == Def::Err {
return PathResult::NonModule(err_path_resolution());
} else if opt_ns.is_some() && (is_last || maybe_assoc) {

View File

@ -15,7 +15,7 @@ use build_reduced_graph::{BuildReducedGraphVisitor, IsMacroExport};
use resolve_imports::ImportResolver;
use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex,
DefIndexAddressSpace};
use rustc::hir::def::{Def, Export};
use rustc::hir::def::{Def, Export, NonMacroAttrKind};
use rustc::hir::map::{self, DefCollector};
use rustc::{ty, lint};
use rustc::middle::cstore::CrateStore;
@ -329,8 +329,9 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
self.report_proc_macro_stub(invoc.span());
return Err(Determinacy::Determined);
} else if let Def::NonMacroAttr = def {
if let InvocationKind::Attr { .. } = invoc.kind {
} else if let Def::NonMacroAttr(attr_kind) = def {
let is_attr = if let InvocationKind::Attr { .. } = invoc.kind { true } else { false };
if is_attr && attr_kind == NonMacroAttrKind::Tool {
if !self.session.features_untracked().tool_attributes {
feature_err(&self.session.parse_sess, "tool_attributes",
invoc.span(), GateIssue::Language,
@ -338,7 +339,7 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
}
return Ok(Some(Lrc::new(SyntaxExtension::NonMacroAttr)));
} else {
self.report_non_macro_attr(invoc.path_span());
self.report_non_macro_attr(invoc.path_span(), def);
return Err(Determinacy::Determined);
}
}
@ -363,8 +364,8 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
if let Def::Macro(_, MacroKind::ProcMacroStub) = def {
self.report_proc_macro_stub(path.span);
return Err(Determinacy::Determined);
} else if let Def::NonMacroAttr = def {
self.report_non_macro_attr(path.span);
} else if let Def::NonMacroAttr(..) = def {
self.report_non_macro_attr(path.span, def);
return Err(Determinacy::Determined);
}
self.unused_macros.remove(&def.def_id());
@ -396,9 +397,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
"can't use a procedural macro from the same crate that defines it");
}
fn report_non_macro_attr(&self, span: Span) {
self.session.span_err(span,
"expected a macro, found non-macro attribute");
fn report_non_macro_attr(&self, span: Span, def: Def) {
self.session.span_err(span, &format!("expected a macro, found {}", def.kind_name()));
}
fn resolve_invoc_to_def(&mut self, invoc: &mut Invocation, scope: Mark, force: bool)
@ -481,7 +481,8 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
"generic arguments in macro path");
});
}
if kind != MacroKind::Bang && path.segments.len() > 1 && def != Ok(Def::NonMacroAttr) {
if kind != MacroKind::Bang && path.segments.len() > 1 &&
def != Ok(Def::NonMacroAttr(NonMacroAttrKind::Tool)) {
if !self.session.features_untracked().proc_macro_path_invoc {
emit_feature_err(
&self.session.parse_sess,
@ -647,8 +648,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
}
WhereToResolve::BuiltinAttrs => {
if is_builtin_attr_name(ident.name) {
let binding = (Def::NonMacroAttr, ty::Visibility::Public,
ident.span, Mark::root()).to_name_binding(self.arenas);
let binding = (Def::NonMacroAttr(NonMacroAttrKind::Builtin),
ty::Visibility::Public, ident.span, Mark::root())
.to_name_binding(self.arenas);
Ok(MacroBinding::Global(binding))
} else {
Err(Determinacy::Determined)

View File

@ -812,7 +812,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
HirDef::Macro(..) |
HirDef::GlobalAsm(..) |
HirDef::ToolMod |
HirDef::NonMacroAttr |
HirDef::NonMacroAttr(..) |
HirDef::Err => None,
}
}

View File

@ -10,5 +10,5 @@
fn main() {
concat!(test!());
//~^ ERROR expected a macro, found non-macro attribute
//~^ ERROR expected a macro, found built-in attribute
}

View File

@ -1,4 +1,4 @@
error: expected a macro, found non-macro attribute
error: expected a macro, found built-in attribute
--> $DIR/issue-11692-2.rs:12:13
|
LL | concat!(test!());

View File

@ -10,9 +10,9 @@
#![feature(use_extern_macros)]
#[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
#[derive(inline)] //~ ERROR expected a macro, found built-in attribute
struct S;
fn main() {
inline!(); //~ ERROR expected a macro, found non-macro attribute
inline!(); //~ ERROR expected a macro, found built-in attribute
}

View File

@ -1,13 +1,13 @@
error: expected a macro, found non-macro attribute
error: expected a macro, found built-in attribute
--> $DIR/macro-path-prelude-fail-3.rs:13:10
|
LL | #[derive(inline)] //~ ERROR expected a macro, found non-macro attribute
LL | #[derive(inline)] //~ ERROR expected a macro, found built-in attribute
| ^^^^^^
error: expected a macro, found non-macro attribute
error: expected a macro, found built-in attribute
--> $DIR/macro-path-prelude-fail-3.rs:17:5
|
LL | inline!(); //~ ERROR expected a macro, found non-macro attribute
LL | inline!(); //~ ERROR expected a macro, found built-in attribute
| ^^^^^^
error: aborting due to 2 previous errors

View File

@ -11,7 +11,7 @@
#![feature(tool_attributes)]
type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip`
#[derive(rustfmt)] //~ ERROR cannot find derive macro `rustfmt` in this scope
struct S;
@ -24,5 +24,5 @@ fn main() {
rustfmt; //~ ERROR expected value, found tool module `rustfmt`
rustfmt!(); //~ ERROR cannot find macro `rustfmt!` in this scope
rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip`
}

View File

@ -22,10 +22,10 @@ error[E0573]: expected type, found tool module `rustfmt`
LL | type A = rustfmt; //~ ERROR expected type, found tool module `rustfmt`
| ^^^^^^^ not a type
error[E0573]: expected type, found non-macro attribute `rustfmt::skip`
error[E0573]: expected type, found tool attribute `rustfmt::skip`
--> $DIR/tool-attributes-misplaced-1.rs:14:10
|
LL | type B = rustfmt::skip; //~ ERROR expected type, found non-macro attribute `rustfmt::skip`
LL | type B = rustfmt::skip; //~ ERROR expected type, found tool attribute `rustfmt::skip`
| ^^^^^^^^^^^^^ not a type
error[E0423]: expected value, found tool module `rustfmt`
@ -34,10 +34,10 @@ error[E0423]: expected value, found tool module `rustfmt`
LL | rustfmt; //~ ERROR expected value, found tool module `rustfmt`
| ^^^^^^^ not a value
error[E0423]: expected value, found non-macro attribute `rustfmt::skip`
error[E0423]: expected value, found tool attribute `rustfmt::skip`
--> $DIR/tool-attributes-misplaced-1.rs:27:5
|
LL | rustfmt::skip; //~ ERROR expected value, found non-macro attribute `rustfmt::skip`
LL | rustfmt::skip; //~ ERROR expected value, found tool attribute `rustfmt::skip`
| ^^^^^^^^^^^^^ not a value
error: aborting due to 7 previous errors

View File

@ -10,9 +10,9 @@
#![feature(tool_attributes)]
#[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
#[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
struct S;
fn main() {
rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
}

View File

@ -1,13 +1,13 @@
error: expected a macro, found non-macro attribute
error: expected a macro, found tool attribute
--> $DIR/tool-attributes-misplaced-2.rs:13:10
|
LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found non-macro attribute
LL | #[derive(rustfmt::skip)] //~ ERROR expected a macro, found tool attribute
| ^^^^^^^^^^^^^
error: expected a macro, found non-macro attribute
error: expected a macro, found tool attribute
--> $DIR/tool-attributes-misplaced-2.rs:17:5
|
LL | rustfmt::skip!(); //~ ERROR expected a macro, found non-macro attribute
LL | rustfmt::skip!(); //~ ERROR expected a macro, found tool attribute
| ^^^^^^^^^^^^^
error: aborting due to 2 previous errors