Skip to content

Commit 83fdb8d

Browse files
committed
Resolve attributes in generic parameter position
1 parent 83dfe7b commit 83fdb8d

17 files changed

+220
-248
lines changed

src/librustc/hir/map/def_collector.rs

+3
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
179179
}
180180

181181
fn visit_generic_param(&mut self, param: &'a GenericParam) {
182+
if param.ident.as_str() == "placeholder" {
183+
return self.visit_macro_invoc(param.id);
184+
}
182185
let name = param.ident.as_interned_str();
183186
let def_path_data = match param.kind {
184187
GenericParamKind::Lifetime { .. } => DefPathData::LifetimeNs(name),

src/librustc_resolve/build_reduced_graph.rs

+7
Original file line numberDiff line numberDiff line change
@@ -1070,4 +1070,11 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
10701070
}
10711071
visit::walk_attribute(self, attr);
10721072
}
1073+
1074+
fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
1075+
if param.ident.as_str() == "placeholder" {
1076+
self.visit_invoc(param.id);
1077+
}
1078+
visit::walk_generic_param(self, param);
1079+
}
10731080
}

src/librustc_resolve/macros.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use syntax::ast::{self, Ident, ItemKind};
1515
use syntax::attr::{self, StabilityLevel};
1616
use syntax::ext::base::{self, Indeterminate};
1717
use syntax::ext::base::{MacroKind, SyntaxExtension};
18-
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
18+
use syntax::ext::expand::{AstFragment, AstFragmentKind, Invocation, InvocationKind};
1919
use syntax::ext::hygiene::{self, ExpnId, ExpnInfo, ExpnKind};
2020
use syntax::ext::tt::macro_rules;
2121
use syntax::feature_gate::{emit_feature_err, is_builtin_attr_name};
@@ -236,6 +236,16 @@ impl<'a> base::Resolver for Resolver<'a> {
236236
normal_module_def_id);
237237
}
238238

239+
match invoc.fragment_kind {
240+
AstFragmentKind::GenericParams => {
241+
if let Res::Def(..) = res {
242+
self.session.span_err(span, "expected an inert attribute, found an attribute macro");
243+
return Ok(Some(self.dummy_ext(kind)));
244+
}
245+
}
246+
_ => {}
247+
}
248+
239249
Ok(Some(ext))
240250
}
241251

src/libsyntax/config.rs

-4
Original file line numberDiff line numberDiff line change
@@ -241,10 +241,6 @@ impl<'a> StripUnconfigured<'a> {
241241
items.flat_map_in_place(|item| self.configure(item));
242242
}
243243

244-
pub fn configure_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
245-
params.flat_map_in_place(|param| self.configure(param));
246-
}
247-
248244
fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) {
249245
match vdata {
250246
ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) =>

src/libsyntax/ext/base.rs

+24
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ pub enum Annotatable {
3434
ForeignItem(P<ast::ForeignItem>),
3535
Stmt(P<ast::Stmt>),
3636
Expr(P<ast::Expr>),
37+
// New
38+
GenericParam(ast::GenericParam),
3739
}
3840

3941
impl HasAttrs for Annotatable {
@@ -45,6 +47,7 @@ impl HasAttrs for Annotatable {
4547
Annotatable::ForeignItem(ref foreign_item) => &foreign_item.attrs,
4648
Annotatable::Stmt(ref stmt) => stmt.attrs(),
4749
Annotatable::Expr(ref expr) => &expr.attrs,
50+
Annotatable::GenericParam(ref param) => &param.attrs,
4851
}
4952
}
5053

@@ -56,6 +59,7 @@ impl HasAttrs for Annotatable {
5659
Annotatable::ForeignItem(foreign_item) => foreign_item.visit_attrs(f),
5760
Annotatable::Stmt(stmt) => stmt.visit_attrs(f),
5861
Annotatable::Expr(expr) => expr.visit_attrs(f),
62+
Annotatable::GenericParam(param) => param.visit_attrs(f),
5963
}
6064
}
6165
}
@@ -69,6 +73,7 @@ impl Annotatable {
6973
Annotatable::ForeignItem(ref foreign_item) => foreign_item.span,
7074
Annotatable::Stmt(ref stmt) => stmt.span,
7175
Annotatable::Expr(ref expr) => expr.span,
76+
Annotatable::GenericParam(..) => DUMMY_SP,
7277
}
7378
}
7479

@@ -124,6 +129,13 @@ impl Annotatable {
124129
}
125130
}
126131

132+
pub fn expect_generic_param(self) -> ast::GenericParam {
133+
match self {
134+
Annotatable::GenericParam(i) => i,
135+
_ => panic!("expected generic parameter")
136+
}
137+
}
138+
127139
pub fn derive_allowed(&self) -> bool {
128140
match *self {
129141
Annotatable::Item(ref item) => match item.node {
@@ -315,6 +327,10 @@ pub trait MacResult {
315327
fn make_ty(self: Box<Self>) -> Option<P<ast::Ty>> {
316328
None
317329
}
330+
331+
fn make_generic_params(self: Box<Self>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
332+
None
333+
}
318334
}
319335

320336
macro_rules! make_MacEager {
@@ -515,6 +531,14 @@ impl MacResult for DummyResult {
515531
fn make_ty(self: Box<DummyResult>) -> Option<P<ast::Ty>> {
516532
Some(DummyResult::raw_ty(self.span, self.is_error))
517533
}
534+
535+
fn make_generic_params(self: Box<DummyResult>) -> Option<SmallVec<[ast::GenericParam; 1]>> {
536+
if self.expr_only {
537+
None
538+
} else {
539+
Some(SmallVec::new())
540+
}
541+
}
518542
}
519543

520544
/// A syntax extension kind.

src/libsyntax/ext/expand.rs

+25-4
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,10 @@ ast_fragments! {
155155
ForeignItems(SmallVec<[ast::ForeignItem; 1]>) {
156156
"foreign item"; many fn flat_map_foreign_item; fn visit_foreign_item; fn make_foreign_items;
157157
}
158+
// New
159+
GenericParams(SmallVec<[ast::GenericParam; 1]>) {
160+
"generic parameter"; many fn flat_map_generic_param; fn visit_generic_param; fn make_generic_params;
161+
}
158162
}
159163

160164
impl AstFragmentKind {
@@ -181,6 +185,8 @@ impl AstFragmentKind {
181185
),
182186
AstFragmentKind::OptExpr =>
183187
AstFragment::OptExpr(items.next().map(Annotatable::expect_expr)),
188+
AstFragmentKind::GenericParams =>
189+
AstFragment::GenericParams(items.map(Annotatable::expect_generic_param).collect()),
184190
AstFragmentKind::Pat | AstFragmentKind::Ty =>
185191
panic!("patterns and types aren't annotatable"),
186192
}
@@ -189,7 +195,7 @@ impl AstFragmentKind {
189195

190196
pub struct Invocation {
191197
pub kind: InvocationKind,
192-
fragment_kind: AstFragmentKind,
198+
pub fragment_kind: AstFragmentKind,
193199
pub expansion_data: ExpansionData,
194200
}
195201

@@ -479,6 +485,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
479485
Annotatable::Expr(mut expr) => {
480486
Annotatable::Expr({ cfg.visit_expr(&mut expr); expr })
481487
}
488+
Annotatable::GenericParam(param) => {
489+
Annotatable::GenericParam(cfg.flat_map_generic_param(param).pop().unwrap())
490+
}
482491
}
483492
}
484493

@@ -540,6 +549,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
540549
Annotatable::ForeignItem(item) => token::NtForeignItem(item.into_inner()),
541550
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
542551
Annotatable::Expr(expr) => token::NtExpr(expr),
552+
Annotatable::GenericParam(..) => panic!("unexpected annotatable")
543553
})), DUMMY_SP).into();
544554
let input = self.extract_proc_macro_attr_input(attr.tokens, span);
545555
let tok_result = expander.expand(self.cx, span, input, item_tok);
@@ -623,6 +633,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
623633
Annotatable::Expr(_) if self.cx.ecfg.proc_macro_hygiene() => return,
624634
Annotatable::Stmt(_) => ("statements", sym::proc_macro_hygiene),
625635
Annotatable::Expr(_) => ("expressions", sym::proc_macro_hygiene),
636+
Annotatable::GenericParam(..) => panic!("unexpected annotatable"),
626637
};
627638
emit_feature_err(
628639
self.cx.parse_sess,
@@ -679,6 +690,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
679690
AstFragmentKind::TraitItems => return,
680691
AstFragmentKind::ImplItems => return,
681692
AstFragmentKind::ForeignItems => return,
693+
AstFragmentKind::GenericParams => panic!("unexpected AST fragment kind"),
682694
};
683695
if self.cx.ecfg.proc_macro_hygiene() {
684696
return
@@ -767,6 +779,7 @@ impl<'a> Parser<'a> {
767779
},
768780
AstFragmentKind::Ty => AstFragment::Ty(self.parse_ty()?),
769781
AstFragmentKind::Pat => AstFragment::Pat(self.parse_pat(None)?),
782+
AstFragmentKind::GenericParams => panic!("unexpected AST fragment kind"),
770783
})
771784
}
772785

@@ -1220,9 +1233,17 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12201233
}
12211234
}
12221235

1223-
fn visit_generic_params(&mut self, params: &mut Vec<ast::GenericParam>) {
1224-
self.cfg.configure_generic_params(params);
1225-
noop_visit_generic_params(params, self);
1236+
fn flat_map_generic_param(&mut self, param: ast::GenericParam) -> SmallVec<[ast::GenericParam; 1]> {
1237+
let mut param = configure!(self, param);
1238+
1239+
let (attr, traits, after_derive) = self.classify_item(&mut param);
1240+
if attr.is_some() || !traits.is_empty() {
1241+
return self.collect_attr(attr, traits, Annotatable::GenericParam(param),
1242+
AstFragmentKind::GenericParams, after_derive)
1243+
.make_generic_params();
1244+
}
1245+
1246+
noop_flat_map_generic_param(param, self)
12261247
}
12271248

12281249
fn visit_attribute(&mut self, at: &mut ast::Attribute) {

src/libsyntax/ext/placeholders.rs

+16
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,15 @@ pub fn placeholder(kind: AstFragmentKind, id: ast::NodeId) -> AstFragment {
6666
let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ThinVec::new()));
6767
ast::Stmt { id, span, node: ast::StmtKind::Mac(mac) }
6868
}]),
69+
AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
70+
ast::GenericParam {
71+
id,
72+
ident: ast::Ident::from_str("placeholder"),
73+
attrs: Default::default(),
74+
bounds: Default::default(),
75+
kind: ast::GenericParamKind::Lifetime,
76+
}
77+
}])
6978
}
7079
}
7180

@@ -164,6 +173,13 @@ impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
164173
stmts
165174
}
166175

176+
fn flat_map_generic_param(&mut self, param: ast::GenericParam) -> SmallVec<[ast::GenericParam; 1]> {
177+
if param.ident.as_str() == "placeholder" {
178+
return self.remove(param.id).make_generic_params()
179+
}
180+
noop_flat_map_generic_param(param, self)
181+
}
182+
167183
fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
168184
match pat.node {
169185
ast::PatKind::Mac(_) => *pat = self.remove(pat.id).make_pat(),

src/libsyntax/mut_visit.rs

+9-15
Original file line numberDiff line numberDiff line change
@@ -242,12 +242,8 @@ pub trait MutVisitor: Sized {
242242
noop_visit_variant_data(vdata, self);
243243
}
244244

245-
fn visit_generic_param(&mut self, param: &mut GenericParam) {
246-
noop_visit_generic_param(param, self);
247-
}
248-
249-
fn visit_generic_params(&mut self, params: &mut Vec<GenericParam>) {
250-
noop_visit_generic_params(params, self);
245+
fn flat_map_generic_param(&mut self, param: GenericParam) -> SmallVec<[GenericParam; 1]> {
246+
noop_flat_map_generic_param(param, self)
251247
}
252248

253249
fn visit_tt(&mut self, tt: &mut TokenTree) {
@@ -421,7 +417,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
421417
}
422418
TyKind::BareFn(bft) => {
423419
let BareFnTy { unsafety: _, abi: _, generic_params, decl } = bft.deref_mut();
424-
vis.visit_generic_params(generic_params);
420+
generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
425421
vis.visit_fn_decl(decl);
426422
}
427423
TyKind::Tup(tys) => visit_vec(tys, |ty| vis.visit_ty(ty)),
@@ -702,8 +698,8 @@ pub fn noop_visit_param_bound<T: MutVisitor>(pb: &mut GenericBound, vis: &mut T)
702698
}
703699
}
704700

705-
pub fn noop_visit_generic_param<T: MutVisitor>(param: &mut GenericParam, vis: &mut T) {
706-
let GenericParam { id, ident, attrs, bounds, kind } = param;
701+
pub fn noop_flat_map_generic_param<T: MutVisitor>(mut param: GenericParam, vis: &mut T) -> SmallVec<[GenericParam; 1]> {
702+
let GenericParam { id, ident, attrs, bounds, kind } = &mut param;
707703
vis.visit_id(id);
708704
vis.visit_ident(ident);
709705
visit_thin_attrs(attrs, vis);
@@ -717,10 +713,8 @@ pub fn noop_visit_generic_param<T: MutVisitor>(param: &mut GenericParam, vis: &m
717713
vis.visit_ty(ty);
718714
}
719715
}
720-
}
721716

722-
pub fn noop_visit_generic_params<T: MutVisitor>(params: &mut Vec<GenericParam>, vis: &mut T){
723-
visit_vec(params, |param| vis.visit_generic_param(param));
717+
smallvec![param]
724718
}
725719

726720
pub fn noop_visit_label<T: MutVisitor>(Label { ident }: &mut Label, vis: &mut T) {
@@ -734,7 +728,7 @@ fn noop_visit_lifetime<T: MutVisitor>(Lifetime { id, ident }: &mut Lifetime, vis
734728

735729
pub fn noop_visit_generics<T: MutVisitor>(generics: &mut Generics, vis: &mut T) {
736730
let Generics { params, where_clause, span } = generics;
737-
vis.visit_generic_params(params);
731+
params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
738732
vis.visit_where_clause(where_clause);
739733
vis.visit_span(span);
740734
}
@@ -750,7 +744,7 @@ pub fn noop_visit_where_predicate<T: MutVisitor>(pred: &mut WherePredicate, vis:
750744
WherePredicate::BoundPredicate(bp) => {
751745
let WhereBoundPredicate { span, bound_generic_params, bounded_ty, bounds } = bp;
752746
vis.visit_span(span);
753-
vis.visit_generic_params(bound_generic_params);
747+
bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
754748
vis.visit_ty(bounded_ty);
755749
visit_vec(bounds, |bound| vis.visit_param_bound(bound));
756750
}
@@ -788,7 +782,7 @@ pub fn noop_visit_trait_ref<T: MutVisitor>(TraitRef { path, ref_id }: &mut Trait
788782

789783
pub fn noop_visit_poly_trait_ref<T: MutVisitor>(p: &mut PolyTraitRef, vis: &mut T) {
790784
let PolyTraitRef { bound_generic_params, trait_ref, span } = p;
791-
vis.visit_generic_params(bound_generic_params);
785+
bound_generic_params.flat_map_in_place(|param| vis.flat_map_generic_param(param));
792786
vis.visit_trait_ref(trait_ref);
793787
vis.visit_span(span);
794788
}

src/libsyntax_ext/deriving/custom.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ impl MultiItemModifier for ProcMacroDerive {
5353
applied to a struct, enum, or union");
5454
return Vec::new()
5555
}
56+
Annotatable::GenericParam(..) => panic!("unexpected annotatable")
5657
};
5758
match item.node {
5859
ItemKind::Struct(..) |

src/test/ui/conditional-compilation/cfg-generic-params.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,21 @@ struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy;
1616
//~^ ERROR only lifetime parameters can be used in this context
1717

1818
fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK
19-
fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} //~ ERROR attribute `unknown` is currently unknown
19+
fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} //~ ERROR cannot find attribute macro `unknown` in this scope
2020
fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK
21-
fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} //~ ERROR attribute `unknown` is currently unknown
21+
fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} //~ ERROR cannot find attribute macro `unknown` in this scope
2222

2323
type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK
2424
type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn();
25-
//~^ ERROR attribute `unknown` is currently unknown
25+
//~^ ERROR cannot find attribute macro `unknown` in this scope
2626

2727
type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK
2828
type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy;
29-
//~^ ERROR attribute `unknown` is currently unknown
29+
//~^ ERROR cannot find attribute macro `unknown` in this scope
3030

3131
struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK
3232
struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy;
33-
//~^ ERROR attribute `unknown` is currently unknown
33+
//~^ ERROR cannot find attribute macro `unknown` in this scope
3434

3535
fn main() {
3636
f_lt::<'static>();

0 commit comments

Comments
 (0)