diff options
| author | kennytm <kennytm@gmail.com> | 2018-06-08 07:05:39 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-06-08 07:05:39 +0800 |
| commit | 26a9d589c8fa46061912497de638f3f523087097 (patch) | |
| tree | 57bc9392a285c70b1f92d22cacc0617eff554515 | |
| parent | 0bc15ed7c0878f9f314bdd1e02175574637602a5 (diff) | |
| parent | c9cb806689a9691e2a29836e2c597751cdbcfdc8 (diff) | |
| download | rust-26a9d589c8fa46061912497de638f3f523087097.tar.gz rust-26a9d589c8fa46061912497de638f3f523087097.zip | |
Rollup merge of #51283 - kennytm:fix-51279-preempt-the-warning-song-and-dance, r=nikomatsakis
Deny #[cfg] and #[cfg_attr] on generic parameters. Fix #51279. Attributes on generic parameters are not expanded, meaning `#[cfg]`, `#[cfg_attr]` and attribute proc macros are entirely ignored on them. This PR makes using the first two attributes an error, because if they are correctly expanded will affect the AST and change code behavior. I'm beta-nominating this, because generic parameter attributes are stabilizing in 1.27, and if we did not reserve their usage, we may never be able to repurpose the meaning of these attributes in the Rust 2015 edition.
| -rw-r--r-- | src/libsyntax/attr.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/config.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/issue-51279.rs | 34 | ||||
| -rw-r--r-- | src/test/ui/issue-51279.stderr | 50 |
6 files changed, 124 insertions, 3 deletions
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index 076b6d17658..2389ed799cf 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -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 } diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 36911683a0e..33643789139 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -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> { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 83e7dd84cbf..29030783ca6 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -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 diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 51788b6063a..4d2a152df6e 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -605,7 +605,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(...)] diff --git a/src/test/ui/issue-51279.rs b/src/test/ui/issue-51279.rs new file mode 100644 index 00000000000..4639d73e44d --- /dev/null +++ b/src/test/ui/issue-51279.rs @@ -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 index 00000000000..38d5a5acc50 --- /dev/null +++ b/src/test/ui/issue-51279.stderr @@ -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 + |
