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};
}
}
+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 {
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
}
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> {
}
}
+ 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
// 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(...)]
--- /dev/null
+// 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
--- /dev/null
+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
+