From f4737d5607eabbfc07440b0ce64b852395948a68 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 18 Jun 2019 22:06:00 +0200 Subject: [PATCH 1/3] Make Place::ty iterate --- src/librustc/mir/tcx.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index afabcdfadd03c..2079a2a34e7ef 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -122,13 +122,25 @@ impl<'tcx> Place<'tcx> { where D: HasLocalDecls<'tcx>, { - match *self { - Place::Base(PlaceBase::Local(index)) => - PlaceTy::from_ty(local_decls.local_decls()[index].ty), - Place::Base(PlaceBase::Static(ref data)) => - PlaceTy::from_ty(data.ty), - Place::Projection(ref proj) => - proj.base.ty(local_decls, tcx).projection_ty(tcx, &proj.elem), + self.iterate(|place_base, place_projections| { + let mut place_ty = place_base.ty(local_decls); + + for proj in place_projections { + place_ty = place_ty.projection_ty(tcx, &proj.elem); + } + + place_ty + }) + } +} + +impl<'tcx> PlaceBase<'tcx> { + pub fn ty(&self, local_decls: &D) -> PlaceTy<'tcx> + where D: HasLocalDecls<'tcx> + { + match self { + PlaceBase::Local(index) => PlaceTy::from_ty(local_decls.local_decls()[*index].ty), + PlaceBase::Static(data) => PlaceTy::from_ty(data.ty), } } } From 8b21b075f73c629c25e8225c78a2992aa6e1d874 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 19 Jun 2019 09:21:44 +0200 Subject: [PATCH 2/3] Add functions to build raw slices --- src/libcore/ptr/mod.rs | 47 ++++++++++++++++++++++++++++++++++++++++ src/libcore/slice/mod.rs | 19 +++------------- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 8f026a5b7d8dd..ba88fde6ebc97 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -230,6 +230,53 @@ pub const fn null() -> *const T { 0 as *const T } #[rustc_promotable] pub const fn null_mut() -> *mut T { 0 as *mut T } +#[repr(C)] +pub(crate) union Repr { + pub(crate) rust: *const [T], + rust_mut: *mut [T], + pub(crate) raw: FatPtr, +} + +#[repr(C)] +pub(crate) struct FatPtr { + data: *const T, + pub(crate) len: usize, +} + +/// Forms a slice from a pointer and a length. +/// +/// The `len` argument is the number of **elements**, not the number of bytes. +/// +/// # Examples +/// +/// ```rust +/// #![feature(slice_from_raw_parts)] +/// use std::ptr; +/// +/// // create a slice pointer when starting out with a pointer to the first element +/// let mut x = [5, 6, 7]; +/// let ptr = &mut x[0] as *mut _; +/// let slice = ptr::slice_from_raw_parts_mut(ptr, 3); +/// assert_eq!(unsafe { &*slice }[2], 7); +/// ``` +#[inline] +#[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] +pub fn slice_from_raw_parts(data: *const T, len: usize) -> *const [T] { + unsafe { Repr { raw: FatPtr { data, len } }.rust } +} + +/// Performs the same functionality as [`from_raw_parts`], except that a +/// mutable slice is returned. +/// +/// See the documentation of [`from_raw_parts`] for more details. +/// +/// [`from_raw_parts`]: ../../std/slice/fn.from_raw_parts.html +#[inline] +#[unstable(feature = "slice_from_raw_parts", reason = "recently added", issue = "36925")] +pub fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { + unsafe { Repr { raw: FatPtr { data, len } }.rust_mut } +} + /// Swaps the values at two mutable locations of the same type, without /// deinitializing either. /// diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index b2376cdf9fa76..af1b20a4c10cf 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -45,19 +45,6 @@ pub mod memchr; mod rotate; mod sort; -#[repr(C)] -union Repr<'a, T: 'a> { - rust: &'a [T], - rust_mut: &'a mut [T], - raw: FatPtr, -} - -#[repr(C)] -struct FatPtr { - data: *const T, - len: usize, -} - // // Extension traits // @@ -78,7 +65,7 @@ impl [T] { #[rustc_const_unstable(feature = "const_slice_len")] pub const fn len(&self) -> usize { unsafe { - Repr { rust: self }.raw.len + crate::ptr::Repr { rust: self }.raw.len } } @@ -5195,7 +5182,7 @@ pub unsafe fn from_raw_parts<'a, T>(data: *const T, len: usize) -> &'a [T] { debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); - Repr { raw: FatPtr { data, len } }.rust + &*ptr::slice_from_raw_parts(data, len) } /// Performs the same functionality as [`from_raw_parts`], except that a @@ -5216,7 +5203,7 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] debug_assert!(data as usize % mem::align_of::() == 0, "attempt to create unaligned slice"); debug_assert!(mem::size_of::().saturating_mul(len) <= isize::MAX as usize, "attempt to create slice covering half the address space"); - Repr { raw: FatPtr { data, len } }.rust_mut + &mut *ptr::slice_from_raw_parts_mut(data, len) } /// Converts a reference to T into a slice of length 1 (without copying). From 0b58bb32f66f4ec5f00683293093d94d8fb1aada Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 5 Jun 2019 17:59:37 +0300 Subject: [PATCH 3/3] 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`.