Deny #[cfg] and #[cfg_attr] on generic parameters.
This commit is contained in:
parent
aa094a43cc
commit
c9cb806689
@ -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
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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(¶m);
|
||||
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
|
||||
|
@ -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(...)]
|
||||
|
34
src/test/ui/issue-51279.rs
Normal file
34
src/test/ui/issue-51279.rs
Normal 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
|
50
src/test/ui/issue-51279.stderr
Normal file
50
src/test/ui/issue-51279.stderr
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user