Skip to content

Commit 26a9d58

Browse files
authored
Rollup merge of rust-lang#51283 - kennytm:fix-51279-preempt-the-warning-song-and-dance, r=nikomatsakis
Deny #[cfg] and #[cfg_attr] on generic parameters. Fix rust-lang#51279. Attributes on generic parameters are not expanded, meaning `#[cfg]`, `#[cfg_attr]` and attribute proc macros are entirely ignored on them. This PR makes using the first two attributes an error, because if they are correctly expanded will affect the AST and change code behavior. I'm beta-nominating this, because generic parameter attributes are stabilizing in 1.27, and if we did not reserve their usage, we may never be able to repurpose the meaning of these attributes in the Rust 2015 edition.
2 parents 0bc15ed + c9cb806 commit 26a9d58

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
@@ -605,7 +605,7 @@ declare_features! (
605605
// allow `'_` placeholder lifetimes
606606
(accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
607607
// Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
608-
(accepted, generic_param_attrs, "1.26.0", Some(48848), None),
608+
(accepted, generic_param_attrs, "1.27.0", Some(48848), None),
609609
// Allows cfg(target_feature = "...").
610610
(accepted, cfg_target_feature, "1.27.0", Some(29717), None),
611611
// 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)