Skip to content

Commit 470c519

Browse files
authored
Rollup merge of rust-lang#34446 - jseyfried:refactor_decorators, r=nrc
Treat `MultiDecorator`s as a special case of `MultiModifier`s This deals with rust-lang#32950 by using @durka's [option 1](rust-lang#33769 (comment)). r? @nrc
2 parents f74d0fb + a595ffa commit 470c519

File tree

3 files changed

+53
-88
lines changed

3 files changed

+53
-88
lines changed

src/libsyntax/ext/expand.rs

+33-78
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ impl<'a> Folder for PatIdentRenamer<'a> {
691691
}
692692

693693
fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
694-
let new_items: SmallVector<Annotatable> = match a {
694+
match a {
695695
Annotatable::Item(it) => match it.node {
696696
ast::ItemKind::Mac(..) => {
697697
it.and_then(|it| match it.node {
@@ -728,63 +728,6 @@ fn expand_multi_modified(a: Annotatable, fld: &mut MacroExpander) -> SmallVector
728728
expand_impl_item(ii.unwrap(), fld).into_iter().
729729
map(|ii| Annotatable::ImplItem(P(ii))).collect()
730730
}
731-
};
732-
733-
new_items.into_iter().flat_map(|a| decorate(a, fld)).collect()
734-
}
735-
736-
fn decorate(a: Annotatable, fld: &mut MacroExpander) -> SmallVector<Annotatable> {
737-
let mut decorator_items = SmallVector::zero();
738-
let mut new_attrs = Vec::new();
739-
expand_decorators(a.clone(), fld, &mut decorator_items, &mut new_attrs);
740-
741-
let mut new_items = SmallVector::one(a.fold_attrs(new_attrs));
742-
new_items.push_all(decorator_items);
743-
new_items
744-
}
745-
746-
fn expand_decorators(a: Annotatable,
747-
fld: &mut MacroExpander,
748-
decorator_items: &mut SmallVector<Annotatable>,
749-
new_attrs: &mut Vec<ast::Attribute>)
750-
{
751-
for attr in a.attrs() {
752-
let mname = intern(&attr.name());
753-
match fld.cx.syntax_env.find(mname) {
754-
Some(rc) => match *rc {
755-
MultiDecorator(ref dec) => {
756-
attr::mark_used(&attr);
757-
758-
fld.cx.bt_push(ExpnInfo {
759-
call_site: attr.span,
760-
callee: NameAndSpan {
761-
format: MacroAttribute(mname),
762-
span: Some(attr.span),
763-
// attributes can do whatever they like,
764-
// for now.
765-
allow_internal_unstable: true,
766-
}
767-
});
768-
769-
let mut items: SmallVector<Annotatable> = SmallVector::zero();
770-
dec.expand(fld.cx,
771-
attr.span,
772-
&attr.node.value,
773-
&a,
774-
&mut |ann| items.push(ann));
775-
776-
for item in items {
777-
for configured_item in item.fold_with(&mut fld.strip_unconfigured()) {
778-
decorator_items.extend(expand_annotatable(configured_item, fld));
779-
}
780-
}
781-
782-
fld.cx.bt_pop();
783-
}
784-
_ => new_attrs.push((*attr).clone()),
785-
},
786-
_ => new_attrs.push((*attr).clone()),
787-
}
788731
}
789732
}
790733

@@ -793,9 +736,12 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe
793736
item = item.map_attrs(|mut attrs| {
794737
for i in 0..attrs.len() {
795738
if let Some(extension) = fld.cx.syntax_env.find(intern(&attrs[i].name())) {
796-
if let MultiModifier(..) = *extension {
797-
multi_modifier = Some((attrs.remove(i), extension));
798-
break;
739+
match *extension {
740+
MultiModifier(..) | MultiDecorator(..) => {
741+
multi_modifier = Some((attrs.remove(i), extension));
742+
break;
743+
}
744+
_ => {}
799745
}
800746
}
801747
}
@@ -804,23 +750,32 @@ fn expand_annotatable(mut item: Annotatable, fld: &mut MacroExpander) -> SmallVe
804750

805751
match multi_modifier {
806752
None => expand_multi_modified(item, fld),
807-
Some((attr, extension)) => match *extension {
808-
MultiModifier(ref mac) => {
809-
attr::mark_used(&attr);
810-
fld.cx.bt_push(ExpnInfo {
811-
call_site: attr.span,
812-
callee: NameAndSpan {
813-
format: MacroAttribute(intern(&attr.name())),
814-
span: Some(attr.span),
815-
// attributes can do whatever they like, for now
816-
allow_internal_unstable: true,
817-
}
818-
});
819-
let modified = mac.expand(fld.cx, attr.span, &attr.node.value, item);
820-
fld.cx.bt_pop();
821-
modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect()
822-
}
823-
_ => unreachable!(),
753+
Some((attr, extension)) => {
754+
attr::mark_used(&attr);
755+
fld.cx.bt_push(ExpnInfo {
756+
call_site: attr.span,
757+
callee: NameAndSpan {
758+
format: MacroAttribute(intern(&attr.name())),
759+
span: Some(attr.span),
760+
// attributes can do whatever they like, for now
761+
allow_internal_unstable: true,
762+
}
763+
});
764+
765+
let modified = match *extension {
766+
MultiModifier(ref mac) => mac.expand(fld.cx, attr.span, &attr.node.value, item),
767+
MultiDecorator(ref mac) => {
768+
let mut items = Vec::new();
769+
mac.expand(fld.cx, attr.span, &attr.node.value, &item,
770+
&mut |item| items.push(item));
771+
items.push(item);
772+
items
773+
}
774+
_ => unreachable!(),
775+
};
776+
777+
fld.cx.bt_pop();
778+
modified.into_iter().flat_map(|it| expand_annotatable(it, fld)).collect()
824779
}
825780
}
826781
}

src/libsyntax_ext/deriving/generic/mod.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -345,15 +345,18 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
345345
/// This method helps to extract all the type parameters referenced from a
346346
/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
347347
/// is not global and starts with `T`, or a `TyQPath`.
348-
fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast::Ty>> {
348+
fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt)
349+
-> Vec<P<ast::Ty>> {
349350
use syntax::visit;
350351

351-
struct Visitor<'a> {
352+
struct Visitor<'a, 'b: 'a> {
353+
cx: &'a ExtCtxt<'b>,
354+
span: Span,
352355
ty_param_names: &'a [ast::Name],
353356
types: Vec<P<ast::Ty>>,
354357
}
355358

356-
impl<'a> visit::Visitor for Visitor<'a> {
359+
impl<'a, 'b> visit::Visitor for Visitor<'a, 'b> {
357360
fn visit_ty(&mut self, ty: &ast::Ty) {
358361
match ty.node {
359362
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
371374

372375
visit::walk_ty(self, ty)
373376
}
377+
378+
fn visit_mac(&mut self, mac: &ast::Mac) {
379+
let span = Span { expn_id: self.span.expn_id, ..mac.span };
380+
self.cx.span_err(span, "`derive` cannot be used on items with type macros");
381+
}
374382
}
375383

376384
let mut visitor = Visitor {
377385
ty_param_names: ty_param_names,
378386
types: Vec::new(),
387+
span: span,
388+
cx: cx,
379389
};
380390

381391
visit::Visitor::visit_ty(&mut visitor, ty);
@@ -556,7 +566,7 @@ impl<'a> TraitDef<'a> {
556566

557567
let mut processed_field_types = HashSet::new();
558568
for field_ty in field_tys {
559-
let tys = find_type_parameters(&field_ty, &ty_param_names);
569+
let tys = find_type_parameters(&field_ty, &ty_param_names, self.span, cx);
560570

561571
for ty in tys {
562572
// if we have already handled this type, skip it

src/test/compile-fail/issue-32950.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#![feature(type_macros, concat_idents, rustc_attrs)]
12-
#![allow(unused)]
11+
#![feature(type_macros, concat_idents)]
1312

14-
#[derive(Debug)] struct FooBar;
15-
#[derive(Debug)] struct Baz<T>(T, concat_idents!(Foo, Bar));
13+
#[derive(Debug)] //~ NOTE in this expansion
14+
struct Baz<T>(
15+
concat_idents!(Foo, Bar) //~ ERROR `derive` cannot be used on items with type macros
16+
);
1617

17-
#[rustc_error]
18-
fn main() {} //~ ERROR compilation successful
18+
fn main() {}

0 commit comments

Comments
 (0)