From 00d537dcd03f9ff5ebdf8b86e039dbdb0a7f850c Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Thu, 2 Jul 2020 09:32:41 +0200 Subject: [PATCH 01/37] deny(unsafe_op_in_unsafe_fn) in libstd/path.rs --- library/std/src/path.rs | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/library/std/src/path.rs b/library/std/src/path.rs index e3d529df7de16..92c0f61972c83 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -60,6 +60,7 @@ //! [`push`]: PathBuf::push #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] use crate::borrow::{Borrow, Cow}; use crate::cmp; @@ -293,7 +294,8 @@ fn os_str_as_u8_slice(s: &OsStr) -> &[u8] { unsafe { &*(s as *const OsStr as *const [u8]) } } unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { - &*(s as *const [u8] as *const OsStr) + // SAFETY: see the comment of `os_str_as_u8_slice` + unsafe { &*(s as *const [u8] as *const OsStr) } } // Detect scheme on Redox @@ -313,24 +315,21 @@ fn has_physical_root(s: &[u8], prefix: Option>) -> bool { // basic workhorse for splitting stem and extension fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { - unsafe { - if os_str_as_u8_slice(file) == b".." { - return (Some(file), None); - } - - // The unsafety here stems from converting between &OsStr and &[u8] - // and back. This is safe to do because (1) we only look at ASCII - // contents of the encoding and (2) new &OsStr values are produced - // only from ASCII-bounded slices of existing &OsStr values. - - let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.'); - let after = iter.next(); - let before = iter.next(); - if before == Some(b"") { - (Some(file), None) - } else { - (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) - } + if os_str_as_u8_slice(file) == b".." { + return (Some(file), None); + } + + // The unsafety here stems from converting between &OsStr and &[u8] + // and back. This is safe to do because (1) we only look at ASCII + // contents of the encoding and (2) new &OsStr values are produced + // only from ASCII-bounded slices of existing &OsStr values. + let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.'); + let after = iter.next(); + let before = iter.next(); + if before == Some(b"") { + (Some(file), None) + } else { + unsafe { (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) } } } @@ -1701,7 +1700,7 @@ impl Path { // The following (private!) function allows construction of a path from a u8 // slice, which is only safe when it is known to follow the OsStr encoding. unsafe fn from_u8_slice(s: &[u8]) -> &Path { - Path::new(u8_slice_as_os_str(s)) + unsafe { Path::new(u8_slice_as_os_str(s)) } } // The following (private!) function reveals the byte encoding used for OsStr. fn as_u8_slice(&self) -> &[u8] { From 0f2bd56b29857453835e47abbe96a80b175632d1 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 3 Aug 2020 11:08:03 +0100 Subject: [PATCH 02/37] lint/ty: move fns to avoid abstraction violation This commit moves `transparent_newtype_field` and `is_zst` to `LateContext` where they are used, rather than being on the `VariantDef` and `TyS` types. Signed-off-by: David Wood --- compiler/rustc_lint/src/builtin.rs | 6 +++--- compiler/rustc_lint/src/types.rs | 26 +++++++++++++++++++++++--- compiler/rustc_middle/src/ty/mod.rs | 15 +-------------- compiler/rustc_middle/src/ty/sty.rs | 5 ----- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index ea624b9ed3003..694455171e9ec 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -21,7 +21,8 @@ //! `late_lint_methods!` invocation in `lib.rs`. use crate::{ - types::CItemKind, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, + types::{transparent_newtype_field, CItemKind}, + EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext, }; use rustc_ast::attr::{self, HasAttrs}; use rustc_ast::tokenstream::{TokenStream, TokenTree}; @@ -2180,8 +2181,7 @@ impl ClashingExternDeclarations { if is_transparent && !is_non_null { debug_assert!(def.variants.len() == 1); let v = &def.variants[VariantIdx::new(0)]; - ty = v - .transparent_newtype_field(tcx) + ty = transparent_newtype_field(tcx, v) .expect( "single-variant transparent structure with zero-sized field", ) diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 35c462c24c8e8..132e9286f6b3b 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -533,6 +533,26 @@ crate fn nonnull_optimization_guaranteed<'tcx>(tcx: TyCtxt<'tcx>, def: &ty::AdtD .any(|a| tcx.sess.check_name(a, sym::rustc_nonnull_optimization_guaranteed)) } +/// `repr(transparent)` structs can have a single non-ZST field, this function returns that +/// field. +pub fn transparent_newtype_field<'a, 'tcx>( + tcx: TyCtxt<'tcx>, + variant: &'a ty::VariantDef, +) -> Option<&'a ty::FieldDef> { + let param_env = tcx.param_env(variant.def_id); + for field in &variant.fields { + let field_ty = tcx.type_of(field.did); + let is_zst = + tcx.layout_of(param_env.and(field_ty)).map(|layout| layout.is_zst()).unwrap_or(false); + + if !is_zst { + return Some(field); + } + } + + None +} + /// Is type known to be non-null? crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKind) -> bool { let tcx = cx.tcx; @@ -548,7 +568,7 @@ crate fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: C } for variant in &def.variants { - if let Some(field) = variant.transparent_newtype_field(tcx) { + if let Some(field) = transparent_newtype_field(cx.tcx, variant) { if ty_is_known_nonnull(cx, field.ty(tcx, substs), mode) { return true; } @@ -569,7 +589,7 @@ fn get_nullable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option { let inner_field_ty = { let first_non_zst_ty = - field_def.variants.iter().filter_map(|v| v.transparent_newtype_field(tcx)); + field_def.variants.iter().filter_map(|v| transparent_newtype_field(cx.tcx, v)); debug_assert_eq!( first_non_zst_ty.clone().count(), 1, @@ -710,7 +730,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if def.repr.transparent() { // Can assume that only one field is not a ZST, so only check // that field's type for FFI-safety. - if let Some(field) = variant.transparent_newtype_field(self.cx.tcx) { + if let Some(field) = transparent_newtype_field(self.cx.tcx, variant) { self.check_field_type_for_ffi(cache, field, substs) } else { bug!("malformed transparent type"); diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b6300a40b0d8d..8027bed2c8cf0 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2005,7 +2005,7 @@ pub struct VariantDef { flags: VariantFlags, } -impl<'tcx> VariantDef { +impl VariantDef { /// Creates a new `VariantDef`. /// /// `variant_did` is the `DefId` that identifies the enum variant (if this `VariantDef` @@ -2071,19 +2071,6 @@ impl<'tcx> VariantDef { pub fn is_recovered(&self) -> bool { self.flags.intersects(VariantFlags::IS_RECOVERED) } - - /// `repr(transparent)` structs can have a single non-ZST field, this function returns that - /// field. - pub fn transparent_newtype_field(&self, tcx: TyCtxt<'tcx>) -> Option<&FieldDef> { - for field in &self.fields { - let field_ty = field.ty(tcx, InternalSubsts::identity_for_item(tcx, self.def_id)); - if !field_ty.is_zst(tcx, self.def_id) { - return Some(field); - } - } - - None - } } #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, HashStable)] diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c1f354c7a15f3..2af3fb7f8638a 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2280,9 +2280,4 @@ impl<'tcx> TyS<'tcx> { } } } - - /// Is this a zero-sized type? - pub fn is_zst(&'tcx self, tcx: TyCtxt<'tcx>, did: DefId) -> bool { - tcx.layout_of(tcx.param_env(did).and(self)).map(|layout| layout.is_zst()).unwrap_or(false) - } } From 6092828d1f432bb313818e7cfab961c0e494f69e Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Thu, 3 Sep 2020 19:59:51 -0700 Subject: [PATCH 03/37] Add `[T; N]: TryFrom>` This is very similar to the existing `Box<[T; N]>: TryFrom>`, but allows avoiding the `shrink_to_fit` if you have a vector and not a boxed slice. --- library/alloc/src/vec.rs | 52 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 9013e3fc16ab9..b6d923daaf2ab 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -55,6 +55,7 @@ #![stable(feature = "rust1", since = "1.0.0")] use core::cmp::{self, Ordering}; +use core::convert::TryFrom; use core::fmt; use core::hash::{Hash, Hasher}; use core::intrinsics::{arith_offset, assume}; @@ -2771,6 +2772,57 @@ impl From<&str> for Vec { } } +#[stable(feature = "array_try_from_vec", since = "1.47.0")] +impl TryFrom> for [T; N] { + type Error = Vec; + + /// Gets the entire contents of the `Vec` as an array, + /// if its size exactly matches that of the requested array. + /// + /// # Examples + /// + /// ``` + /// use std::convert::TryInto; + /// assert_eq!(vec![1, 2, 3].try_into(), Ok([1, 2, 3])); + /// assert_eq!(>::new().try_into(), Ok([])); + /// ``` + /// + /// If the length doesn't match, the input comes back in `Err`: + /// ``` + /// use std::convert::TryInto; + /// let r: Result<[i32; 4], _> = (0..10).collect::>().try_into(); + /// assert_eq!(r, Err(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9])); + /// ``` + /// + /// If you're fine with just getting a prefix of the `Vec`, + /// you can call [`.truncate(N)`](Vec::truncate) first. + /// ``` + /// use std::convert::TryInto; + /// let mut v = String::from("hello world").into_bytes(); + /// v.sort(); + /// v.truncate(2); + /// let [a, b]: [_; 2] = v.try_into().unwrap(); + /// assert_eq!(a, b' '); + /// assert_eq!(b, b'd'); + /// ``` + fn try_from(mut vec: Vec) -> Result<[T; N], Vec> { + if vec.len() != N { + return Err(vec); + } + + // SAFETY: `.set_len(0)` is always sound. + unsafe { vec.set_len(0) }; + + // SAFETY: A `Vec`'s pointer is always aligned property, and + // the alignment the array needs is the same as the items. + // We checked earlier that we have sufficient items. + // The items will not double-drop as the `set_len` + // tells the `Vec` not to also drop them. + let array = unsafe { ptr::read(vec.as_ptr() as *const [T; N]) }; + Ok(array) + } +} + //////////////////////////////////////////////////////////////////////////////// // Clone-on-write //////////////////////////////////////////////////////////////////////////////// From 6cb671628393e292d5e68e6367f80488ace46532 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sun, 16 Aug 2020 03:01:38 +0000 Subject: [PATCH 04/37] Add test for checking if-let or-patterns --- src/test/mir-opt/issues/issue-75439.rs | 21 +++++ ...e_75439.foo.MatchBranchSimplification.diff | 87 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 src/test/mir-opt/issues/issue-75439.rs create mode 100644 src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff diff --git a/src/test/mir-opt/issues/issue-75439.rs b/src/test/mir-opt/issues/issue-75439.rs new file mode 100644 index 0000000000000..44d6bc619d3bb --- /dev/null +++ b/src/test/mir-opt/issues/issue-75439.rs @@ -0,0 +1,21 @@ +// EMIT_MIR issue_75439.foo.MatchBranchSimplification.diff + +#![feature(const_fn_transmute)] +#![feature(or_patterns)] + +use std::mem::transmute; + +pub fn foo(bytes: [u8; 16]) -> Option<[u8; 4]> { + // big endian `u32`s + let dwords: [u32; 4] = unsafe { transmute(bytes) }; + const FF: u32 = 0x0000_ffff_u32.to_be(); + if let [0, 0, 0 | FF, ip] = dwords { + Some(unsafe { transmute(ip) }) + } else { + None + } +} + +fn main() { + let _ = foo([0; 16]); +} diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff new file mode 100644 index 0000000000000..43422b36e1e52 --- /dev/null +++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff @@ -0,0 +1,87 @@ +- // MIR for `foo` before MatchBranchSimplification ++ // MIR for `foo` after MatchBranchSimplification + + fn foo(_1: [u8; 16]) -> Option<[u8; 4]> { + debug bytes => _1; // in scope 0 at $DIR/issue-75439.rs:8:12: 8:17 + let mut _0: std::option::Option<[u8; 4]>; // return place in scope 0 at $DIR/issue-75439.rs:8:32: 8:47 + let _2: [u32; 4]; // in scope 0 at $DIR/issue-75439.rs:10:9: 10:15 + let mut _3: [u8; 16]; // in scope 0 at $DIR/issue-75439.rs:10:47: 10:52 + let mut _5: [u8; 4]; // in scope 0 at $DIR/issue-75439.rs:13:14: 13:38 + let mut _6: u32; // in scope 0 at $DIR/issue-75439.rs:13:33: 13:35 + scope 1 { + debug dwords => _2; // in scope 1 at $DIR/issue-75439.rs:10:9: 10:15 + let _4: u32; // in scope 1 at $DIR/issue-75439.rs:12:27: 12:29 + scope 3 { + debug ip => _4; // in scope 3 at $DIR/issue-75439.rs:12:27: 12:29 + scope 4 { + } + } + } + scope 2 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-75439.rs:10:9: 10:15 + StorageLive(_3); // scope 2 at $DIR/issue-75439.rs:10:47: 10:52 + _3 = _1; // scope 2 at $DIR/issue-75439.rs:10:47: 10:52 + _2 = transmute::<[u8; 16], [u32; 4]>(move _3) -> bb1; // scope 2 at $DIR/issue-75439.rs:10:37: 10:53 + // mir::Constant + // + span: $DIR/issue-75439.rs:10:37: 10:46 + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn([u8; 16]) -> [u32; 4] {std::intrinsics::transmute::<[u8; 16], [u32; 4]>}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_3); // scope 2 at $DIR/issue-75439.rs:10:52: 10:53 + switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:13: 12:14 + } + + bb2: { + switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:16: 12:17 + } + + bb3: { + switchInt(_2[2 of 4]) -> [0_u32: bb6, 4294901760_u32: bb7, otherwise: bb4]; // scope 1 at $DIR/issue-75439.rs:12:19: 12:20 + } + + bb4: { + discriminant(_0) = 0; // scope 1 at $DIR/issue-75439.rs:15:9: 15:13 + goto -> bb9; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + } + + bb5: { + StorageLive(_5); // scope 3 at $DIR/issue-75439.rs:13:14: 13:38 + StorageLive(_6); // scope 4 at $DIR/issue-75439.rs:13:33: 13:35 + _6 = _4; // scope 4 at $DIR/issue-75439.rs:13:33: 13:35 + _5 = transmute::(move _6) -> bb8; // scope 4 at $DIR/issue-75439.rs:13:23: 13:36 + // mir::Constant + // + span: $DIR/issue-75439.rs:13:23: 13:32 + // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32) -> [u8; 4] {std::intrinsics::transmute::}, val: Value(Scalar()) } + } + + bb6: { + StorageLive(_4); // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 + _4 = _2[3 of 4]; // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 + goto -> bb5; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + } + + bb7: { + StorageLive(_4); // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 + _4 = _2[3 of 4]; // scope 1 at $DIR/issue-75439.rs:12:27: 12:29 + goto -> bb5; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + } + + bb8: { + StorageDead(_6); // scope 4 at $DIR/issue-75439.rs:13:35: 13:36 + ((_0 as Some).0: [u8; 4]) = move _5; // scope 3 at $DIR/issue-75439.rs:13:9: 13:39 + discriminant(_0) = 1; // scope 3 at $DIR/issue-75439.rs:13:9: 13:39 + StorageDead(_5); // scope 3 at $DIR/issue-75439.rs:13:38: 13:39 + StorageDead(_4); // scope 1 at $DIR/issue-75439.rs:14:5: 14:6 + goto -> bb9; // scope 1 at $DIR/issue-75439.rs:12:5: 16:6 + } + + bb9: { + StorageDead(_2); // scope 0 at $DIR/issue-75439.rs:17:1: 17:2 + return; // scope 0 at $DIR/issue-75439.rs:17:2: 17:2 + } + } + From 2c8a4c8f73e8b36e72b15e7f97ef29ad36c15e17 Mon Sep 17 00:00:00 2001 From: scottmcm Date: Sat, 5 Sep 2020 19:02:21 +0000 Subject: [PATCH 05/37] Nightly is currently 1.48 --- library/alloc/src/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index b6d923daaf2ab..4a263829bd421 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2772,7 +2772,7 @@ impl From<&str> for Vec { } } -#[stable(feature = "array_try_from_vec", since = "1.47.0")] +#[stable(feature = "array_try_from_vec", since = "1.48.0")] impl TryFrom> for [T; N] { type Error = Vec; From 685f04220ee584f00f60e5ff9d7aca16351c5399 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 6 Sep 2020 12:00:22 +0800 Subject: [PATCH 06/37] Clean up vec benches bench_in_place style --- library/alloc/benches/vec.rs | 43 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/library/alloc/benches/vec.rs b/library/alloc/benches/vec.rs index 5ba3e0e00572c..6703a99b15155 100644 --- a/library/alloc/benches/vec.rs +++ b/library/alloc/benches/vec.rs @@ -457,9 +457,7 @@ fn bench_clone_from_10_1000_0100(b: &mut Bencher) { } macro_rules! bench_in_place { - ( - $($fname:ident, $type:ty , $count:expr, $init: expr);* - ) => { + ($($fname:ident, $type:ty, $count:expr, $init:expr);*) => { $( #[bench] fn $fname(b: &mut Bencher) { @@ -467,7 +465,8 @@ macro_rules! bench_in_place { let src: Vec<$type> = black_box(vec![$init; $count]); let mut sink = src.into_iter() .enumerate() - .map(|(idx, e)| { (idx as $type) ^ e }).collect::>(); + .map(|(idx, e)| idx as $type ^ e) + .collect::>(); black_box(sink.as_mut_ptr()) }); } @@ -476,24 +475,24 @@ macro_rules! bench_in_place { } bench_in_place![ - bench_in_place_xxu8_i0_0010, u8, 10, 0; - bench_in_place_xxu8_i0_0100, u8, 100, 0; - bench_in_place_xxu8_i0_1000, u8, 1000, 0; - bench_in_place_xxu8_i1_0010, u8, 10, 1; - bench_in_place_xxu8_i1_0100, u8, 100, 1; - bench_in_place_xxu8_i1_1000, u8, 1000, 1; - bench_in_place_xu32_i0_0010, u32, 10, 0; - bench_in_place_xu32_i0_0100, u32, 100, 0; - bench_in_place_xu32_i0_1000, u32, 1000, 0; - bench_in_place_xu32_i1_0010, u32, 10, 1; - bench_in_place_xu32_i1_0100, u32, 100, 1; - bench_in_place_xu32_i1_1000, u32, 1000, 1; - bench_in_place_u128_i0_0010, u128, 10, 0; - bench_in_place_u128_i0_0100, u128, 100, 0; - bench_in_place_u128_i0_1000, u128, 1000, 0; - bench_in_place_u128_i1_0010, u128, 10, 1; - bench_in_place_u128_i1_0100, u128, 100, 1; - bench_in_place_u128_i1_1000, u128, 1000, 1 + bench_in_place_xxu8_0010_i0, u8, 10, 0; + bench_in_place_xxu8_0100_i0, u8, 100, 0; + bench_in_place_xxu8_1000_i0, u8, 1000, 0; + bench_in_place_xxu8_0010_i1, u8, 10, 1; + bench_in_place_xxu8_0100_i1, u8, 100, 1; + bench_in_place_xxu8_1000_i1, u8, 1000, 1; + bench_in_place_xu32_0010_i0, u32, 10, 0; + bench_in_place_xu32_0100_i0, u32, 100, 0; + bench_in_place_xu32_1000_i0, u32, 1000, 0; + bench_in_place_xu32_0010_i1, u32, 10, 1; + bench_in_place_xu32_0100_i1, u32, 100, 1; + bench_in_place_xu32_1000_i1, u32, 1000, 1; + bench_in_place_u128_0010_i0, u128, 10, 0; + bench_in_place_u128_0100_i0, u128, 100, 0; + bench_in_place_u128_1000_i0, u128, 1000, 0; + bench_in_place_u128_0010_i1, u128, 10, 1; + bench_in_place_u128_0100_i1, u128, 100, 1; + bench_in_place_u128_1000_i1, u128, 1000, 1 ]; #[bench] From 3d89ee9586354e736cfe4a472d8aaa507d10f77c Mon Sep 17 00:00:00 2001 From: scottmcm Date: Mon, 7 Sep 2020 02:30:42 +0000 Subject: [PATCH 07/37] Typo fix Thanks, Amanieu Co-authored-by: Amanieu d'Antras --- library/alloc/src/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec.rs b/library/alloc/src/vec.rs index 4a263829bd421..ccba23f684877 100644 --- a/library/alloc/src/vec.rs +++ b/library/alloc/src/vec.rs @@ -2813,7 +2813,7 @@ impl TryFrom> for [T; N] { // SAFETY: `.set_len(0)` is always sound. unsafe { vec.set_len(0) }; - // SAFETY: A `Vec`'s pointer is always aligned property, and + // SAFETY: A `Vec`'s pointer is always aligned properly, and // the alignment the array needs is the same as the items. // We checked earlier that we have sufficient items. // The items will not double-drop as the `set_len` From caeb5544ecd9dba4d67b68b8c1b32d8132c6d5f2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Sep 2020 11:31:37 +0200 Subject: [PATCH 08/37] do not inline black_box when building for Miri --- library/core/src/hint.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index d40a380286762..a7b8c2f373a9e 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -108,7 +108,8 @@ pub fn spin_loop() { /// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The /// extent to which it can block optimisations may vary depending upon the platform and code-gen /// backend used. Programs cannot rely on `black_box` for *correctness* in any way. -#[inline] +#[cfg_attr(not(miri), inline)] +#[cfg_attr(miri, inline(never))] #[unstable(feature = "test", issue = "50297")] #[allow(unreachable_code)] // this makes #[cfg] a bit easier below. pub fn black_box(dummy: T) -> T { From 4b5cd544d1268df8f95424a7dc77ce6c852bac56 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Sep 2020 11:37:35 +0200 Subject: [PATCH 09/37] use black_box instead of local optimziation barriers in const tests where possible --- .../ui/consts/cast-discriminant-zst-enum.rs | 14 ++++++-------- src/test/ui/consts/const_discriminant.rs | 17 ++++++----------- 2 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs index a77258120111e..743043609ec32 100644 --- a/src/test/ui/consts/cast-discriminant-zst-enum.rs +++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs @@ -1,5 +1,6 @@ // run-pass // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32. +use std::hint::black_box; #[derive(Copy, Clone)] enum Nums { @@ -12,9 +13,6 @@ const NEG_ONE_I32: i32 = Nums::NegOne as i32; const NEG_ONE_I64: i64 = Nums::NegOne as i64; const NEG_ONE_I128: i128 = Nums::NegOne as i128; -#[inline(never)] -fn identity(t: T) -> T { t } - fn test_as_arg(n: Nums) { assert_eq!(-1i8, n as i8); assert_eq!(-1i16, n as i16); @@ -31,11 +29,11 @@ fn main() { assert_eq!(-1i64, kind as i64); assert_eq!(-1i128, kind as i128); - assert_eq!(-1i8, identity(kind) as i8); - assert_eq!(-1i16, identity(kind) as i16); - assert_eq!(-1i32, identity(kind) as i32); - assert_eq!(-1i64, identity(kind) as i64); - assert_eq!(-1i128, identity(kind) as i128); + assert_eq!(-1i8, black_box(kind) as i8); + assert_eq!(-1i16, black_box(kind) as i16); + assert_eq!(-1i32, black_box(kind) as i32); + assert_eq!(-1i64, black_box(kind) as i64); + assert_eq!(-1i128, black_box(kind) as i128); test_as_arg(Nums::NegOne); diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index 1ad5134e71c52..24fb760f5a3f7 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -1,14 +1,9 @@ // run-pass -#![feature(const_discriminant)] +#![feature(const_discriminant, test)] #![allow(dead_code)] use std::mem::{discriminant, Discriminant}; - -// `discriminant(const_expr)` may get const-propagated. -// As we want to check that const-eval is equal to ordinary exection, -// we wrap `const_expr` with a function which is not const to prevent this. -#[inline(never)] -fn identity(x: T) -> T { x } +use std::hint::black_box; enum Test { A(u8), @@ -31,10 +26,10 @@ const TEST_V: Discriminant = discriminant(&SingleVariant::V); fn main() { assert_eq!(TEST_A, TEST_A_OTHER); - assert_eq!(TEST_A, discriminant(identity(&Test::A(17)))); - assert_eq!(TEST_B, discriminant(identity(&Test::B))); + assert_eq!(TEST_A, discriminant(black_box(&Test::A(17)))); + assert_eq!(TEST_B, discriminant(black_box(&Test::B))); assert_ne!(TEST_A, TEST_B); - assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 }))); + assert_ne!(TEST_B, discriminant(black_box(&Test::C { a: 42, b: 7 }))); - assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V))); + assert_eq!(TEST_V, discriminant(black_box(&SingleVariant::V))); } From 47668edb64ed1f8676cfcb4c9ccb6fe018f660c5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Sep 2020 13:04:41 +0200 Subject: [PATCH 10/37] Separate feature flags Co-authored-by: Ivan Tham --- src/test/ui/consts/const_discriminant.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index 24fb760f5a3f7..d016d236dbf81 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -1,5 +1,6 @@ // run-pass -#![feature(const_discriminant, test)] +#![feature(const_discriminant)] +#![feature(test)] #![allow(dead_code)] use std::mem::{discriminant, Discriminant}; From 284b16913aa6fccdf7b14edc3bb2693aadd39919 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 7 Sep 2020 13:05:59 +0200 Subject: [PATCH 11/37] add missing feature flag --- src/test/ui/consts/cast-discriminant-zst-enum.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/consts/cast-discriminant-zst-enum.rs b/src/test/ui/consts/cast-discriminant-zst-enum.rs index 743043609ec32..9c02d232e134b 100644 --- a/src/test/ui/consts/cast-discriminant-zst-enum.rs +++ b/src/test/ui/consts/cast-discriminant-zst-enum.rs @@ -1,5 +1,6 @@ // run-pass // Test a ZST enum whose dicriminant is ~0i128. This caused an ICE when casting to a i32. +#![feature(test)] use std::hint::black_box; #[derive(Copy, Clone)] From daa62d9081bfeeb0f438f88eb69082c227a5c221 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Sep 2020 17:40:15 +0200 Subject: [PATCH 12/37] Add as_str() and AsRef to string::Drain. --- library/alloc/src/string.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index e1724bf3c9a90..d27dd9c93402c 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2462,6 +2462,32 @@ impl Drop for Drain<'_> { } } +impl<'a> Drain<'a> { + /// Returns the remaining (sub)string of this iterator as a slice. + /// + /// # Examples + /// + /// ``` + /// #![feature(string_drain_as_str)] + /// let mut s = String::from("abc"); + /// let mut drain = s.drain(..); + /// assert_eq!(drain.as_str(), "abc"); + /// let _ = drain.next().unwrap(); + /// assert_eq!(drain.as_str(), "bc"); + /// ``` + #[unstable(feature = "string_drain_as_str", issue = "none")] + pub fn as_str(&self) -> &str { + self.iter.as_str() + } +} + +#[unstable(feature = "string_drain_as_str", issue = "none")] +impl<'a> AsRef for Drain<'a> { + fn as_ref(&self) -> &str { + self.as_str() + } +} + #[stable(feature = "drain", since = "1.6.0")] impl Iterator for Drain<'_> { type Item = char; From 673284058b53992cfd66c04b9db8e551a0dc9996 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Sep 2020 17:40:44 +0200 Subject: [PATCH 13/37] Show remaining data in string::Drain's Debug impl. --- library/alloc/src/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index d27dd9c93402c..14ffd06e9bdfd 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2439,7 +2439,7 @@ pub struct Drain<'a> { #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Drain<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("Drain { .. }") + f.debug_tuple("Drain").field(&self.as_str()).finish() } } From f5bb523e94b431c35b495b6ad6ae94495b653a5f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Sep 2020 17:59:43 +0200 Subject: [PATCH 14/37] Add AsRef<[u8]> for String's Drain. --- library/alloc/src/string.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 14ffd06e9bdfd..a164de8b4d387 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2488,6 +2488,13 @@ impl<'a> AsRef for Drain<'a> { } } +#[unstable(feature = "string_drain_as_str", issue = "none")] +impl<'a> AsRef<[u8]> for Drain<'a> { + fn as_ref(&self) -> &[u8] { + self.as_str().as_bytes() + } +} + #[stable(feature = "drain", since = "1.6.0")] impl Iterator for Drain<'_> { type Item = char; From f2a32909e0649eb589406ddac63597ba34273c95 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Sep 2020 19:10:06 +0200 Subject: [PATCH 15/37] Mark AsRef impls for String's Drain as stable. Trait implementations effectively can't be #[unstable]. --- library/alloc/src/string.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index a164de8b4d387..047ae942cd9a2 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2481,14 +2481,14 @@ impl<'a> Drain<'a> { } } -#[unstable(feature = "string_drain_as_str", issue = "none")] +#[stable(feature = "string_drain_as_ref", since = "1.48.0")] impl<'a> AsRef for Drain<'a> { fn as_ref(&self) -> &str { self.as_str() } } -#[unstable(feature = "string_drain_as_str", issue = "none")] +#[stable(feature = "string_drain_as_ref", since = "1.48.0")] impl<'a> AsRef<[u8]> for Drain<'a> { fn as_ref(&self) -> &[u8] { self.as_str().as_bytes() From 829019d4043a6e9dd1305113f43b30fc8415893d Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 9 Sep 2020 19:38:51 +0200 Subject: [PATCH 16/37] Disable AsRef implementations for String's Drain. Since trait implementations cannot be unstable, we should only add them when the as_str feature gets stabilized. Until then, only `.as_str()` is available (behind a feature gate). --- library/alloc/src/string.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 047ae942cd9a2..b9506281ed629 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2475,25 +2475,26 @@ impl<'a> Drain<'a> { /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_str(), "bc"); /// ``` - #[unstable(feature = "string_drain_as_str", issue = "none")] + #[unstable(feature = "string_drain_as_str", issue = "none")] // Note: uncomment AsRef impls below when stabilizing. pub fn as_str(&self) -> &str { self.iter.as_str() } } -#[stable(feature = "string_drain_as_ref", since = "1.48.0")] -impl<'a> AsRef for Drain<'a> { - fn as_ref(&self) -> &str { - self.as_str() - } -} - -#[stable(feature = "string_drain_as_ref", since = "1.48.0")] -impl<'a> AsRef<[u8]> for Drain<'a> { - fn as_ref(&self) -> &[u8] { - self.as_str().as_bytes() - } -} +// Uncomment when stabilizing `string_drain_as_str`. +// #[unstable(feature = "string_drain_as_str", issue = "none")] +// impl<'a> AsRef for Drain<'a> { +// fn as_ref(&self) -> &str { +// self.as_str() +// } +// } +// +// #[unstable(feature = "string_drain_as_str", issue = "none")] +// impl<'a> AsRef<[u8]> for Drain<'a> { +// fn as_ref(&self) -> &[u8] { +// self.as_str().as_bytes() +// } +// } #[stable(feature = "drain", since = "1.6.0")] impl Iterator for Drain<'_> { From 91f7d761e762d0d9f47cf61cf5d942fd93eaf2a8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 12 Sep 2020 10:33:49 +0200 Subject: [PATCH 17/37] also assert ScalarMaybeUninit size --- compiler/rustc_middle/src/mir/interpret/value.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs index 7d6ff3eb5c1cc..7741c76ff3e45 100644 --- a/compiler/rustc_middle/src/mir/interpret/value.rs +++ b/compiler/rustc_middle/src/mir/interpret/value.rs @@ -578,6 +578,9 @@ pub enum ScalarMaybeUninit { Uninit, } +#[cfg(target_arch = "x86_64")] +static_assert_size!(ScalarMaybeUninit, 24); + impl From> for ScalarMaybeUninit { #[inline(always)] fn from(s: Scalar) -> Self { From f567287f9f35e4d4781213bddc5770e270f48d0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 15 Sep 2020 22:44:43 +0200 Subject: [PATCH 18/37] don't convert types to the same type with try_into (clippy::useless_conversion) --- compiler/rustc_mir/src/dataflow/move_paths/builder.rs | 5 +---- compiler/rustc_mir/src/interpret/place.rs | 6 ++---- compiler/rustc_mir_build/src/build/matches/util.rs | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index b083044a9c6d9..eb92461672259 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -4,7 +4,6 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use smallvec::{smallvec, SmallVec}; -use std::convert::TryInto; use std::mem; use super::abs_domain::Lift; @@ -482,10 +481,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty; let len: u64 = match base_ty.kind() { ty::Array(_, size) => { - let length = size.eval_usize(self.builder.tcx, self.builder.param_env); + let length: u64 = size.eval_usize(self.builder.tcx, self.builder.param_env); length - .try_into() - .expect("slice pattern of array with more than u32::MAX elements") } _ => bug!("from_end: false slice pattern of non-array type"), }; diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index 9e16063bd21af..3b22eb5d98719 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -551,7 +551,7 @@ where let n = base.len(self)?; if n < min_length { // This can only be reached in ConstProp and non-rustc-MIR. - throw_ub!(BoundsCheckFailed { len: min_length.into(), index: n }); + throw_ub!(BoundsCheckFailed { len: min_length, index: n }); } let index = if from_end { @@ -565,9 +565,7 @@ where self.mplace_index(base, index)? } - Subslice { from, to, from_end } => { - self.mplace_subslice(base, u64::from(from), u64::from(to), from_end)? - } + Subslice { from, to, from_end } => self.mplace_subslice(base, from, to, from_end)?, }) } diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index d6e828c966a95..4ef88c25cadf3 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind() { ty::Array(_, length) => { - (length.eval_usize(tcx, self.hir.param_env).try_into().unwrap(), true) + (length.eval_usize(tcx, self.hir.param_env), true) } _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), }; From de0d55cb3c197b13d90922c8998bf90399f3b8a2 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 08:42:39 -0700 Subject: [PATCH 19/37] library/panic_unwind: Add UNWIND_DATA_REG for RISC-V 32-bit Signed-off-by: Alistair Francis --- library/panic_unwind/src/gcc.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 85a2a18947db2..81b7b556eb4f0 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -123,6 +123,9 @@ const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 #[cfg(target_arch = "riscv64")] const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 +#[cfg(target_arch = "riscv32")] +const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 + // The following code is based on GCC's C and C++ personality routines. For reference, see: // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c From 84fe26c4d33924d2195af4324f036b64709baba2 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 08:43:54 -0700 Subject: [PATCH 20/37] library/std: linux: Add support for RISC-V 32-bit Signed-off-by: Alistair Francis --- library/std/src/os/linux/raw.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/linux/raw.rs b/library/std/src/os/linux/raw.rs index a007fd2b6be04..4ff3a6e578984 100644 --- a/library/std/src/os/linux/raw.rs +++ b/library/std/src/os/linux/raw.rs @@ -234,7 +234,8 @@ mod arch { target_arch = "mips64", target_arch = "s390x", target_arch = "sparc64", - target_arch = "riscv64" + target_arch = "riscv64", + target_arch = "riscv32" ))] mod arch { pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; From cd066c9debeace035d02867a5b5b2d72197f1831 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 08:44:35 -0700 Subject: [PATCH 21/37] library/std: raw: Add support for RISC-V 32-bit Signed-off-by: Alistair Francis --- library/std/src/os/raw/mod.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 83e8853fe7923..16272aa05712f 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -22,7 +22,8 @@ mod tests; target_arch = "powerpc", target_arch = "powerpc64", target_arch = "s390x", - target_arch = "riscv64" + target_arch = "riscv64", + target_arch = "riscv32" ) ), all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), @@ -65,7 +66,8 @@ pub type c_char = u8; target_arch = "powerpc", target_arch = "powerpc64", target_arch = "s390x", - target_arch = "riscv64" + target_arch = "riscv64", + target_arch = "riscv32" ) ), all(target_os = "android", any(target_arch = "aarch64", target_arch = "arm")), From cf075355da15c9fb0b1c975649dd13759a78a2bd Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 08:45:08 -0700 Subject: [PATCH 22/37] library/std: sys_common: Add support for RISC-V 32-bit Signed-off-by: Alistair Francis --- library/std/src/sys_common/alloc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys_common/alloc.rs b/library/std/src/sys_common/alloc.rs index c669410078592..f22476be32560 100644 --- a/library/std/src/sys_common/alloc.rs +++ b/library/std/src/sys_common/alloc.rs @@ -14,7 +14,8 @@ use crate::ptr; target_arch = "powerpc64", target_arch = "asmjs", target_arch = "wasm32", - target_arch = "hexagon" + target_arch = "hexagon", + target_arch = "riscv32" )))] pub const MIN_ALIGN: usize = 8; #[cfg(all(any( From 0f3ccbd662977d9434f8478a379f292c5bb72a8c Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 08:45:49 -0700 Subject: [PATCH 23/37] library/unwind: Add support for RISC-V 32-bit Signed-off-by: Alistair Francis --- library/unwind/src/libunwind.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 0c57861f70a82..2d65ded390916 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -57,6 +57,9 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "riscv64")] pub const unwinder_private_data_size: usize = 2; +#[cfg(target_arch = "riscv32")] +pub const unwinder_private_data_size: usize = 2; + #[cfg(target_os = "emscripten")] pub const unwinder_private_data_size: usize = 20; From be372657089da3b7e88c2baaa44b0b833f3a31d3 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 16 Sep 2020 12:00:56 -0400 Subject: [PATCH 24/37] Give a better error message when x.py uses the wrong stage for CI --- src/bootstrap/config.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 30c9e012cd6f5..913104ff9e3dc 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -616,7 +616,13 @@ impl Config { | Subcommand::Build { .. } | Subcommand::Bench { .. } | Subcommand::Dist { .. } - | Subcommand::Install { .. } => assert_eq!(config.stage, 2), + | Subcommand::Install { .. } => { + assert_eq!( + config.stage, 2, + "x.py should be run with `--stage 2` on CI, but was run with `--stage {}`", + config.stage, + ); + } Subcommand::Clean { .. } | Subcommand::Check { .. } | Subcommand::Clippy { .. } From 3e942958536aad794cec08a2d2b8d6f125e36bb4 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 09:37:00 -0700 Subject: [PATCH 25/37] tools/build-manifest: Add support for RISC-V 32-bit Signed-off-by: Alistair Francis --- src/tools/build-manifest/src/main.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 58022484fa6cc..1e86f7a4737cc 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -110,6 +110,7 @@ static TARGETS: &[&str] = &[ "riscv32i-unknown-none-elf", "riscv32imc-unknown-none-elf", "riscv32imac-unknown-none-elf", + "riscv32gc-unknown-linux-gnu", "riscv64imac-unknown-none-elf", "riscv64gc-unknown-none-elf", "riscv64gc-unknown-linux-gnu", From 1d930483247bac3dd7df3470abd5432d198fe755 Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Tue, 15 Sep 2020 09:56:17 -0700 Subject: [PATCH 26/37] give better suggestion when matching a const range --- compiler/rustc_typeck/src/check/pat.rs | 53 +++++++++++++++++++++----- src/test/ui/issues/issue-76191.rs | 5 +++ src/test/ui/issues/issue-76191.stderr | 26 ++++++++++++- 3 files changed, 73 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 6be2fdf9f1904..3b1559dfcf5ef 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -772,12 +772,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } _ => { - let const_def_id = match pat_ty.kind() { + let (type_def_id, item_def_id) = match pat_ty.kind() { Adt(def, _) => match res { - Res::Def(DefKind::Const, _) => Some(def.did), - _ => None, + Res::Def(DefKind::Const, def_id) => (Some(def.did), Some(def_id)), + _ => (None, None), }, - _ => None, + _ => (None, None), }; let ranges = &[ @@ -788,11 +788,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.lang_items().range_inclusive_struct(), self.tcx.lang_items().range_to_inclusive_struct(), ]; - if const_def_id != None && ranges.contains(&const_def_id) { - let msg = "constants only support matching by type, \ - if you meant to match against a range of values, \ - consider using a range pattern like `min ..= max` in the match block"; - e.note(msg); + if type_def_id != None && ranges.contains(&type_def_id) { + let generic_message = match item_def_id { + Some(def_id) => match self.tcx.hir().get_if_local(def_id) { + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Const(_, body_id), + .. + })) => match self.tcx.hir().get(body_id.hir_id) { + hir::Node::Expr(expr) => { + if hir::is_range_literal(expr) { + let span = self.tcx.hir().span(body_id.hir_id); + if let Ok(snip) = + self.tcx.sess.source_map().span_to_snippet(span) + { + e.span_suggestion_verbose( + span, + "you may want to move the range into the match block", + snip, + Applicability::MachineApplicable + ); + false + } else { + true + } + } else { + true + } + } + _ => true, + }, + _ => true, + }, + _ => true, + }; + + if generic_message { + let msg = "constants only support matching by type, \ + if you meant to match against a range of values, \ + consider using a range pattern like `min ..= max` in the match block"; + e.note(msg); + } } else { let msg = "introduce a new binding instead"; let sugg = format!("other_{}", ident.as_str().to_lowercase()); diff --git a/src/test/ui/issues/issue-76191.rs b/src/test/ui/issues/issue-76191.rs index bc327123c6fe9..d9790d2b56e28 100644 --- a/src/test/ui/issues/issue-76191.rs +++ b/src/test/ui/issues/issue-76191.rs @@ -2,13 +2,18 @@ #![allow(non_snake_case)] use std::ops::RangeInclusive; + const RANGE: RangeInclusive = 0..=255; +const RANGE2: RangeInclusive = panic!(); + fn main() { let n: i32 = 1; match n { RANGE => {} //~^ ERROR mismatched types + RANGE2 => {} + //~^ ERROR mismatched types _ => {} } } diff --git a/src/test/ui/issues/issue-76191.stderr b/src/test/ui/issues/issue-76191.stderr index a5544d9e9da40..61f4be81f43a4 100644 --- a/src/test/ui/issues/issue-76191.stderr +++ b/src/test/ui/issues/issue-76191.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-76191.rs:10:9 + --> $DIR/issue-76191.rs:13:9 | LL | const RANGE: RangeInclusive = 0..=255; | ------------------------------------------- constant defined here @@ -14,8 +14,30 @@ LL | RANGE => {} | = note: expected type `i32` found struct `RangeInclusive` +help: you may want to move the range into the match block + | +LL | const RANGE: RangeInclusive = 0..=255; + | ^^^^^^^ + +error[E0308]: mismatched types + --> $DIR/issue-76191.rs:15:9 + | +LL | const RANGE2: RangeInclusive = panic!(); + | --------------------------------------------- constant defined here +... +LL | match n { + | - this expression has type `i32` +... +LL | RANGE2 => {} + | ^^^^^^ + | | + | expected `i32`, found struct `RangeInclusive` + | `RANGE2` is interpreted as a constant, not a new binding + | + = note: expected type `i32` + found struct `RangeInclusive` = note: constants only support matching by type, if you meant to match against a range of values, consider using a range pattern like `min ..= max` in the match block -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0308`. From 230355f25f10306211a80040bec1561545715383 Mon Sep 17 00:00:00 2001 From: Gus Wynn Date: Wed, 16 Sep 2020 12:32:10 -0700 Subject: [PATCH 27/37] comments and factor to own method --- compiler/rustc_typeck/src/check/pat.rs | 70 +++++++++++++------------- src/test/ui/issues/issue-76191.stderr | 4 +- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_typeck/src/check/pat.rs b/compiler/rustc_typeck/src/check/pat.rs index 3b1559dfcf5ef..713717cfe1a54 100644 --- a/compiler/rustc_typeck/src/check/pat.rs +++ b/compiler/rustc_typeck/src/check/pat.rs @@ -1,5 +1,6 @@ use crate::check::FnCtxt; use rustc_ast as ast; + use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; @@ -740,6 +741,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat_ty } + fn maybe_suggest_range_literal( + &self, + e: &mut DiagnosticBuilder<'_>, + opt_def_id: Option, + ident: Ident, + ) -> bool { + match opt_def_id { + Some(def_id) => match self.tcx.hir().get_if_local(def_id) { + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Const(_, body_id), .. + })) => match self.tcx.hir().get(body_id.hir_id) { + hir::Node::Expr(expr) => { + if hir::is_range_literal(expr) { + let span = self.tcx.hir().span(body_id.hir_id); + if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) { + e.span_suggestion_verbose( + ident.span, + "you may want to move the range into the match block", + snip, + Applicability::MachineApplicable, + ); + return true; + } + } + } + _ => (), + }, + _ => (), + }, + _ => (), + } + false + } + fn emit_bad_pat_path( &self, mut e: DiagnosticBuilder<'_>, @@ -789,40 +824,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.lang_items().range_to_inclusive_struct(), ]; if type_def_id != None && ranges.contains(&type_def_id) { - let generic_message = match item_def_id { - Some(def_id) => match self.tcx.hir().get_if_local(def_id) { - Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Const(_, body_id), - .. - })) => match self.tcx.hir().get(body_id.hir_id) { - hir::Node::Expr(expr) => { - if hir::is_range_literal(expr) { - let span = self.tcx.hir().span(body_id.hir_id); - if let Ok(snip) = - self.tcx.sess.source_map().span_to_snippet(span) - { - e.span_suggestion_verbose( - span, - "you may want to move the range into the match block", - snip, - Applicability::MachineApplicable - ); - false - } else { - true - } - } else { - true - } - } - _ => true, - }, - _ => true, - }, - _ => true, - }; - - if generic_message { + if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) { let msg = "constants only support matching by type, \ if you meant to match against a range of values, \ consider using a range pattern like `min ..= max` in the match block"; diff --git a/src/test/ui/issues/issue-76191.stderr b/src/test/ui/issues/issue-76191.stderr index 61f4be81f43a4..bdcd2fe1adc5a 100644 --- a/src/test/ui/issues/issue-76191.stderr +++ b/src/test/ui/issues/issue-76191.stderr @@ -16,8 +16,8 @@ LL | RANGE => {} found struct `RangeInclusive` help: you may want to move the range into the match block | -LL | const RANGE: RangeInclusive = 0..=255; - | ^^^^^^^ +LL | 0..=255 => {} + | ^^^^^^^ error[E0308]: mismatched types --> $DIR/issue-76191.rs:15:9 From fd762681666d7fe229acf82a1b7b23476fd96148 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 14:31:42 -0700 Subject: [PATCH 28/37] library/panic_unwind: Consolidate RV32 and RV64 Signed-off-by: Alistair Francis --- library/panic_unwind/src/gcc.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs index 81b7b556eb4f0..1cfd527b5841a 100644 --- a/library/panic_unwind/src/gcc.rs +++ b/library/panic_unwind/src/gcc.rs @@ -120,10 +120,7 @@ const UNWIND_DATA_REG: (i32, i32) = (24, 25); // I0, I1 #[cfg(target_arch = "hexagon")] const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 -#[cfg(target_arch = "riscv64")] -const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 - -#[cfg(target_arch = "riscv32")] +#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] const UNWIND_DATA_REG: (i32, i32) = (10, 11); // x10, x11 // The following code is based on GCC's C and C++ personality routines. For reference, see: From 57b2da808c36fa2acf991379cd971639091122f7 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 16 Sep 2020 15:19:13 -0700 Subject: [PATCH 29/37] library/unwind: Consolidate RV32 and RV64 Signed-off-by: Alistair Francis --- library/unwind/src/libunwind.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 2d65ded390916..677843e12e1be 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -54,10 +54,7 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "sparc64")] pub const unwinder_private_data_size: usize = 2; -#[cfg(target_arch = "riscv64")] -pub const unwinder_private_data_size: usize = 2; - -#[cfg(target_arch = "riscv32")] +#[cfg(any(target_arch = "riscv64", target_arch = "riscv32")] pub const unwinder_private_data_size: usize = 2; #[cfg(target_os = "emscripten")] From 0e3414248a683aa4490c84500cba772c3d920c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 15 Sep 2020 23:10:24 +0200 Subject: [PATCH 30/37] don't lazily evaulate some trivial values for Option::None replacements (clippy::unnecessary_lazy_evaluations) --- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_metadata/src/native_libs.rs | 4 ++-- compiler/rustc_mir/src/dataflow/move_paths/builder.rs | 5 +---- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index efdb7489ba5b0..5b5dbcf192ca1 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -961,7 +961,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & continue; } - let span = sugared_span.take().unwrap_or_else(|| attr.span); + let span = sugared_span.take().unwrap_or(attr.span); if attr.is_doc_comment() || cx.sess().check_name(attr, sym::doc) { cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 3976475cb063e..e76c2cb356f3f 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -170,7 +170,7 @@ impl Collector<'tcx> { feature_err( &self.tcx.sess.parse_sess, sym::static_nobundle, - span.unwrap_or_else(|| rustc_span::DUMMY_SP), + span.unwrap_or(rustc_span::DUMMY_SP), "kind=\"static-nobundle\" is unstable", ) .emit(); @@ -179,7 +179,7 @@ impl Collector<'tcx> { feature_err( &self.tcx.sess.parse_sess, sym::raw_dylib, - span.unwrap_or_else(|| rustc_span::DUMMY_SP), + span.unwrap_or(rustc_span::DUMMY_SP), "kind=\"raw-dylib\" is unstable", ) .emit(); diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index eb92461672259..5c3e353840180 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -480,10 +480,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { }; let base_ty = base_place.ty(self.builder.body, self.builder.tcx).ty; let len: u64 = match base_ty.kind() { - ty::Array(_, size) => { - let length: u64 = size.eval_usize(self.builder.tcx, self.builder.param_env); - length - } + ty::Array(_, size) => size.eval_usize(self.builder.tcx, self.builder.param_env), _ => bug!("from_end: false slice pattern of non-array type"), }; for offset in from..to { From 3d1b6d6cc29587ace6895814fa32ec38a49d8a68 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Thu, 17 Sep 2020 07:10:10 -0700 Subject: [PATCH 31/37] library/unwind: Add missing ) Signed-off-by: Alistair Francis --- library/unwind/src/libunwind.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 677843e12e1be..dcf4fcd4e5aab 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -54,7 +54,7 @@ pub const unwinder_private_data_size: usize = 2; #[cfg(target_arch = "sparc64")] pub const unwinder_private_data_size: usize = 2; -#[cfg(any(target_arch = "riscv64", target_arch = "riscv32")] +#[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))] pub const unwinder_private_data_size: usize = 2; #[cfg(target_os = "emscripten")] From e03f4164d9229d8a79ab2d9c20221d0b646734ae Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 1 Sep 2020 12:28:55 -0700 Subject: [PATCH 32/37] Default to implicit (not explicit) rules for promotability in `const fn` --- compiler/rustc_mir/src/transform/promote_consts.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 1d2295a37dddf..b6124049579fd 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -734,7 +734,14 @@ impl<'tcx> Validator<'_, 'tcx> { ) -> Result<(), Unpromotable> { let fn_ty = callee.ty(self.body, self.tcx); - if !self.explicit && self.const_kind.is_none() { + // `const` and `static` use the explicit rules for promotion regardless of the `Candidate`, + // meaning calls to `const fn` can be promoted. + let context_uses_explicit_promotion_rules = matches!( + self.const_kind, + Some(hir::ConstContext::Static(_) | hir::ConstContext::Const) + ); + + if !self.explicit && !context_uses_explicit_promotion_rules { if let ty::FnDef(def_id, _) = *fn_ty.kind() { // Never promote runtime `const fn` calls of // functions without `#[rustc_promotable]`. From 3f68ae47df90d2803c849503a4cbdb2bb3dbb9a6 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 8 Sep 2020 20:17:23 +0200 Subject: [PATCH 33/37] Add `BITS` associated constant to all integer types. --- library/core/src/num/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 050c187e55576..33bcf93676b2a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -348,6 +348,10 @@ $EndFeature, " pub const MAX: Self = !Self::MIN; } + /// The size of this integer type in bits. + #[unstable(feature = "int_bits_const", issue = "none")] + pub const BITS: u32 = $BITS; + doc_comment! { concat!("Converts a string slice in a given base to an integer. @@ -2601,6 +2605,10 @@ $EndFeature, " pub const MAX: Self = !0; } + /// The size of this integer type in bits. + #[unstable(feature = "int_bits_const", issue = "none")] + pub const BITS: u32 = $BITS; + doc_comment! { concat!("Converts a string slice in a given base to an integer. From 5c30a16fa03efaf87241b363f4323743746c12b0 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 8 Sep 2020 20:24:55 +0200 Subject: [PATCH 34/37] Add example/test to ::BITS. --- library/core/src/num/mod.rs | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 33bcf93676b2a..5df67a5f53df7 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -348,9 +348,19 @@ $EndFeature, " pub const MAX: Self = !Self::MIN; } - /// The size of this integer type in bits. - #[unstable(feature = "int_bits_const", issue = "none")] - pub const BITS: u32 = $BITS; + doc_comment! { + concat!("The size of this integer type in bits. + +# Examples + +``` +", $Feature, "#![feature(int_bits_const)] +assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");", +$EndFeature, " +```"), + #[unstable(feature = "int_bits_const", issue = "none")] + pub const BITS: u32 = $BITS; + } doc_comment! { concat!("Converts a string slice in a given base to an integer. @@ -2605,9 +2615,19 @@ $EndFeature, " pub const MAX: Self = !0; } - /// The size of this integer type in bits. - #[unstable(feature = "int_bits_const", issue = "none")] - pub const BITS: u32 = $BITS; + doc_comment! { + concat!("The size of this integer type in bits. + +# Examples + +``` +", $Feature, "#![feature(int_bits_const)] +assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");", +$EndFeature, " +```"), + #[unstable(feature = "int_bits_const", issue = "none")] + pub const BITS: u32 = $BITS; + } doc_comment! { concat!("Converts a string slice in a given base to an integer. From 1e2dba1e7cf15442257f2cd3ddfe5d0462ee9102 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Tue, 8 Sep 2020 21:39:13 +0200 Subject: [PATCH 35/37] Use `T::BITS` instead of `size_of:: * 8`. --- compiler/rustc_data_structures/src/lib.rs | 1 + .../src/tagged_ptr/copy.rs | 2 +- library/alloc/src/collections/binary_heap.rs | 4 +-- library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 2 +- library/alloc/tests/lib.rs | 1 + library/alloc/tests/string.rs | 5 ++- library/alloc/tests/vec.rs | 2 +- library/core/src/fmt/mod.rs | 2 +- library/core/src/num/bignum.rs | 34 +++++-------------- library/core/src/slice/sort.rs | 6 ++-- library/core/tests/iter.rs | 2 +- library/core/tests/lib.rs | 1 + library/core/tests/num/int_macros.rs | 20 +++++------ library/core/tests/num/uint_macros.rs | 20 +++++------ library/panic_unwind/src/dwarf/mod.rs | 4 +-- library/panic_unwind/src/lib.rs | 1 + 17 files changed, 44 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 88c160e93b66a..06718cc980312 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -14,6 +14,7 @@ #![feature(generators)] #![feature(generator_trait)] #![feature(fn_traits)] +#![feature(int_bits_const)] #![feature(min_specialization)] #![feature(optin_builtin_traits)] #![feature(nll)] diff --git a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs index d39d146db318f..d63bcdb3c2b04 100644 --- a/compiler/rustc_data_structures/src/tagged_ptr/copy.rs +++ b/compiler/rustc_data_structures/src/tagged_ptr/copy.rs @@ -48,7 +48,7 @@ where P: Pointer, T: Tag, { - const TAG_BIT_SHIFT: usize = (8 * std::mem::size_of::()) - T::BITS; + const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS; const ASSERTION: () = { assert!(T::BITS <= P::BITS); // Used for the transmute_copy's below diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs index 24d17fdd880ba..8a7dd9d4249a8 100644 --- a/library/alloc/src/collections/binary_heap.rs +++ b/library/alloc/src/collections/binary_heap.rs @@ -146,7 +146,7 @@ use core::fmt; use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; -use core::mem::{self, size_of, swap, ManuallyDrop}; +use core::mem::{self, swap, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::ptr; @@ -617,7 +617,7 @@ impl BinaryHeap { #[inline(always)] fn log2_fast(x: usize) -> usize { - 8 * size_of::() - (x.leading_zeros() as usize) - 1 + (usize::BITS - x.leading_zeros() - 1) as usize } // `rebuild` takes O(len1 + len2) operations diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 7881c101f9f60..f3c1eee47c721 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -101,6 +101,7 @@ #![feature(fn_traits)] #![feature(fundamental)] #![feature(inplace_iteration)] +#![feature(int_bits_const)] #![feature(lang_items)] #![feature(layout_for_ptr)] #![feature(libc)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 05382d0b5594e..62675665f037f 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -528,7 +528,7 @@ unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec { #[inline] fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { - if mem::size_of::() < 8 && alloc_size > isize::MAX as usize { + if usize::BITS < 64 && alloc_size > isize::MAX as usize { Err(CapacityOverflow) } else { Ok(()) diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index 03737e1ef1f4d..3ee0cfbe74759 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -18,6 +18,7 @@ #![feature(deque_range)] #![feature(inplace_iteration)] #![feature(iter_map_while)] +#![feature(int_bits_const)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs index 4e6043541226f..a6e41b21b618c 100644 --- a/library/alloc/tests/string.rs +++ b/library/alloc/tests/string.rs @@ -1,6 +1,5 @@ use std::borrow::Cow; use std::collections::TryReserveError::*; -use std::mem::size_of; use std::ops::Bound::*; pub trait IntoCow<'a, B: ?Sized> @@ -605,7 +604,7 @@ fn test_try_reserve() { // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. // Any platform that succeeds for these requests is technically broken with // ptr::offset because LLVM is the worst. - let guards_against_isize = size_of::() < 8; + let guards_against_isize = usize::BITS < 64; { // Note: basic stuff is checked by test_reserve @@ -686,7 +685,7 @@ fn test_try_reserve_exact() { const MAX_CAP: usize = isize::MAX as usize; const MAX_USIZE: usize = usize::MAX; - let guards_against_isize = size_of::() < 8; + let guards_against_isize = usize::BITS < 64; { let mut empty_string: String = String::new(); diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 368ca4c543219..a49ca7c256a75 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1341,7 +1341,7 @@ fn test_try_reserve() { // on 64-bit, we assume the OS will give an OOM for such a ridiculous size. // Any platform that succeeds for these requests is technically broken with // ptr::offset because LLVM is the worst. - let guards_against_isize = size_of::() < 8; + let guards_against_isize = usize::BITS < 64; { // Note: basic stuff is checked by test_reserve diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 48b7f2739eeb2..8558cb5a5e8a3 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2086,7 +2086,7 @@ impl Pointer for *const T { f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32); if f.width.is_none() { - f.width = Some(((mem::size_of::() * 8) / 4) + 2); + f.width = Some((usize::BITS / 4) as usize + 2); } } f.flags |= 1 << (FlagV1::Alternate as u32); diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 6f16b93d0488a..6a1a1e1976160 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -20,7 +20,6 @@ #![macro_use] use crate::intrinsics; -use crate::mem; /// Arithmetic operations required by bignums. pub trait FullOps: Sized { @@ -58,25 +57,22 @@ macro_rules! impl_full_ops { // This cannot overflow; // the output is between `0` and `2^nbits * (2^nbits - 1)`. // FIXME: will LLVM optimize this into ADC or similar? - let nbits = mem::size_of::<$ty>() * 8; let v = (self as $bigty) * (other as $bigty) + (carry as $bigty); - ((v >> nbits) as $ty, v as $ty) + ((v >> <$ty>::BITS) as $ty, v as $ty) } fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) { // This cannot overflow; // the output is between `0` and `2^nbits * (2^nbits - 1)`. - let nbits = mem::size_of::<$ty>() * 8; let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) + (carry as $bigty); - ((v >> nbits) as $ty, v as $ty) + ((v >> <$ty>::BITS) as $ty, v as $ty) } fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) { debug_assert!(borrow < other); // This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`. - let nbits = mem::size_of::<$ty>() * 8; - let lhs = ((borrow as $bigty) << nbits) | (self as $bigty); + let lhs = ((borrow as $bigty) << <$ty>::BITS) | (self as $bigty); let rhs = other as $bigty; ((lhs / rhs) as $ty, (lhs % rhs) as $ty) } @@ -128,13 +124,11 @@ macro_rules! define_bignum { /// Makes a bignum from `u64` value. pub fn from_u64(mut v: u64) -> $name { - use crate::mem; - let mut base = [0; $n]; let mut sz = 0; while v > 0 { base[sz] = v as $ty; - v >>= mem::size_of::<$ty>() * 8; + v >>= <$ty>::BITS; sz += 1; } $name { size: sz, base: base } @@ -150,9 +144,7 @@ macro_rules! define_bignum { /// Returns the `i`-th bit where bit 0 is the least significant one. /// In other words, the bit with weight `2^i`. pub fn get_bit(&self, i: usize) -> u8 { - use crate::mem; - - let digitbits = mem::size_of::<$ty>() * 8; + let digitbits = <$ty>::BITS as usize; let d = i / digitbits; let b = i % digitbits; ((self.base[d] >> b) & 1) as u8 @@ -166,8 +158,6 @@ macro_rules! define_bignum { /// Returns the number of bits necessary to represent this value. Note that zero /// is considered to need 0 bits. pub fn bit_length(&self) -> usize { - use crate::mem; - // Skip over the most significant digits which are zero. let digits = self.digits(); let zeros = digits.iter().rev().take_while(|&&x| x == 0).count(); @@ -180,7 +170,7 @@ macro_rules! define_bignum { } // This could be optimized with leading_zeros() and bit shifts, but that's // probably not worth the hassle. - let digitbits = mem::size_of::<$ty>() * 8; + let digitbits = <$ty>::BITS as usize; let mut i = nonzero.len() * digitbits - 1; while self.get_bit(i) == 0 { i -= 1; @@ -265,9 +255,7 @@ macro_rules! define_bignum { /// Multiplies itself by `2^bits` and returns its own mutable reference. pub fn mul_pow2(&mut self, bits: usize) -> &mut $name { - use crate::mem; - - let digitbits = mem::size_of::<$ty>() * 8; + let digitbits = <$ty>::BITS as usize; let digits = bits / digitbits; let bits = bits % digitbits; @@ -393,13 +381,11 @@ macro_rules! define_bignum { /// Divide self by another bignum, overwriting `q` with the quotient and `r` with the /// remainder. pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) { - use crate::mem; - // Stupid slow base-2 long division taken from // https://en.wikipedia.org/wiki/Division_algorithm // FIXME use a greater base ($ty) for the long division. assert!(!d.is_zero()); - let digitbits = mem::size_of::<$ty>() * 8; + let digitbits = <$ty>::BITS as usize; for digit in &mut q.base[..] { *digit = 0; } @@ -462,10 +448,8 @@ macro_rules! define_bignum { impl crate::fmt::Debug for $name { fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result { - use crate::mem; - let sz = if self.size < 1 { 1 } else { self.size }; - let digitlen = mem::size_of::<$ty>() * 2; + let digitlen = <$ty>::BITS as usize / 4; write!(f, "{:#x}", self.base[sz - 1])?; for &v in self.base[..sz - 1].iter().rev() { diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs index 8c14651bd826c..71d2c2c9b2f4c 100644 --- a/library/core/src/slice/sort.rs +++ b/library/core/src/slice/sort.rs @@ -565,7 +565,7 @@ fn break_patterns(v: &mut [T]) { random }; let mut gen_usize = || { - if mem::size_of::() <= 4 { + if usize::BITS <= 32 { gen_u32() as usize } else { (((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize @@ -667,7 +667,7 @@ where /// /// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero, /// this function will immediately switch to heapsort. -fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize) +fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: u32) where F: FnMut(&T, &T) -> bool, { @@ -763,7 +763,7 @@ where } // Limit the number of imbalanced partitions to `floor(log2(len)) + 1`. - let limit = mem::size_of::() * 8 - v.len().leading_zeros() as usize; + let limit = usize::BITS - v.len().leading_zeros(); recurse(v, &mut is_less, None, limit); } diff --git a/library/core/tests/iter.rs b/library/core/tests/iter.rs index 00e3972c42f9d..0eb9af3f454e9 100644 --- a/library/core/tests/iter.rs +++ b/library/core/tests/iter.rs @@ -474,7 +474,7 @@ fn test_iterator_step_by_nth_overflow() { } let mut it = Test(0); - let root = usize::MAX >> (::std::mem::size_of::() * 8 / 2); + let root = usize::MAX >> (usize::BITS / 2); let n = root + 20; (&mut it).step_by(n).nth(n); assert_eq!(it.0, n as Bigger * n as Bigger); diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index a5b1b51e06c64..4db391f3e567e 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -52,6 +52,7 @@ #![feature(partition_point)] #![feature(once_cell)] #![feature(unsafe_block_in_unsafe_fn)] +#![feature(int_bits_const)] #![deny(unsafe_op_in_unsafe_fn)] extern crate test; diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs index 58a585669122c..27e6760e7cbb9 100644 --- a/library/core/tests/num/int_macros.rs +++ b/library/core/tests/num/int_macros.rs @@ -2,7 +2,6 @@ macro_rules! int_module { ($T:ident, $T_i:ident) => { #[cfg(test)] mod tests { - use core::mem; use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use core::$T_i::*; @@ -82,30 +81,27 @@ macro_rules! int_module { #[test] fn test_count_zeros() { - let bits = mem::size_of::<$T>() * 8; - assert_eq!(A.count_zeros(), bits as u32 - 3); - assert_eq!(B.count_zeros(), bits as u32 - 2); - assert_eq!(C.count_zeros(), bits as u32 - 5); + assert_eq!(A.count_zeros(), $T::BITS - 3); + assert_eq!(B.count_zeros(), $T::BITS - 2); + assert_eq!(C.count_zeros(), $T::BITS - 5); } #[test] fn test_leading_trailing_ones() { - let bits = (mem::size_of::<$T>() * 8) as u32; - let a: $T = 0b0101_1111; assert_eq!(a.trailing_ones(), 5); - assert_eq!((!a).leading_ones(), bits - 7); + assert_eq!((!a).leading_ones(), $T::BITS - 7); assert_eq!(a.reverse_bits().leading_ones(), 5); - assert_eq!(_1.leading_ones(), bits); - assert_eq!(_1.trailing_ones(), bits); + assert_eq!(_1.leading_ones(), $T::BITS); + assert_eq!(_1.trailing_ones(), $T::BITS); assert_eq!((_1 << 1).trailing_ones(), 0); assert_eq!(MAX.leading_ones(), 0); - assert_eq!((_1 << 1).leading_ones(), bits - 1); - assert_eq!(MAX.trailing_ones(), bits - 1); + assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq!(MAX.trailing_ones(), $T::BITS - 1); assert_eq!(_0.leading_ones(), 0); assert_eq!(_0.trailing_ones(), 0); diff --git a/library/core/tests/num/uint_macros.rs b/library/core/tests/num/uint_macros.rs index b84a8a7d9f88b..952ec188dc138 100644 --- a/library/core/tests/num/uint_macros.rs +++ b/library/core/tests/num/uint_macros.rs @@ -4,7 +4,6 @@ macro_rules! uint_module { mod tests { use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; use core::$T_i::*; - use std::mem; use std::str::FromStr; use crate::num; @@ -47,30 +46,27 @@ macro_rules! uint_module { #[test] fn test_count_zeros() { - let bits = mem::size_of::<$T>() * 8; - assert!(A.count_zeros() == bits as u32 - 3); - assert!(B.count_zeros() == bits as u32 - 2); - assert!(C.count_zeros() == bits as u32 - 5); + assert!(A.count_zeros() == $T::BITS - 3); + assert!(B.count_zeros() == $T::BITS - 2); + assert!(C.count_zeros() == $T::BITS - 5); } #[test] fn test_leading_trailing_ones() { - let bits = (mem::size_of::<$T>() * 8) as u32; - let a: $T = 0b0101_1111; assert_eq!(a.trailing_ones(), 5); - assert_eq!((!a).leading_ones(), bits - 7); + assert_eq!((!a).leading_ones(), $T::BITS - 7); assert_eq!(a.reverse_bits().leading_ones(), 5); - assert_eq!(_1.leading_ones(), bits); - assert_eq!(_1.trailing_ones(), bits); + assert_eq!(_1.leading_ones(), $T::BITS); + assert_eq!(_1.trailing_ones(), $T::BITS); assert_eq!((_1 << 1).trailing_ones(), 0); assert_eq!((_1 >> 1).leading_ones(), 0); - assert_eq!((_1 << 1).leading_ones(), bits - 1); - assert_eq!((_1 >> 1).trailing_ones(), bits - 1); + assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1); + assert_eq!((_1 >> 1).trailing_ones(), $T::BITS - 1); assert_eq!(_0.leading_ones(), 0); assert_eq!(_0.trailing_ones(), 0); diff --git a/library/panic_unwind/src/dwarf/mod.rs b/library/panic_unwind/src/dwarf/mod.rs index 649bbce52a364..652fbe95a14d1 100644 --- a/library/panic_unwind/src/dwarf/mod.rs +++ b/library/panic_unwind/src/dwarf/mod.rs @@ -53,7 +53,7 @@ impl DwarfReader { } pub unsafe fn read_sleb128(&mut self) -> i64 { - let mut shift: usize = 0; + let mut shift: u32 = 0; let mut result: u64 = 0; let mut byte: u8; loop { @@ -65,7 +65,7 @@ impl DwarfReader { } } // sign-extend - if shift < 8 * mem::size_of::() && (byte & 0x40) != 0 { + if shift < u64::BITS && (byte & 0x40) != 0 { result |= (!0 as u64) << shift; } result as i64 diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 6f31e6dcae70d..162f0386b6692 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -18,6 +18,7 @@ issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/" )] #![feature(core_intrinsics)] +#![feature(int_bits_const)] #![feature(lang_items)] #![feature(libc)] #![feature(nll)] From 1bfe5efe8f635268646da91f1f4f6e616104b71f Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 19 Sep 2020 08:14:41 +0200 Subject: [PATCH 36/37] Add tracking issue number for int_bits_const. --- library/core/src/num/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 5df67a5f53df7..eec149cc3e801 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -358,7 +358,7 @@ $EndFeature, " assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");", $EndFeature, " ```"), - #[unstable(feature = "int_bits_const", issue = "none")] + #[unstable(feature = "int_bits_const", issue = "76904")] pub const BITS: u32 = $BITS; } @@ -2625,7 +2625,7 @@ $EndFeature, " assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");", $EndFeature, " ```"), - #[unstable(feature = "int_bits_const", issue = "none")] + #[unstable(feature = "int_bits_const", issue = "76904")] pub const BITS: u32 = $BITS; } From 15eb638dc9c9f663ab9e596a838c33821ae7f772 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Sat, 19 Sep 2020 08:23:23 +0200 Subject: [PATCH 37/37] Add tracking issue number for string_drain_as_str. --- library/alloc/src/string.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b9506281ed629..ed6443da830d0 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -2475,21 +2475,21 @@ impl<'a> Drain<'a> { /// let _ = drain.next().unwrap(); /// assert_eq!(drain.as_str(), "bc"); /// ``` - #[unstable(feature = "string_drain_as_str", issue = "none")] // Note: uncomment AsRef impls below when stabilizing. + #[unstable(feature = "string_drain_as_str", issue = "76905")] // Note: uncomment AsRef impls below when stabilizing. pub fn as_str(&self) -> &str { self.iter.as_str() } } // Uncomment when stabilizing `string_drain_as_str`. -// #[unstable(feature = "string_drain_as_str", issue = "none")] +// #[unstable(feature = "string_drain_as_str", issue = "76905")] // impl<'a> AsRef for Drain<'a> { // fn as_ref(&self) -> &str { // self.as_str() // } // } // -// #[unstable(feature = "string_drain_as_str", issue = "none")] +// #[unstable(feature = "string_drain_as_str", issue = "76905")] // impl<'a> AsRef<[u8]> for Drain<'a> { // fn as_ref(&self) -> &[u8] { // self.as_str().as_bytes()