Skip to content

Commit c9cb806

Browse files
committed
Deny #[cfg] and #[cfg_attr] on generic parameters.
1 parent aa094a4 commit c9cb806

File tree

6 files changed

+124
-3
lines changed

6 files changed

+124
-3
lines changed

src/libsyntax/attr.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use self::IntType::*;
1717
use ast;
1818
use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment};
1919
use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
20-
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
20+
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
2121
use codemap::{BytePos, Spanned, respan, dummy_spanned};
2222
use syntax_pos::Span;
2323
use errors::{Applicability, Handler};
@@ -1444,6 +1444,22 @@ impl HasAttrs for Stmt {
14441444
}
14451445
}
14461446

1447+
impl HasAttrs for GenericParam {
1448+
fn attrs(&self) -> &[ast::Attribute] {
1449+
match self {
1450+
GenericParam::Lifetime(lifetime) => lifetime.attrs(),
1451+
GenericParam::Type(ty) => ty.attrs(),
1452+
}
1453+
}
1454+
1455+
fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
1456+
match self {
1457+
GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)),
1458+
GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)),
1459+
}
1460+
}
1461+
}
1462+
14471463
macro_rules! derive_has_attrs {
14481464
($($ty:path),*) => { $(
14491465
impl HasAttrs for $ty {
@@ -1463,5 +1479,5 @@ macro_rules! derive_has_attrs {
14631479

14641480
derive_has_attrs! {
14651481
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
1466-
ast::Field, ast::FieldPat, ast::Variant_
1482+
ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam
14671483
}

src/libsyntax/config.rs

+16
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,22 @@ impl<'a> StripUnconfigured<'a> {
278278
pattern
279279
})
280280
}
281+
282+
// deny #[cfg] on generic parameters until we decide what to do with it.
283+
// see issue #51279.
284+
pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) {
285+
for attr in param.attrs() {
286+
let offending_attr = if attr.check_name("cfg") {
287+
"cfg"
288+
} else if attr.check_name("cfg_attr") {
289+
"cfg_attr"
290+
} else {
291+
continue;
292+
};
293+
let msg = format!("#[{}] cannot be applied on a generic parameter", offending_attr);
294+
self.sess.span_diagnostic.span_err(attr.span, &msg);
295+
}
296+
}
281297
}
282298

283299
impl<'a> fold::Folder for StripUnconfigured<'a> {

src/libsyntax/ext/expand.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
14121412
}
14131413
}
14141414

1415+
fn fold_generic_param(&mut self, param: ast::GenericParam) -> ast::GenericParam {
1416+
self.cfg.disallow_cfg_on_generic_param(&param);
1417+
noop_fold_generic_param(param, self)
1418+
}
1419+
14151420
fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
14161421
// turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
14171422
// contents="file contents")]` attributes

src/libsyntax/feature_gate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,7 @@ declare_features! (
598598
// allow `'_` placeholder lifetimes
599599
(accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
600600
// Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
601-
(accepted, generic_param_attrs, "1.26.0", Some(48848), None),
601+
(accepted, generic_param_attrs, "1.27.0", Some(48848), None),
602602
// Allows cfg(target_feature = "...").
603603
(accepted, cfg_target_feature, "1.27.0", Some(29717), None),
604604
// Allows #[target_feature(...)]

src/test/ui/issue-51279.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
12+
//~^ ERROR #[cfg] cannot be applied on a generic parameter
13+
//~^^ ERROR #[cfg] cannot be applied on a generic parameter
14+
15+
impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
16+
//~^ ERROR #[cfg] cannot be applied on a generic parameter
17+
//~^^ ERROR #[cfg] cannot be applied on a generic parameter
18+
19+
pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
20+
//~^ ERROR #[cfg] cannot be applied on a generic parameter
21+
//~^^ ERROR #[cfg] cannot be applied on a generic parameter
22+
23+
#[cfg(none)]
24+
pub struct Y<#[cfg(none)] T>(T); // shouldn't care when the entire item is stripped out
25+
26+
struct M<T>(*const T);
27+
28+
unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
29+
//~^ ERROR #[cfg_attr] cannot be applied on a generic parameter
30+
fn drop(&mut self) {}
31+
}
32+
33+
type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
34+
//~^ ERROR #[cfg] cannot be applied on a generic parameter

src/test/ui/issue-51279.stderr

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
error: #[cfg] cannot be applied on a generic parameter
2+
--> $DIR/issue-51279.rs:11:14
3+
|
4+
LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
5+
| ^^^^^^^^^^^^
6+
7+
error: #[cfg] cannot be applied on a generic parameter
8+
--> $DIR/issue-51279.rs:11:31
9+
|
10+
LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
11+
| ^^^^^^^^^^^^
12+
13+
error: #[cfg] cannot be applied on a generic parameter
14+
--> $DIR/issue-51279.rs:15:6
15+
|
16+
LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
17+
| ^^^^^^^^^^^^
18+
19+
error: #[cfg] cannot be applied on a generic parameter
20+
--> $DIR/issue-51279.rs:15:23
21+
|
22+
LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
23+
| ^^^^^^^^^^^^
24+
25+
error: #[cfg] cannot be applied on a generic parameter
26+
--> $DIR/issue-51279.rs:19:10
27+
|
28+
LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
29+
| ^^^^^^^^^^^^
30+
31+
error: #[cfg] cannot be applied on a generic parameter
32+
--> $DIR/issue-51279.rs:19:27
33+
|
34+
LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
35+
| ^^^^^^^^^^^^
36+
37+
error: #[cfg_attr] cannot be applied on a generic parameter
38+
--> $DIR/issue-51279.rs:28:13
39+
|
40+
LL | unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
error: #[cfg] cannot be applied on a generic parameter
44+
--> $DIR/issue-51279.rs:33:23
45+
|
46+
LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
47+
| ^^^^^^^^^^^^
48+
49+
error: aborting due to 8 previous errors
50+

0 commit comments

Comments
 (0)