From 0b58bb32f66f4ec5f00683293093d94d8fb1aada Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 5 Jun 2019 17:59:37 +0300 Subject: [PATCH] Support `cfg` and `cfg_attr` on generic parameters --- src/libsyntax/config.rs | 20 ++---- src/libsyntax/ext/expand.rs | 6 +- .../cfg-generic-params.rs | 38 +++++++++++ .../cfg-generic-params.stderr | 66 +++++++++++++++++++ src/test/ui/issues/issue-51279.rs | 27 -------- src/test/ui/issues/issue-51279.stderr | 60 ----------------- 6 files changed, 111 insertions(+), 106 deletions(-) create mode 100644 src/test/ui/conditional-compilation/cfg-generic-params.rs create mode 100644 src/test/ui/conditional-compilation/cfg-generic-params.stderr delete mode 100644 src/test/ui/issues/issue-51279.rs delete mode 100644 src/test/ui/issues/issue-51279.stderr diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 1cc13ac7878be..3b42e1de61497 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -240,6 +240,10 @@ impl<'a> StripUnconfigured<'a> { items.flat_map_in_place(|item| self.configure(item)); } + pub fn configure_generic_params(&mut self, params: &mut Vec) { + params.flat_map_in_place(|param| self.configure(param)); + } + fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { match vdata { ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => @@ -301,22 +305,6 @@ impl<'a> StripUnconfigured<'a> { pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); } - - /// Denies `#[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(sym::cfg) { - "cfg" - } else if attr.check_name(sym::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> MutVisitor for StripUnconfigured<'a> { diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index d433e6c5a896f..a71d1d503cabc 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1439,9 +1439,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } - fn visit_generic_param(&mut self, param: &mut ast::GenericParam) { - self.cfg.disallow_cfg_on_generic_param(¶m); - noop_visit_generic_param(param, self) + fn visit_generic_params(&mut self, params: &mut Vec) { + self.cfg.configure_generic_params(params); + noop_visit_generic_params(params, self); } fn visit_attribute(&mut self, at: &mut ast::Attribute) { diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.rs b/src/test/ui/conditional-compilation/cfg-generic-params.rs new file mode 100644 index 0000000000000..d80d3ea7b7fe9 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-generic-params.rs @@ -0,0 +1,38 @@ +// compile-flags:--cfg yes + +fn f_lt<#[cfg(yes)] 'a: 'a, #[cfg(no)] T>() {} +fn f_ty<#[cfg(no)] 'a: 'a, #[cfg(yes)] T>() {} + +type FnGood = for<#[cfg(yes)] 'a, #[cfg(no)] T> fn(); // OK +type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); +//~^ ERROR only lifetime parameters can be used in this context + +type PolyGood = dyn for<#[cfg(yes)] 'a, #[cfg(no)] T> Copy; // OK +type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; +//~^ ERROR only lifetime parameters can be used in this context + +struct WhereGood where for<#[cfg(yes)] 'a, #[cfg(no)] T> u8: Copy; // OK +struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; +//~^ ERROR only lifetime parameters can be used in this context + +fn f_lt_no<#[cfg_attr(no, unknown)] 'a>() {} // OK +fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} //~ ERROR attribute `unknown` is currently unknown +fn f_ty_no<#[cfg_attr(no, unknown)] T>() {} // OK +fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} //~ ERROR attribute `unknown` is currently unknown + +type FnNo = for<#[cfg_attr(no, unknown)] 'a> fn(); // OK +type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); +//~^ ERROR attribute `unknown` is currently unknown + +type PolyNo = dyn for<#[cfg_attr(no, unknown)] 'a> Copy; // OK +type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; +//~^ ERROR attribute `unknown` is currently unknown + +struct WhereNo where for<#[cfg_attr(no, unknown)] 'a> u8: Copy; // OK +struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; +//~^ ERROR attribute `unknown` is currently unknown + +fn main() { + f_lt::<'static>(); + f_ty::(); +} diff --git a/src/test/ui/conditional-compilation/cfg-generic-params.stderr b/src/test/ui/conditional-compilation/cfg-generic-params.stderr new file mode 100644 index 0000000000000..40ca44d9db59c --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg-generic-params.stderr @@ -0,0 +1,66 @@ +error: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:7:45 + | +LL | type FnBad = for<#[cfg(no)] 'a, #[cfg(yes)] T> fn(); + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:11:51 + | +LL | type PolyBad = dyn for<#[cfg(no)] 'a, #[cfg(yes)] T> Copy; + | ^ + +error: only lifetime parameters can be used in this context + --> $DIR/cfg-generic-params.rs:15:54 + | +LL | struct WhereBad where for<#[cfg(no)] 'a, #[cfg(yes)] T> u8: Copy; + | ^ + +error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/cfg-generic-params.rs:19:29 + | +LL | fn f_lt_yes<#[cfg_attr(yes, unknown)] 'a>() {} + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/cfg-generic-params.rs:21:29 + | +LL | fn f_ty_yes<#[cfg_attr(yes, unknown)] T>() {} + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/cfg-generic-params.rs:24:34 + | +LL | type FnYes = for<#[cfg_attr(yes, unknown)] 'a> fn(); + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/cfg-generic-params.rs:28:40 + | +LL | type PolyYes = dyn for<#[cfg_attr(yes, unknown)] 'a> Copy; + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error[E0658]: The attribute `unknown` is currently unknown to the compiler and may have meaning added to it in the future + --> $DIR/cfg-generic-params.rs:32:43 + | +LL | struct WhereYes where for<#[cfg_attr(yes, unknown)] 'a> u8: Copy; + | ^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/29642 + = help: add #![feature(custom_attribute)] to the crate attributes to enable + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/issues/issue-51279.rs b/src/test/ui/issues/issue-51279.rs deleted file mode 100644 index f8f3626caabe7..0000000000000 --- a/src/test/ui/issues/issue-51279.rs +++ /dev/null @@ -1,27 +0,0 @@ -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(*const T); - -impl<#[cfg_attr(none, may_dangle)] T> Drop for M { - //~^ 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 -//~| ERROR attribute `ignored` is currently unknown to the compiler - -fn main() {} diff --git a/src/test/ui/issues/issue-51279.stderr b/src/test/ui/issues/issue-51279.stderr deleted file mode 100644 index 9dd4a9f23814c..0000000000000 --- a/src/test/ui/issues/issue-51279.stderr +++ /dev/null @@ -1,60 +0,0 @@ -error: #[cfg] cannot be applied on a generic parameter - --> $DIR/issue-51279.rs:1: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:1: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:5: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:5: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:9: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:9: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:18:6 - | -LL | impl<#[cfg_attr(none, may_dangle)] T> Drop for M { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: #[cfg] cannot be applied on a generic parameter - --> $DIR/issue-51279.rs:23:23 - | -LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>; - | ^^^^^^^^^^^^ - -error[E0658]: The attribute `ignored` is currently unknown to the compiler and may have meaning added to it in the future - --> $DIR/issue-51279.rs:23:8 - | -LL | type Z<#[ignored] 'a, #[cfg(none)] T> = X<'a, T>; - | ^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/29642 - = help: add #![feature(custom_attribute)] to the crate attributes to enable - -error: aborting due to 9 previous errors - -For more information about this error, try `rustc --explain E0658`.