Rollup merge of #34446 - jseyfried:refactor_decorators, r=nrc
Treat `MultiDecorator`s as a special case of `MultiModifier`s This deals with #32950 by using @durka's [option 1](https://github.com/rust-lang/rust/pull/33769#issuecomment-221774136). r? @nrc
This commit is contained in:
commit
470c5191f5
@ -691,7 +691,7 @@ impl<'a> Folder for PatIdentRenamer<'a> {
|
||||
}
|
||||
|
||||
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
|
||||
let new_items: SmallVector<Annotatable> = match a {
|
||||
match a {
|
||||
Annotatable::Item(it) => match it.node {
|
||||
ast::ItemKind::Mac(..) => {
|
||||
it.and_then(|it| match it.node {
|
||||
@ -728,63 +728,6 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector
|
||||
expand_impl_item(ii.unwrap(), fld).into_iter().
|
||||
map(|ii| Annotatable::ImplItem(P(ii))).collect()
|
||||
}
|
||||
};
|
||||
|
||||
new_items.into_iter().flat_map(|a| decorate(a, fld)).collect()
|
||||
}
|
||||
|
||||
fn decorate(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
|
||||
let mut decorator_items = SmallVector::zero();
|
||||
let mut new_attrs = Vec::new();
|
||||
expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs);
|
||||
|
||||
let mut new_items = SmallVector::one(a.fold_attrs(new_attrs));
|
||||
new_items.push_all(decorator_items);
|
||||
new_items
|
||||
}
|
||||
|
||||
fn expand_decorators(a: Annotatable,
|
||||
fld: &mut MacroExpander,
|
||||
decorator_items: &mut SmallVector<Annotatable>,
|
||||
new_attrs: &mut Vec<ast::Attribute>)
|
||||
{
|
||||
for attr in a.attrs() {
|
||||
let mname = intern(&attr.name());
|
||||
match fld.cx.syntax_env.find(mname) {
|
||||
Some(rc) => match *rc {
|
||||
MultiDecorator(ref dec) => {
|
||||
attr::mark_used(&attr);
|
||||
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
callee: NameAndSpan {
|
||||
format: MacroAttribute(mname),
|
||||
span: Some(attr.span),
|
||||
// attributes can do whatever they like,
|
||||
// for now.
|
||||
allow_internal_unstable: true,
|
||||
}
|
||||
});
|
||||
|
||||
let mut items: SmallVector<Annotatable> = SmallVector::zero();
|
||||
dec.expand(fld.cx,
|
||||
attr.span,
|
||||
&attr.node.value,
|
||||
&a,
|
||||
&mut |ann| items.push(ann));
|
||||
|
||||
for item in items {
|
||||
for configured_item in item.fold_with(&mut fld.strip_unconfigured()) {
|
||||
decorator_items.extend(expand_annotatable(configured_item, fld));
|
||||
}
|
||||
}
|
||||
|
||||
fld.cx.bt_pop();
|
||||
}
|
||||
_ => new_attrs.push((*attr).clone()),
|
||||
},
|
||||
_ => new_attrs.push((*attr).clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -793,9 +736,12 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe
|
||||
item = item.map_attrs(|mut attrs| {
|
||||
for i in 0..attrs.len() {
|
||||
if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) {
|
||||
if let MultiModifier(..) = *extension {
|
||||
multi_modifier = Some((attrs.remove(i), extension));
|
||||
break;
|
||||
match *extension {
|
||||
MultiModifier(..) | MultiDecorator(..) => {
|
||||
multi_modifier = Some((attrs.remove(i), extension));
|
||||
break;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -804,23 +750,32 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe
|
||||
|
||||
match multi_modifier {
|
||||
None => expand_multi_modified(item, fld),
|
||||
Some((attr, extension)) => match *extension {
|
||||
MultiModifier(ref mac) => {
|
||||
attr::mark_used(&attr);
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
callee: NameAndSpan {
|
||||
format: MacroAttribute(intern(&attr.name())),
|
||||
span: Some(attr.span),
|
||||
// attributes can do whatever they like, for now
|
||||
allow_internal_unstable: true,
|
||||
}
|
||||
});
|
||||
let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item);
|
||||
fld.cx.bt_pop();
|
||||
modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
Some((attr, extension)) => {
|
||||
attr::mark_used(&attr);
|
||||
fld.cx.bt_push(ExpnInfo {
|
||||
call_site: attr.span,
|
||||
callee: NameAndSpan {
|
||||
format: MacroAttribute(intern(&attr.name())),
|
||||
span: Some(attr.span),
|
||||
// attributes can do whatever they like, for now
|
||||
allow_internal_unstable: true,
|
||||
}
|
||||
});
|
||||
|
||||
let modified = match *extension {
|
||||
MultiModifier(ref mac) => mac.expand(fld.cx, attr.span, &attr.node.value, item),
|
||||
MultiDecorator(ref mac) => {
|
||||
let mut items = Vec::new();
|
||||
mac.expand(fld.cx, attr.span, &attr.node.value, &item,
|
||||
&mut |item| items.push(item));
|
||||
items.push(item);
|
||||
items
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
fld.cx.bt_pop();
|
||||
modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -345,15 +345,18 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
|
||||
/// This method helps to extract all the type parameters referenced from a
|
||||
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
|
||||
/// is not global and starts with `T`, or a `TyQPath`.
|
||||
fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast::Ty>> {
|
||||
fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt)
|
||||
-> Vec<P<ast::Ty>> {
|
||||
use syntax::visit;
|
||||
|
||||
struct Visitor<'a> {
|
||||
struct Visitor<'a, 'b: 'a> {
|
||||
cx: &'a ExtCtxt<'b>,
|
||||
span: Span,
|
||||
ty_param_names: &'a [ast::Name],
|
||||
types: Vec<P<ast::Ty>>,
|
||||
}
|
||||
|
||||
impl<'a> visit::Visitor for Visitor<'a> {
|
||||
impl<'a, 'b> visit::Visitor for Visitor<'a, 'b> {
|
||||
fn visit_ty(&mut self, ty: &ast::Ty) {
|
||||
match ty.node {
|
||||
ast::TyKind::Path(_, ref path) if !path.global => {
|
||||
@ -371,11 +374,18 @@ fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast
|
||||
|
||||
visit::walk_ty(self, ty)
|
||||
}
|
||||
|
||||
fn visit_mac(&mut self, mac: &ast::Mac) {
|
||||
let span = Span { expn_id: self.span.expn_id, ..mac.span };
|
||||
self.cx.span_err(span, "`derive` cannot be used on items with type macros");
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = Visitor {
|
||||
ty_param_names: ty_param_names,
|
||||
types: Vec::new(),
|
||||
span: span,
|
||||
cx: cx,
|
||||
};
|
||||
|
||||
visit::Visitor::visit_ty(&mut visitor, ty);
|
||||
@ -556,7 +566,7 @@ impl<'a> TraitDef<'a> {
|
||||
|
||||
let mut processed_field_types = HashSet::new();
|
||||
for field_ty in field_tys {
|
||||
let tys = find_type_parameters(&field_ty, &ty_param_names);
|
||||
let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx);
|
||||
|
||||
for ty in tys {
|
||||
// if we have already handled this type, skip it
|
||||
|
@ -8,11 +8,11 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(type_macros, concat_idents, rustc_attrs)]
|
||||
#![allow(unused)]
|
||||
#![feature(type_macros, concat_idents)]
|
||||
|
||||
#[derive(Debug)] struct FooBar;
|
||||
#[derive(Debug)] struct Baz<T>(T, concat_idents!(Foo, Bar));
|
||||
#[derive(Debug)] //~ NOTE in this expansion
|
||||
struct Baz<T>(
|
||||
concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
|
||||
);
|
||||
|
||||
#[rustc_error]
|
||||
fn main() {} //~ ERROR compilation successful
|
||||
fn main() {}
|
||||
|
Loading…
Reference in New Issue
Block a user