Deny #[cfg] and #[cfg_attr] on generic parameters.

This commit is contained in:
kennytm 2018-06-02 05:10:29 +08:00
parent aa094a43cc
commit c9cb806689
No known key found for this signature in database
GPG Key ID: FEF6C8051D0E013C
6 changed files with 124 additions and 3 deletions

View File

@ -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};
@ -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 {
@ -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
}

View File

@ -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> {

View File

@ -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

View File

@ -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(...)]

View File

@ -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

View File

@ -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