Skip to content

Commit

Permalink
Deny #[cfg] and #[cfg_attr] on generic parameters.
Browse files Browse the repository at this point in the history
  • Loading branch information
kennytm committed Jun 1, 2018
1 parent aa094a4 commit c9cb806
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 3 deletions.
20 changes: 18 additions & 2 deletions src/libsyntax/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use self::IntType::*;
use ast;
use ast::{AttrId, Attribute, Name, Ident, Path, PathSegment};
use ast::{MetaItem, MetaItemKind, NestedMetaItem, NestedMetaItemKind};
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind};
use ast::{Lit, LitKind, Expr, ExprKind, Item, Local, Stmt, StmtKind, GenericParam};
use codemap::{BytePos, Spanned, respan, dummy_spanned};
use syntax_pos::Span;
use errors::{Applicability, Handler};
Expand Down Expand Up @@ -1444,6 +1444,22 @@ impl HasAttrs for Stmt {
}
}

impl HasAttrs for GenericParam {
fn attrs(&self) -> &[ast::Attribute] {
match self {
GenericParam::Lifetime(lifetime) => lifetime.attrs(),
GenericParam::Type(ty) => ty.attrs(),
}
}

fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
match self {
GenericParam::Lifetime(lifetime) => GenericParam::Lifetime(lifetime.map_attrs(f)),
GenericParam::Type(ty) => GenericParam::Type(ty.map_attrs(f)),
}
}
}

macro_rules! derive_has_attrs {
($($ty:path),*) => { $(
impl HasAttrs for $ty {
Expand All @@ -1463,5 +1479,5 @@ macro_rules! derive_has_attrs {

derive_has_attrs! {
Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm,
ast::Field, ast::FieldPat, ast::Variant_
ast::Field, ast::FieldPat, ast::Variant_, ast::LifetimeDef, ast::TyParam
}
16 changes: 16 additions & 0 deletions src/libsyntax/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,22 @@ impl<'a> StripUnconfigured<'a> {
pattern
})
}

// deny #[cfg] on generic parameters until we decide what to do with it.
// see issue #51279.
pub fn disallow_cfg_on_generic_param(&mut self, param: &ast::GenericParam) {
for attr in param.attrs() {
let offending_attr = if attr.check_name("cfg") {
"cfg"
} else if attr.check_name("cfg_attr") {
"cfg_attr"
} else {
continue;
};
let msg = format!("#[{}] cannot be applied on a generic parameter", offending_attr);
self.sess.span_diagnostic.span_err(attr.span, &msg);
}
}
}

impl<'a> fold::Folder for StripUnconfigured<'a> {
Expand Down
5 changes: 5 additions & 0 deletions src/libsyntax/ext/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1412,6 +1412,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
}
}

fn fold_generic_param(&mut self, param: ast::GenericParam) -> ast::GenericParam {
self.cfg.disallow_cfg_on_generic_param(&param);
noop_fold_generic_param(param, self)
}

fn fold_attribute(&mut self, at: ast::Attribute) -> Option<ast::Attribute> {
// turn `#[doc(include="filename")]` attributes into `#[doc(include(file="filename",
// contents="file contents")]` attributes
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/feature_gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,7 +598,7 @@ declare_features! (
// allow `'_` placeholder lifetimes
(accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
// Allows attributes on lifetime/type formal parameters in generics (RFC 1327)
(accepted, generic_param_attrs, "1.26.0", Some(48848), None),
(accepted, generic_param_attrs, "1.27.0", Some(48848), None),
// Allows cfg(target_feature = "...").
(accepted, cfg_target_feature, "1.27.0", Some(29717), None),
// Allows #[target_feature(...)]
Expand Down
34 changes: 34 additions & 0 deletions src/test/ui/issue-51279.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
//~^ ERROR #[cfg] cannot be applied on a generic parameter
//~^^ ERROR #[cfg] cannot be applied on a generic parameter

impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
//~^ ERROR #[cfg] cannot be applied on a generic parameter
//~^^ ERROR #[cfg] cannot be applied on a generic parameter

pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
//~^ ERROR #[cfg] cannot be applied on a generic parameter
//~^^ ERROR #[cfg] cannot be applied on a generic parameter

#[cfg(none)]
pub struct Y<#[cfg(none)] T>(T); // shouldn't care when the entire item is stripped out

struct M<T>(*const T);

unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
//~^ ERROR #[cfg_attr] cannot be applied on a generic parameter
fn drop(&mut self) {}
}

type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
//~^ ERROR #[cfg] cannot be applied on a generic parameter
50 changes: 50 additions & 0 deletions src/test/ui/issue-51279.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:11:14
|
LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
| ^^^^^^^^^^^^

error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:11:31
|
LL | pub struct X<#[cfg(none)] 'a, #[cfg(none)] T>(&'a T);
| ^^^^^^^^^^^^

error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:15:6
|
LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
| ^^^^^^^^^^^^

error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:15:23
|
LL | impl<#[cfg(none)] 'a, #[cfg(none)] T> X<'a, T> {}
| ^^^^^^^^^^^^

error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:19:10
|
LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
| ^^^^^^^^^^^^

error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:19:27
|
LL | pub fn f<#[cfg(none)] 'a, #[cfg(none)] T>(_: &'a T) {}
| ^^^^^^^^^^^^

error: #[cfg_attr] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:28:13
|
LL | unsafe impl<#[cfg_attr(none, may_dangle)] T> Drop for M<T> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: #[cfg] cannot be applied on a generic parameter
--> $DIR/issue-51279.rs:33:23
|
LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>;
| ^^^^^^^^^^^^

error: aborting due to 8 previous errors

0 comments on commit c9cb806

Please sign in to comment.