]> git.lizzy.rs Git - rust.git/commitdiff
Deny #[cfg] and #[cfg_attr] on generic parameters.
authorkennytm <kennytm@gmail.com>
Fri, 1 Jun 2018 21:10:29 +0000 (05:10 +0800)
committerkennytm <kennytm@gmail.com>
Fri, 1 Jun 2018 21:11:33 +0000 (05:11 +0800)
src/libsyntax/attr.rs
src/libsyntax/config.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/test/ui/issue-51279.rs [new file with mode: 0644]
src/test/ui/issue-51279.stderr [new file with mode: 0644]

index 076b6d1765848104aecc0fe2e6fae18eb0aa2c05..2389ed799cfcc268301e70275aac9b3c190f029f 100644 (file)
@@ -17,7 +17,7 @@
 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 @@ fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F)
     }
 }
 
+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 @@ fn map_attrs<F>(mut self, f: F) -> Self
 
 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
 }
index 36911683a0e7785654cd7c88a642cec1c106814f..3364378913952deabb76eacf3ae07d463028beb0 100644 (file)
@@ -278,6 +278,22 @@ pub fn configure_pat(&mut self, pattern: P<ast::Pat>) -> P<ast::Pat> {
             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> {
index 83e7dd84cbff2a443b9419041fa269adde70f05e..29030783ca6b848d0c253c019fb30f126f76e4a7 100644 (file)
@@ -1412,6 +1412,11 @@ fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind {
         }
     }
 
+    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
index 9b84713b0f90f28d3ff607a87ba952e92e3d04e0..785aedd3f3337e4d5b8d1839cf046d04720c0b41 100644 (file)
@@ -598,7 +598,7 @@ pub fn walk_feature_fields<F>(&self, mut f: F)
     // 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(...)]
diff --git a/src/test/ui/issue-51279.rs b/src/test/ui/issue-51279.rs
new file mode 100644 (file)
index 0000000..4639d73
--- /dev/null
@@ -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
diff --git a/src/test/ui/issue-51279.stderr b/src/test/ui/issue-51279.stderr
new file mode 100644 (file)
index 0000000..38d5a5a
--- /dev/null
@@ -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
+