From f165f49d228d2582d2dbfd588c2729cfc9585eb0 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Sat, 6 Feb 2021 19:14:13 +0000 Subject: [PATCH 01/25] Slight perf improvement on char::to_ascii_lowercase --- library/core/benches/char/methods.rs | 10 ++++++++++ library/core/src/char/methods.rs | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/library/core/benches/char/methods.rs b/library/core/benches/char/methods.rs index a9a08a4d76200..de4b63030fa7c 100644 --- a/library/core/benches/char/methods.rs +++ b/library/core/benches/char/methods.rs @@ -35,3 +35,13 @@ fn bench_to_digit_radix_var(b: &mut Bencher) { .min() }) } + +#[bench] +fn bench_to_ascii_uppercase(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_uppercase()).min()) +} + +#[bench] +fn bench_to_ascii_lowercase(b: &mut Bencher) { + b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_ascii_lowercase()).min()) +} diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 2baea7842a796..4c28d9cd673af 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1090,7 +1090,8 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> char { - if self.is_ascii() { (*self as u8).to_ascii_uppercase() as char } else { *self } + // 6th bit dictates ascii case. + if self.is_ascii_lowercase() { ((*self as u8) & !0b10_0000u8) as char } else { *self } } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -1118,7 +1119,8 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> char { - if self.is_ascii() { (*self as u8).to_ascii_lowercase() as char } else { *self } + // 6th bit dictates ascii case. + if self.is_ascii_uppercase() { ((*self as u8) | 0b10_0000u8) as char } else { *self } } /// Checks that two values are an ASCII case-insensitive match. From f30c51abe8ce62756f86abbbd6623a9131d3954c Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Sat, 6 Feb 2021 20:35:21 +0000 Subject: [PATCH 02/25] Pulling out constant. --- library/core/src/char/methods.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 4c28d9cd673af..4032e7770772e 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -7,6 +7,9 @@ use crate::unicode::{self, conversions}; use super::*; +/// If 6th bit set ascii is upper case. +const ASCII_CASE_MASK: u8 = 0b10_0000u8; + #[lang = "char"] impl char { /// The highest valid code point a `char` can have. @@ -1090,8 +1093,7 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> char { - // 6th bit dictates ascii case. - if self.is_ascii_lowercase() { ((*self as u8) & !0b10_0000u8) as char } else { *self } + if self.is_ascii_lowercase() { ((*self as u8) & !ASCII_CASE_MASK) as char } else { *self } } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -1119,8 +1121,7 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> char { - // 6th bit dictates ascii case. - if self.is_ascii_uppercase() { ((*self as u8) | 0b10_0000u8) as char } else { *self } + if self.is_ascii_uppercase() { ((*self as u8) | ASCII_CASE_MASK) as char } else { *self } } /// Checks that two values are an ASCII case-insensitive match. From cadcf5ed990dc02ad86cbb9f31423959a5517f50 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Mon, 8 Feb 2021 12:21:36 +0000 Subject: [PATCH 03/25] Unify way to flip 6th bit. (Same assembly generated) --- library/core/benches/ascii.rs | 6 ++++-- library/core/src/char/methods.rs | 5 +---- library/core/src/num/mod.rs | 5 +++-- library/core/src/unicode/mod.rs | 3 +++ 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/library/core/benches/ascii.rs b/library/core/benches/ascii.rs index bc59c378609f0..64938745a4a16 100644 --- a/library/core/benches/ascii.rs +++ b/library/core/benches/ascii.rs @@ -66,6 +66,8 @@ macro_rules! benches { use test::black_box; use test::Bencher; +const ASCII_CASE_MASK: u8 = 0b0010_0000; + benches! { fn case00_alloc_only(_bytes: &mut [u8]) {} @@ -204,7 +206,7 @@ benches! { } } for byte in bytes { - *byte &= !((is_ascii_lowercase(*byte) as u8) << 5) + *byte &= !((is_ascii_lowercase(*byte) as u8) * ASCII_CASE_MASK) } } @@ -216,7 +218,7 @@ benches! { } } for byte in bytes { - *byte -= (is_ascii_lowercase(*byte) as u8) << 5 + *byte -= (is_ascii_lowercase(*byte) as u8) * ASCII_CASE_MASK } } diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 4032e7770772e..bbdb2a5d41b99 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -3,13 +3,10 @@ use crate::slice; use crate::str::from_utf8_unchecked_mut; use crate::unicode::printable::is_printable; -use crate::unicode::{self, conversions}; +use crate::unicode::{self, conversions, ASCII_CASE_MASK}; use super::*; -/// If 6th bit set ascii is upper case. -const ASCII_CASE_MASK: u8 = 0b10_0000u8; - #[lang = "char"] impl char { /// The highest valid code point a `char` can have. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 6bdfa18fa434c..7563a742b9a90 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -5,6 +5,7 @@ use crate::intrinsics; use crate::mem; use crate::str::FromStr; +use crate::unicode::ASCII_CASE_MASK; // Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { @@ -195,7 +196,7 @@ impl u8 { #[inline] pub fn to_ascii_uppercase(&self) -> u8 { // Unset the fifth bit if this is a lowercase letter - *self & !((self.is_ascii_lowercase() as u8) << 5) + *self & !((self.is_ascii_lowercase() as u8) * ASCII_CASE_MASK) } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -218,7 +219,7 @@ impl u8 { #[inline] pub fn to_ascii_lowercase(&self) -> u8 { // Set the fifth bit if this is an uppercase letter - *self | ((self.is_ascii_uppercase() as u8) << 5) + *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK) } /// Checks that two values are an ASCII case-insensitive match. diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index 37ca0a0779b17..b333b46310532 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -17,6 +17,9 @@ mod unicode_data; #[stable(feature = "unicode_version", since = "1.45.0")] pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; +/// If 6th bit set ascii is upper case. +pub(crate) const ASCII_CASE_MASK: u8 = 0b0010_0000; + // For use in liballoc, not re-exported in libstd. pub use unicode_data::{ case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions, From 0060c91cfc9b8c0a73e7a23e16cddf8ac09440fb Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 10 Feb 2021 17:52:36 -0800 Subject: [PATCH 04/25] Make WASI's `hard_link` behavior match other platforms. Following #78026, `std::fs::hard_link` on most platforms does not follow symlinks. Change the WASI implementation to also not follow symlinks. --- library/std/src/sys/wasi/fs.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 4134ef676719c..6050620729f83 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -557,8 +557,9 @@ pub fn symlink(original: &Path, link: &Path) -> io::Result<()> { pub fn link(original: &Path, link: &Path) -> io::Result<()> { let (original, original_file) = open_parent(original)?; let (link, link_file) = open_parent(link)?; + // Pass 0 as the flags argument, meaning don't follow symlinks. original.link( - wasi::LOOKUPFLAGS_SYMLINK_FOLLOW, + 0, osstr2str(original_file.as_ref())?, &link, osstr2str(link_file.as_ref())?, From daa55acdb0bd174bb0bca1f88d5920289808a8f1 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Fri, 12 Feb 2021 13:42:42 +0000 Subject: [PATCH 05/25] Slightly more explicit --- library/core/src/char/methods.rs | 14 +++++++++++--- library/core/src/num/mod.rs | 10 +++++++++- library/core/src/unicode/mod.rs | 3 --- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index bbdb2a5d41b99..3ddf0e638946c 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -3,7 +3,7 @@ use crate::slice; use crate::str::from_utf8_unchecked_mut; use crate::unicode::printable::is_printable; -use crate::unicode::{self, conversions, ASCII_CASE_MASK}; +use crate::unicode::{self, conversions}; use super::*; @@ -1090,7 +1090,11 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_uppercase(&self) -> char { - if self.is_ascii_lowercase() { ((*self as u8) & !ASCII_CASE_MASK) as char } else { *self } + if self.is_ascii_lowercase() { + (*self as u8).ascii_change_case_unchecked() as char + } else { + *self + } } /// Makes a copy of the value in its ASCII lower case equivalent. @@ -1118,7 +1122,11 @@ impl char { #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] #[inline] pub fn to_ascii_lowercase(&self) -> char { - if self.is_ascii_uppercase() { ((*self as u8) | ASCII_CASE_MASK) as char } else { *self } + if self.is_ascii_uppercase() { + (*self as u8).ascii_change_case_unchecked() as char + } else { + *self + } } /// Checks that two values are an ASCII case-insensitive match. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 7563a742b9a90..42ccdd00bbd6a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -5,7 +5,9 @@ use crate::intrinsics; use crate::mem; use crate::str::FromStr; -use crate::unicode::ASCII_CASE_MASK; + +/// If 6th bit set ascii is upper case. +const ASCII_CASE_MASK: u8 = 0b0010_0000; // Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { @@ -222,6 +224,12 @@ impl u8 { *self | (self.is_ascii_uppercase() as u8 * ASCII_CASE_MASK) } + /// Assumes self is ascii + #[inline] + pub(crate) fn ascii_change_case_unchecked(&self) -> u8 { + *self ^ ASCII_CASE_MASK + } + /// Checks that two values are an ASCII case-insensitive match. /// /// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`. diff --git a/library/core/src/unicode/mod.rs b/library/core/src/unicode/mod.rs index b333b46310532..37ca0a0779b17 100644 --- a/library/core/src/unicode/mod.rs +++ b/library/core/src/unicode/mod.rs @@ -17,9 +17,6 @@ mod unicode_data; #[stable(feature = "unicode_version", since = "1.45.0")] pub const UNICODE_VERSION: (u8, u8, u8) = unicode_data::UNICODE_VERSION; -/// If 6th bit set ascii is upper case. -pub(crate) const ASCII_CASE_MASK: u8 = 0b0010_0000; - // For use in liballoc, not re-exported in libstd. pub use unicode_data::{ case_ignorable::lookup as Case_Ignorable, cased::lookup as Cased, conversions, From eace240ebebf46c88959d15bdd634af104de92fe Mon Sep 17 00:00:00 2001 From: Henry Boisdequin <65845077+henryboisdequin@users.noreply.github.com> Date: Sun, 14 Feb 2021 14:39:24 +0530 Subject: [PATCH 06/25] use option> to clean up mir code a little --- compiler/rustc_middle/src/mir/mod.rs | 6 ++---- .../src/transform/check_consts/validation.rs | 19 ++++++++++--------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index cd2bea86ea1a7..718e81c84eddd 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -962,8 +962,7 @@ impl<'tcx> LocalDecl<'tcx> { opt_ty_info: _, opt_match_place: _, pat_span: _, - }) - | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm), + }) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm), ))) ) } @@ -980,8 +979,7 @@ impl<'tcx> LocalDecl<'tcx> { opt_ty_info: _, opt_match_place: _, pat_span: _, - }) - | BindingForm::ImplicitSelf(_), + }) | BindingForm::ImplicitSelf(_), ))) ) } diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 08d969b27bea5..d8e325f1da7e9 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -492,7 +492,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // Special-case reborrows to be more like a copy of a reference. match *rvalue { Rvalue::Ref(_, kind, place) => { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body, place) { + if let Some(place_ref) = place_as_reborrow(self.tcx, self.body, place) { let ctx = match kind { BorrowKind::Shared => { PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) @@ -508,12 +508,12 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { } }; self.visit_local(&place.local, ctx, location); - self.visit_projection(place.local, reborrowed_proj, ctx, location); + self.visit_projection(place.local, place_ref.projection, ctx, location); return; } } Rvalue::AddressOf(mutbl, place) => { - if let Some(reborrowed_proj) = place_as_reborrow(self.tcx, self.body, place) { + if let Some(place_ref) = place_as_reborrow(self.tcx, self.body, place) { let ctx = match mutbl { Mutability::Not => { PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) @@ -521,7 +521,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), }; self.visit_local(&place.local, ctx, location); - self.visit_projection(place.local, reborrowed_proj, ctx, location); + self.visit_projection(place.local, place_ref.projection, ctx, location); return; } } @@ -1016,7 +1016,7 @@ fn place_as_reborrow( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, place: Place<'tcx>, -) -> Option<&'a [PlaceElem<'tcx>]> { +) -> Option> { match place.as_ref().last_projection() { Some((place_base, ProjectionElem::Deref)) => { // A borrow of a `static` also looks like `&(*_1)` in the MIR, but `_1` is a `const` @@ -1025,13 +1025,14 @@ fn place_as_reborrow( None } else { // Ensure the type being derefed is a reference and not a raw pointer. - // // This is sufficient to prevent an access to a `static mut` from being marked as a // reborrow, even if the check above were to disappear. let inner_ty = place_base.ty(body, tcx).ty; - match inner_ty.kind() { - ty::Ref(..) => Some(place_base.projection), - _ => None, + + if let ty::Ref(..) = inner_ty.kind() { + return Some(place_base); + } else { + return None; } } } From 33d8b0456876181883f8d97997a3a0a6e9ff652f Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Sun, 14 Feb 2021 18:23:30 +0000 Subject: [PATCH 07/25] Move const def nearer usage. --- library/core/src/num/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 42ccdd00bbd6a..c13f000a73615 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -6,9 +6,6 @@ use crate::intrinsics; use crate::mem; use crate::str::FromStr; -/// If 6th bit set ascii is upper case. -const ASCII_CASE_MASK: u8 = 0b0010_0000; - // Used because the `?` operator is not allowed in a const context. macro_rules! try_opt { ($e:expr) => { @@ -155,6 +152,9 @@ impl isize { usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } +/// If 6th bit set ascii is upper case. +const ASCII_CASE_MASK: u8 = 0b0010_0000; + #[lang = "u8"] impl u8 { uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", From c675af82b4a5422620d2d8f8db8862320e448ecd Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Sun, 14 Feb 2021 14:42:47 +0100 Subject: [PATCH 08/25] Add internal `collect_into_array[_unchecked]` to remove duplicate code This does not suggest adding such a function to the public API. This is just for the purpose of avoiding duplicate code. Many array methods already contained the same kind of code and there are still many array related methods to come (e.g. `Iterator::{chunks, map_windows, next_n, ...}`) which all basically need this functionality. Writing custom `unsafe` code for each of those seems not like a good idea. --- library/core/src/array/mod.rs | 170 ++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 60 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index d13061d220389..d4fd7545d9bda 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,8 +11,9 @@ use crate::cmp::Ordering; use crate::convert::{Infallible, TryFrom}; use crate::fmt; use crate::hash::{self, Hash}; +use crate::iter::TrustedLen; use crate::marker::Unsize; -use crate::mem::MaybeUninit; +use crate::mem::{self, MaybeUninit}; use crate::ops::{Index, IndexMut}; use crate::slice::{Iter, IterMut}; @@ -426,41 +427,13 @@ impl [T; N] { /// assert_eq!(y, [6, 9, 3, 3]); /// ``` #[unstable(feature = "array_map", issue = "75243")] - pub fn map(self, mut f: F) -> [U; N] + pub fn map(self, f: F) -> [U; N] where F: FnMut(T) -> U, { - struct Guard { - dst: *mut T, - initialized: usize, - } - - impl Drop for Guard { - fn drop(&mut self) { - debug_assert!(self.initialized <= N); - - let initialized_part = - crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized); - // SAFETY: this raw slice will contain only initialized objects - // that's why, it is allowed to drop it. - unsafe { - crate::ptr::drop_in_place(initialized_part); - } - } - } - let mut dst = MaybeUninit::uninit_array::(); - let mut guard: Guard = - Guard { dst: MaybeUninit::slice_as_mut_ptr(&mut dst), initialized: 0 }; - for (src, dst) in IntoIter::new(self).zip(&mut dst) { - dst.write(f(src)); - guard.initialized += 1; - } - // FIXME: Convert to crate::mem::transmute once it works with generics. - // unsafe { crate::mem::transmute::<[MaybeUninit; N], [U; N]>(dst) } - crate::mem::forget(guard); - // SAFETY: At this point we've properly initialized the whole array - // and we just need to cast it to the correct type. - unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) } + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { collect_into_array_unchecked(&mut IntoIter::new(self).map(f)) } } /// 'Zips up' two arrays into a single array of pairs. @@ -481,15 +454,11 @@ impl [T; N] { /// ``` #[unstable(feature = "array_zip", issue = "80094")] pub fn zip(self, rhs: [U; N]) -> [(T, U); N] { - let mut dst = MaybeUninit::uninit_array::(); - for (i, (lhs, rhs)) in IntoIter::new(self).zip(IntoIter::new(rhs)).enumerate() { - dst[i].write((lhs, rhs)); - } - // FIXME: Convert to crate::mem::transmute once it works with generics. - // unsafe { crate::mem::transmute::<[MaybeUninit; N], [U; N]>(dst) } - // SAFETY: At this point we've properly initialized the whole array - // and we just need to cast it to the correct type. - unsafe { crate::mem::transmute_copy::<_, [(T, U); N]>(&dst) } + let mut iter = IntoIter::new(self).zip(IntoIter::new(rhs)); + + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { collect_into_array_unchecked(&mut iter) } } /// Returns a slice containing the entire array. Equivalent to `&s[..]`. @@ -535,16 +504,9 @@ impl [T; N] { /// ``` #[unstable(feature = "array_methods", issue = "76118")] pub fn each_ref(&self) -> [&T; N] { - // Unlike in `map`, we don't need a guard here, as dropping a reference - // is a noop. - let mut out = MaybeUninit::uninit_array::(); - for (src, dst) in self.iter().zip(&mut out) { - dst.write(src); - } - - // SAFETY: All elements of `dst` are properly initialized and - // `MaybeUninit` has the same layout as `T`, so this cast is valid. - unsafe { (&mut out as *mut _ as *mut [&T; N]).read() } + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { collect_into_array_unchecked(&mut self.iter()) } } /// Borrows each element mutably and returns an array of mutable references @@ -564,15 +526,103 @@ impl [T; N] { /// ``` #[unstable(feature = "array_methods", issue = "76118")] pub fn each_mut(&mut self) -> [&mut T; N] { - // Unlike in `map`, we don't need a guard here, as dropping a reference - // is a noop. - let mut out = MaybeUninit::uninit_array::(); - for (src, dst) in self.iter_mut().zip(&mut out) { - dst.write(src); + // SAFETY: we know for certain that this iterator will yield exactly `N` + // items. + unsafe { collect_into_array_unchecked(&mut self.iter_mut()) } + } +} + +/// Pulls `N` items from `iter` and returns them as an array. If the iterator +/// yields fewer than `N` items, this function exhibits undefined behavior. +/// +/// See [`collect_into_array`] for more information. +/// +/// +/// # Safety +/// +/// It is up to the caller to guarantee that `iter` yields at least `N` items. +/// Violating this condition causes undefined behavior. +unsafe fn collect_into_array_unchecked(iter: &mut I) -> [I::Item; N] +where + // Note: `TrustedLen` here is somewhat of an experiment. This is just an + // internal function, so feel free to remove if this bound turns out to be a + // bad idea. In that case, remember to also remove the lower bound + // `debug_assert!` below! + I: Iterator + TrustedLen, +{ + debug_assert!(N <= iter.size_hint().1.unwrap_or(usize::MAX)); + debug_assert!(N <= iter.size_hint().0); + + match collect_into_array(iter) { + Some(array) => array, + // SAFETY: covered by the function contract. + None => unsafe { crate::hint::unreachable_unchecked() }, + } +} + +/// Pulls `N` items from `iter` and returns them as an array. If the iterator +/// yields fewer than `N` items, `None` is returned and all already yielded +/// items are dropped. +/// +/// Since the iterator is passed as mutable reference and this function calls +/// `next` at most `N` times, the iterator can still be used afterwards to +/// retrieve the remaining items. +/// +/// If `iter.next()` panicks, all items already yielded by the iterator are +/// dropped. +fn collect_into_array(iter: &mut I) -> Option<[I::Item; N]> +where + I: Iterator, +{ + if N == 0 { + // SAFETY: An empty array is always inhabited and has no validity invariants. + return unsafe { Some(mem::zeroed()) }; + } + + struct Guard { + ptr: *mut T, + initialized: usize, + } + + impl Drop for Guard { + fn drop(&mut self) { + debug_assert!(self.initialized <= N); + + let initialized_part = crate::ptr::slice_from_raw_parts_mut(self.ptr, self.initialized); + + // SAFETY: this raw slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(initialized_part); + } + } + } + + let mut array = MaybeUninit::uninit_array::(); + let mut guard: Guard<_, N> = + Guard { ptr: MaybeUninit::slice_as_mut_ptr(&mut array), initialized: 0 }; + + while let Some(item) = iter.next() { + // SAFETY: `guard.initialized` starts at 0, is increased by one in the + // loop and the loop is aborted once it reaches N (which is + // `array.len()`). + unsafe { + array.get_unchecked_mut(guard.initialized).write(item); } + guard.initialized += 1; + + // Check if the whole array was initialized. + if guard.initialized == N { + mem::forget(guard); - // SAFETY: All elements of `dst` are properly initialized and - // `MaybeUninit` has the same layout as `T`, so this cast is valid. - unsafe { (&mut out as *mut _ as *mut [&mut T; N]).read() } + // SAFETY: the condition above asserts that all elements are + // initialized. + let out = unsafe { MaybeUninit::array_assume_init(array) }; + return Some(out); + } } + + // This is only reached if the iterator is exhausted before + // `guard.initialized` reaches `N`. Also note that `guard` is dropped here, + // dropping all already initialized elements. + None } From 30c5125fbe86f48a547a23917dcafab1b3f3ac7e Mon Sep 17 00:00:00 2001 From: Henry Boisdequin <65845077+henryboisdequin@users.noreply.github.com> Date: Tue, 16 Feb 2021 07:01:55 +0530 Subject: [PATCH 09/25] update formating --- compiler/rustc_middle/src/mir/mod.rs | 6 +++-- .../src/transform/check_consts/validation.rs | 22 ++++++++++++++----- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 718e81c84eddd..cd2bea86ea1a7 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -962,7 +962,8 @@ impl<'tcx> LocalDecl<'tcx> { opt_ty_info: _, opt_match_place: _, pat_span: _, - }) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm), + }) + | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm), ))) ) } @@ -979,7 +980,8 @@ impl<'tcx> LocalDecl<'tcx> { opt_ty_info: _, opt_match_place: _, pat_span: _, - }) | BindingForm::ImplicitSelf(_), + }) + | BindingForm::ImplicitSelf(_), ))) ) } diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index d8e325f1da7e9..34db0c9ab162b 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -492,7 +492,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { // Special-case reborrows to be more like a copy of a reference. match *rvalue { Rvalue::Ref(_, kind, place) => { - if let Some(place_ref) = place_as_reborrow(self.tcx, self.body, place) { + if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { let ctx = match kind { BorrowKind::Shared => { PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow) @@ -507,21 +507,31 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { PlaceContext::MutatingUse(MutatingUseContext::Borrow) } }; - self.visit_local(&place.local, ctx, location); - self.visit_projection(place.local, place_ref.projection, ctx, location); + self.visit_local(&reborrowed_place_ref.local, ctx, location); + self.visit_projection( + reborrowed_place_ref.local, + reborrowed_place_ref.projection, + ctx, + location, + ); return; } } Rvalue::AddressOf(mutbl, place) => { - if let Some(place_ref) = place_as_reborrow(self.tcx, self.body, place) { + if let Some(reborrowed_place_ref) = place_as_reborrow(self.tcx, self.body, place) { let ctx = match mutbl { Mutability::Not => { PlaceContext::NonMutatingUse(NonMutatingUseContext::AddressOf) } Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), }; - self.visit_local(&place.local, ctx, location); - self.visit_projection(place.local, place_ref.projection, ctx, location); + self.visit_local(&reborrowed_place_ref.local, ctx, location); + self.visit_projection( + reborrowed_place_ref.local, + reborrowed_place_ref.projection, + ctx, + location, + ); return; } } From 5ec4b060a793b7e04e87654b1d96f5d1fca23667 Mon Sep 17 00:00:00 2001 From: Henry Boisdequin <65845077+henryboisdequin@users.noreply.github.com> Date: Tue, 16 Feb 2021 14:20:36 +0530 Subject: [PATCH 10/25] make `visit_projection` take a `PlaceRef` --- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 7 +++---- compiler/rustc_mir/src/dataflow/impls/liveness.rs | 2 +- .../src/transform/check_consts/validation.rs | 14 ++------------ 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index fd0ff5b66e607..289629d921545 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -199,7 +199,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { } self.visit_local(&place_ref.local, context, location); - self.visit_projection(place_ref.local, place_ref.projection, context, location); + self.visit_projection(*place_ref, context, location); } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 023555d91cc92..66dd278b57840 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -998,12 +998,11 @@ macro_rules! visit_place_fns { () => { fn visit_projection( &mut self, - local: Local, - projection: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, context: PlaceContext, location: Location, ) { - self.super_projection(local, projection, context, location); + self.super_projection(place_ref.local, place_ref.projection, context, location); } fn visit_projection_elem( @@ -1033,7 +1032,7 @@ macro_rules! visit_place_fns { self.visit_local(&place.local, context, location); - self.visit_projection(place.local, &place.projection, context, location); + self.visit_projection(place.as_ref(), context, location); } fn super_projection( diff --git a/compiler/rustc_mir/src/dataflow/impls/liveness.rs b/compiler/rustc_mir/src/dataflow/impls/liveness.rs index 85aaff5ab7293..2d20f0d9547c1 100644 --- a/compiler/rustc_mir/src/dataflow/impls/liveness.rs +++ b/compiler/rustc_mir/src/dataflow/impls/liveness.rs @@ -95,7 +95,7 @@ where // We purposefully do not call `super_place` here to avoid calling `visit_local` for this // place with one of the `Projection` variants of `PlaceContext`. - self.visit_projection(local, projection, context, location); + self.visit_projection(place.as_ref(), context, location); match DefUse::for_place(context) { // Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a use. diff --git a/compiler/rustc_mir/src/transform/check_consts/validation.rs b/compiler/rustc_mir/src/transform/check_consts/validation.rs index 34db0c9ab162b..aaf2c83d1d936 100644 --- a/compiler/rustc_mir/src/transform/check_consts/validation.rs +++ b/compiler/rustc_mir/src/transform/check_consts/validation.rs @@ -508,12 +508,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { } }; self.visit_local(&reborrowed_place_ref.local, ctx, location); - self.visit_projection( - reborrowed_place_ref.local, - reborrowed_place_ref.projection, - ctx, - location, - ); + self.visit_projection(reborrowed_place_ref, ctx, location); return; } } @@ -526,12 +521,7 @@ impl Visitor<'tcx> for Validator<'mir, 'tcx> { Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), }; self.visit_local(&reborrowed_place_ref.local, ctx, location); - self.visit_projection( - reborrowed_place_ref.local, - reborrowed_place_ref.projection, - ctx, - location, - ); + self.visit_projection(reborrowed_place_ref, ctx, location); return; } } From b08bc7836be6a53e733190f3174128fe8d005737 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 16 Feb 2021 09:59:38 +0100 Subject: [PATCH 11/25] fix MIR fn-ptr pretty-printing --- compiler/rustc_middle/src/ty/print/pretty.rs | 20 ++++++++++++-------- compiler/rustc_mir/src/interpret/operand.rs | 2 +- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index a8d9995bd0b2f..f934e31a534d2 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1030,15 +1030,19 @@ pub trait PrettyPrinter<'tcx>: )?; } (Scalar::Ptr(ptr), ty::FnPtr(_)) => { - // FIXME: this can ICE when the ptr is dangling or points to a non-function. - // We should probably have a helper method to share code with the "Byte strings" + // FIXME: We should probably have a helper method to share code with the "Byte strings" // printing above (which also has to handle pointers to all sorts of things). - let instance = self.tcx().global_alloc(ptr.alloc_id).unwrap_fn(); - self = self.typed_value( - |this| this.print_value_path(instance.def_id(), instance.substs), - |this| this.print_type(ty), - " as ", - )?; + match self.tcx().get_global_alloc(ptr.alloc_id) { + Some(GlobalAlloc::Function(instance)) => { + self = self.typed_value( + |this| this.print_value_path(instance.def_id(), instance.substs), + |this| this.print_type(ty), + " as ", + )?; + } + Some(_) => p!(""), + None => p!(""), + } } // For function type zsts just printing the path is enough (Scalar::Int(int), ty::FnDef(d, s)) if int == ScalarInt::ZST => { diff --git a/compiler/rustc_mir/src/interpret/operand.rs b/compiler/rustc_mir/src/interpret/operand.rs index 88236458a213a..4b131ecb863ad 100644 --- a/compiler/rustc_mir/src/interpret/operand.rs +++ b/compiler/rustc_mir/src/interpret/operand.rs @@ -106,7 +106,7 @@ impl std::fmt::Display for ImmTy<'tcx, Tag> { } ScalarMaybeUninit::Uninit => cx.typed_value( |mut this| { - this.write_str("{uninit ")?; + this.write_str("uninit ")?; Ok(this) }, |this| this.print_type(ty), From 5fd1ebe50f5bea799efd4ab70a816a731df34319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 11 Feb 2021 12:53:42 +0300 Subject: [PATCH 12/25] Fix panic in 'remove semicolon' when types are not local It's not possible to check if removing a semicolon fixes the type error when checking match arms and one or both of the last arm's and the current arm's return types are imported "opaque" types. In these cases we don't generate a "consider removing semicolon" suggestions. Fixes #81839 --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 9e6c11d9dddbb..67068322733ed 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1078,8 +1078,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "both opaque, likely future {:?} {:?} {:?} {:?}", last_def_id, last_bounds, exp_def_id, exp_bounds ); - let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_def_id.expect_local()); - let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_def_id.expect_local()); + + let (last_local_id, exp_local_id) = + match (last_def_id.as_local(), exp_def_id.as_local()) { + (Some(last_hir_id), Some(exp_hir_id)) => (last_hir_id, exp_hir_id), + (_, _) => return None, + }; + + let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id); + let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id); + match ( &self.tcx.hir().expect_item(last_hir_id).kind, &self.tcx.hir().expect_item(exp_hir_id).kind, From ad47fb1ca9d1eb66752611ae9f4d2c183daa9145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 11 Feb 2021 13:37:00 +0300 Subject: [PATCH 13/25] Check opaque type def ids before bailing out --- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 67068322733ed..37e9e6b4d3d0d 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1073,6 +1073,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let last_expr_ty = self.node_ty(last_expr.hir_id); let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { + (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _)) + if last_def_id == exp_def_id => + { + StatementAsExpression::CorrectType + } (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => { debug!( "both opaque, likely future {:?} {:?} {:?} {:?}", From 15fdccc6ae636b0f5663e2e75e0a115d60b8633c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 11 Feb 2021 20:17:57 +0300 Subject: [PATCH 14/25] Update 'match-prev-arm-needing-semi' --- .../ui/suggestions/match-prev-arm-needing-semi.stderr | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index e9803a78f94b3..fae0c498b440a 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -24,13 +24,10 @@ help: consider `await`ing on the `Future` | LL | false => async_dummy().await, | ^^^^^^ -help: consider removing this semicolon and boxing the expressions - | -LL | Box::new(async_dummy()) -LL | -LL | } -LL | false => Box::new(async_dummy()), +help: consider removing this semicolon | +LL | async_dummy() + | -- error[E0308]: `match` arms have incompatible types --> $DIR/match-prev-arm-needing-semi.rs:39:18 From 9ef67e09a4c2fdfd528ac174e3aec2fe0e97f347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= Date: Thu, 18 Feb 2021 16:47:01 +0300 Subject: [PATCH 15/25] Add regression test --- .../ui/suggestions/auxiliary/issue-81839.rs | 9 +++++++ src/test/ui/suggestions/issue-81839.rs | 17 ++++++++++++ src/test/ui/suggestions/issue-81839.stderr | 27 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 src/test/ui/suggestions/auxiliary/issue-81839.rs create mode 100644 src/test/ui/suggestions/issue-81839.rs create mode 100644 src/test/ui/suggestions/issue-81839.stderr diff --git a/src/test/ui/suggestions/auxiliary/issue-81839.rs b/src/test/ui/suggestions/auxiliary/issue-81839.rs new file mode 100644 index 0000000000000..5683c45adf26d --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-81839.rs @@ -0,0 +1,9 @@ +// edition:2018 + +pub struct Test {} + +impl Test { + pub async fn answer_str(&self, _s: &str) -> Test { + Test {} + } +} diff --git a/src/test/ui/suggestions/issue-81839.rs b/src/test/ui/suggestions/issue-81839.rs new file mode 100644 index 0000000000000..0b9b7aefe735d --- /dev/null +++ b/src/test/ui/suggestions/issue-81839.rs @@ -0,0 +1,17 @@ +// aux-build:issue-81839.rs +// edition:2018 + +extern crate issue_81839; + +async fn test(ans: &str, num: i32, cx: &issue_81839::Test) -> u32 { + match num { + 1 => { + cx.answer_str("hi"); + } + _ => cx.answer_str("hi"), //~ `match` arms have incompatible types + } + + 1 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr new file mode 100644 index 0000000000000..1a289d39e4467 --- /dev/null +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -0,0 +1,27 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-81839.rs:11:14 + | +LL | / match num { +LL | | 1 => { +LL | | cx.answer_str("hi"); + | | -------------------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` +LL | | } +LL | | _ => cx.answer_str("hi"), + | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type +LL | | } + | |_____- `match` arms have incompatible types + | + ::: $DIR/auxiliary/issue-81839.rs:6:49 + | +LL | pub async fn answer_str(&self, _s: &str) -> Test { + | ---- the `Output` of this `async fn`'s found opaque type + | + = note: expected type `()` + found opaque type `impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From 343b67387772dbd068d06a76267288579d3eaed0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 19 Feb 2021 00:00:00 +0000 Subject: [PATCH 16/25] Consider auto derefs before warning about write only fields Changes from 81473 extended the dead code lint with an ability to detect fields that are written to but never read from. The implementation skips over fields on the left hand side of an assignment, without marking them as live. A field access might involve an automatic dereference and de-facto read the field. Conservatively mark expressions with deref adjustments as live to avoid generating false positive warnings. --- compiler/rustc_passes/src/dead.rs | 28 ++++++----- .../ui/lint/dead-code/write-only-field.rs | 49 +++++++++++++++++++ .../ui/lint/dead-code/write-only-field.stderr | 20 +++++++- 3 files changed, 85 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d51b501f7ae3d..62a95aa57c29f 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -37,15 +37,6 @@ fn should_explore(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { ) } -fn base_expr<'a>(mut expr: &'a hir::Expr<'a>) -> &'a hir::Expr<'a> { - loop { - match expr.kind { - hir::ExprKind::Field(base, ..) => expr = base, - _ => return expr, - } - } -} - struct MarkSymbolVisitor<'tcx> { worklist: Vec, tcx: TyCtxt<'tcx>, @@ -143,6 +134,22 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { } } + fn handle_assign(&mut self, expr: &'tcx hir::Expr<'tcx>) { + if self + .typeck_results() + .expr_adjustments(expr) + .iter() + .any(|adj| matches!(adj.kind, ty::adjustment::Adjust::Deref(_))) + { + self.visit_expr(expr); + } else if let hir::ExprKind::Field(base, ..) = expr.kind { + // Ignore write to field + self.handle_assign(base); + } else { + self.visit_expr(expr); + } + } + fn handle_field_pattern_match( &mut self, lhs: &hir::Pat<'_>, @@ -272,8 +279,7 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> { self.lookup_and_handle_method(expr.hir_id); } hir::ExprKind::Assign(ref left, ref right, ..) => { - // Ignore write to field - self.visit_expr(base_expr(left)); + self.handle_assign(left); self.visit_expr(right); return; } diff --git a/src/test/ui/lint/dead-code/write-only-field.rs b/src/test/ui/lint/dead-code/write-only-field.rs index 78cfcfda8f971..7b3f1e9f5b6cb 100644 --- a/src/test/ui/lint/dead-code/write-only-field.rs +++ b/src/test/ui/lint/dead-code/write-only-field.rs @@ -17,4 +17,53 @@ fn field_write(s: &mut S) { fn main() { let mut s = S { f: 0, sub: Sub { f: 0 } }; field_write(&mut s); + + auto_deref(); + nested_boxes(); +} + +fn auto_deref() { + struct E { + x: bool, + y: bool, //~ ERROR: field is never read + } + + struct P<'a> { + e: &'a mut E + } + + impl P<'_> { + fn f(&mut self) { + self.e.x = true; + self.e.y = true; + } + } + + let mut e = E { x: false, y: false }; + let mut p = P { e: &mut e }; + p.f(); + assert!(e.x); +} + +fn nested_boxes() { + struct A { + b: Box, + } + + struct B { + c: Box, + } + + struct C { + u: u32, //~ ERROR: field is never read + v: u32, //~ ERROR: field is never read + } + + let mut a = A { + b: Box::new(B { + c: Box::new(C { u: 0, v: 0 }), + }), + }; + a.b.c.v = 10; + a.b.c = Box::new(C { u: 1, v: 2 }); } diff --git a/src/test/ui/lint/dead-code/write-only-field.stderr b/src/test/ui/lint/dead-code/write-only-field.stderr index 70d2149665b20..a191d22c8b94c 100644 --- a/src/test/ui/lint/dead-code/write-only-field.stderr +++ b/src/test/ui/lint/dead-code/write-only-field.stderr @@ -22,5 +22,23 @@ error: field is never read: `f` LL | f: i32, | ^^^^^^ -error: aborting due to 3 previous errors +error: field is never read: `y` + --> $DIR/write-only-field.rs:28:9 + | +LL | y: bool, + | ^^^^^^^ + +error: field is never read: `u` + --> $DIR/write-only-field.rs:58:9 + | +LL | u: u32, + | ^^^^^^ + +error: field is never read: `v` + --> $DIR/write-only-field.rs:59:9 + | +LL | v: u32, + | ^^^^^^ + +error: aborting due to 6 previous errors From 48b5c093d62f670dc2ca4dd3fb65052a4bb20766 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 16 Feb 2021 00:46:14 +0000 Subject: [PATCH 17/25] add s390x-unknown-linux-musl target --- compiler/rustc_target/src/spec/mod.rs | 1 + .../src/spec/s390x_unknown_linux_musl.rs | 24 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 5b14795f5457c..f7b49ac52b0af 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -641,6 +641,7 @@ supported_targets! { ("powerpc64le-unknown-linux-gnu", powerpc64le_unknown_linux_gnu), ("powerpc64le-unknown-linux-musl", powerpc64le_unknown_linux_musl), ("s390x-unknown-linux-gnu", s390x_unknown_linux_gnu), + ("s390x-unknown-linux-musl", s390x_unknown_linux_musl), ("sparc-unknown-linux-gnu", sparc_unknown_linux_gnu), ("sparc64-unknown-linux-gnu", sparc64_unknown_linux_gnu), ("arm-unknown-linux-gnueabi", arm_unknown_linux_gnueabi), diff --git a/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs new file mode 100644 index 0000000000000..4f811ce98c181 --- /dev/null +++ b/compiler/rustc_target/src/spec/s390x_unknown_linux_musl.rs @@ -0,0 +1,24 @@ +use crate::abi::Endian; +use crate::spec::Target; + +pub fn target() -> Target { + let mut base = super::linux_musl_base::opts(); + base.endian = Endian::Big; + // z10 is the oldest CPU supported by LLVM + base.cpu = "z10".to_string(); + // FIXME: The data_layout string below and the ABI implementation in + // cabi_s390x.rs are for now hard-coded to assume the no-vector ABI. + // Pass the -vector feature string to LLVM to respect this assumption. + base.features = "-vector".to_string(); + base.max_atomic_width = Some(64); + base.min_global_align = Some(16); + base.static_position_independent_executables = true; + + Target { + llvm_target: "s390x-unknown-linux-musl".to_string(), + pointer_width: 64, + data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64".to_string(), + arch: "s390x".to_string(), + options: base, + } +} From 597118baa86f0e799065f2043a8a467238660f33 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 16 Feb 2021 01:34:25 +0000 Subject: [PATCH 18/25] add s390x-unknown-linux-musl target to platform support --- src/doc/rustc/src/platform-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 8198dbaa5278c..9e927067bf016 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -207,6 +207,7 @@ target | std | host | notes `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) +`s390x-unknown-linux-musl` | ✓ | ✓ | S390x Linux (kernel 2.6.32, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux `sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64 `sparc64-unknown-openbsd` | ? | | From 62ee3ec7ba17fe705ba21f25c1a28ce751efc1b7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 19 Feb 2021 01:12:53 +0000 Subject: [PATCH 19/25] remove checkboxes from s390x-unknown-linux-musl triplet --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 9e927067bf016..6335709dc48b9 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -207,7 +207,7 @@ target | std | host | notes `riscv64gc-unknown-linux-musl` | | | RISC-V Linux (kernel 4.20, musl 1.2.0) `riscv32gc-unknown-linux-gnu` | | | RISC-V Linux (kernel 5.4, glibc 2.33) `riscv32gc-unknown-linux-musl` | | | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches) -`s390x-unknown-linux-musl` | ✓ | ✓ | S390x Linux (kernel 2.6.32, MUSL) +`s390x-unknown-linux-musl` | | | S390x Linux (kernel 2.6.32, MUSL) `sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux `sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64 `sparc64-unknown-openbsd` | ? | | From 1abcdfe4493b781cea654840b497674907038faf Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Feb 2021 07:31:01 -0800 Subject: [PATCH 20/25] x.py fmt --- library/std/src/sys/wasi/fs.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs index 6050620729f83..83debdfc86043 100644 --- a/library/std/src/sys/wasi/fs.rs +++ b/library/std/src/sys/wasi/fs.rs @@ -558,12 +558,7 @@ pub fn link(original: &Path, link: &Path) -> io::Result<()> { let (original, original_file) = open_parent(original)?; let (link, link_file) = open_parent(link)?; // Pass 0 as the flags argument, meaning don't follow symlinks. - original.link( - 0, - osstr2str(original_file.as_ref())?, - &link, - osstr2str(link_file.as_ref())?, - ) + original.link(0, osstr2str(original_file.as_ref())?, &link, osstr2str(link_file.as_ref())?) } pub fn stat(p: &Path) -> io::Result { From 0fddc2f780b7d075797364386a77b5f2f3bf909b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 21 Oct 2020 00:46:29 +0300 Subject: [PATCH 21/25] Support `pub` on `macro_rules` --- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_feature/src/active.rs | 3 ++ compiler/rustc_parse/src/parser/item.rs | 10 +--- .../rustc_resolve/src/build_reduced_graph.rs | 9 +++- compiler/rustc_span/src/symbol.rs | 1 + src/test/ui/did_you_mean/pub-macro-rules.rs | 16 ------- .../ui/did_you_mean/pub-macro-rules.stderr | 8 ---- .../feature-gate-pub_macro_rules.rs | 10 ++++ .../feature-gate-pub_macro_rules.stderr | 39 +++++++++++++++ .../macro-export-on-modularized-macros.rs | 11 +++++ .../macro-export-on-modularized-macros.stderr | 14 ++++++ src/test/ui/macros/pub-macro-rules-fail.rs | 28 +++++++++++ .../ui/macros/pub-macro-rules-fail.stderr | 48 +++++++++++++++++++ src/test/ui/macros/pub-macro-rules.rs | 20 ++++++++ 14 files changed, 183 insertions(+), 35 deletions(-) delete mode 100644 src/test/ui/did_you_mean/pub-macro-rules.rs delete mode 100644 src/test/ui/did_you_mean/pub-macro-rules.stderr create mode 100644 src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs create mode 100644 src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr create mode 100644 src/test/ui/macros/macro-export-on-modularized-macros.rs create mode 100644 src/test/ui/macros/macro-export-on-modularized-macros.stderr create mode 100644 src/test/ui/macros/pub-macro-rules-fail.rs create mode 100644 src/test/ui/macros/pub-macro-rules-fail.stderr create mode 100644 src/test/ui/macros/pub-macro-rules.rs diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 6514de2b81315..474ec2b589b71 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -665,6 +665,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { // involved, so we only emit errors where there are no other parsing errors. gate_all!(destructuring_assignment, "destructuring assignments are unstable"); } + gate_all!(pub_macro_rules, "`pub` on `macro_rules` items is unstable"); // All uses of `gate_all!` below this point were added in #65742, // and subsequently disabled (with the non-early gating readded). diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 2d0009c225c59..56f5c3b79bef9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -638,6 +638,9 @@ declare_features! ( /// Allows macro attributes to observe output of `#[derive]`. (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None), + /// Allows `pub` on `macro_rules` items. + (active, pub_macro_rules, "1.49.0", Some(78855), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index cdea82f50ede4..45f6dbca9f048 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1488,15 +1488,7 @@ impl<'a> Parser<'a> { let vstr = pprust::vis_to_string(vis); let vstr = vstr.trim_end(); if macro_rules { - let msg = format!("can't qualify macro_rules invocation with `{}`", vstr); - self.struct_span_err(vis.span, &msg) - .span_suggestion( - vis.span, - "try exporting the macro", - "#[macro_export]".to_owned(), - Applicability::MaybeIncorrect, // speculative - ) - .emit(); + self.sess.gated_spans.gate(sym::pub_macro_rules, vis.span); } else { self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") .span_suggestion( diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 79ed0b5308dab..65e5b0dddea30 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -1230,13 +1230,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }; let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id()); + let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export); self.r.macro_map.insert(def_id.to_def_id(), ext); self.r.local_macro_def_scopes.insert(def_id, parent_scope.module); - if macro_rules { + if macro_rules && matches!(item.vis.kind, ast::VisibilityKind::Inherited) { let ident = ident.normalize_to_macros_2_0(); self.r.macro_names.insert(ident); - let is_macro_export = self.r.session.contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { ty::Visibility::Public } else { @@ -1261,6 +1261,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }), )) } else { + if is_macro_export { + let what = if macro_rules { "`macro_rules` with `pub`" } else { "`macro` items" }; + let msg = format!("`#[macro_export]` cannot be used on {what}"); + self.r.session.span_err(item.span, &msg); + } let module = parent_scope.module; let vis = match item.kind { // Visibilities must not be resolved non-speculatively twice diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 653d70b6cf244..d4a0f968eee1e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -874,6 +874,7 @@ symbols! { ptr_guaranteed_eq, ptr_guaranteed_ne, ptr_offset_from, + pub_macro_rules, pub_restricted, pure, pushpop_unsafe, diff --git a/src/test/ui/did_you_mean/pub-macro-rules.rs b/src/test/ui/did_you_mean/pub-macro-rules.rs deleted file mode 100644 index c5393703f7091..0000000000000 --- a/src/test/ui/did_you_mean/pub-macro-rules.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[macro_use] mod bleh { - pub macro_rules! foo { //~ ERROR can't qualify macro_rules invocation - ($n:ident) => ( - fn $n () -> i32 { - 1 - } - ) - } - -} - -foo!(meh); - -fn main() { - println!("{}", meh()); -} diff --git a/src/test/ui/did_you_mean/pub-macro-rules.stderr b/src/test/ui/did_you_mean/pub-macro-rules.stderr deleted file mode 100644 index 0bde5783b8cc6..0000000000000 --- a/src/test/ui/did_you_mean/pub-macro-rules.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: can't qualify macro_rules invocation with `pub` - --> $DIR/pub-macro-rules.rs:2:5 - | -LL | pub macro_rules! foo { - | ^^^ help: try exporting the macro: `#[macro_export]` - -error: aborting due to previous error - diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs new file mode 100644 index 0000000000000..5504ec317ae59 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.rs @@ -0,0 +1,10 @@ +pub macro_rules! m1 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +#[cfg(FALSE)] +pub macro_rules! m2 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +pub(crate) macro_rules! m3 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +pub(in self) macro_rules! m4 { () => {} } //~ ERROR `pub` on `macro_rules` items is unstable + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr new file mode 100644 index 0000000000000..bfaec398d9a97 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-pub_macro_rules.stderr @@ -0,0 +1,39 @@ +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:1:1 + | +LL | pub macro_rules! m1 { () => {} } + | ^^^ + | + = note: see issue #78855 for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:4:1 + | +LL | pub macro_rules! m2 { () => {} } + | ^^^ + | + = note: see issue #78855 for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:6:1 + | +LL | pub(crate) macro_rules! m3 { () => {} } + | ^^^^^^^^^^ + | + = note: see issue #78855 for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error[E0658]: `pub` on `macro_rules` items is unstable + --> $DIR/feature-gate-pub_macro_rules.rs:8:1 + | +LL | pub(in self) macro_rules! m4 { () => {} } + | ^^^^^^^^^^^^ + | + = note: see issue #78855 for more information + = help: add `#![feature(pub_macro_rules)]` to the crate attributes to enable + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.rs b/src/test/ui/macros/macro-export-on-modularized-macros.rs new file mode 100644 index 0000000000000..467c6ba7b78e4 --- /dev/null +++ b/src/test/ui/macros/macro-export-on-modularized-macros.rs @@ -0,0 +1,11 @@ +#![feature(decl_macro)] +#![feature(pub_macro_rules)] + +#[macro_export] +macro m1() {} //~ ERROR `#[macro_export]` cannot be used on `macro` items + +#[macro_export] +pub macro_rules! m2 { () => {} } +//~^ ERROR `#[macro_export]` cannot be used on `macro_rules` with `pub` + +fn main() {} diff --git a/src/test/ui/macros/macro-export-on-modularized-macros.stderr b/src/test/ui/macros/macro-export-on-modularized-macros.stderr new file mode 100644 index 0000000000000..8bb031e12cba2 --- /dev/null +++ b/src/test/ui/macros/macro-export-on-modularized-macros.stderr @@ -0,0 +1,14 @@ +error: `#[macro_export]` cannot be used on `macro` items + --> $DIR/macro-export-on-modularized-macros.rs:5:1 + | +LL | macro m1() {} + | ^^^^^^^^^^^^^ + +error: `#[macro_export]` cannot be used on `macro_rules` with `pub` + --> $DIR/macro-export-on-modularized-macros.rs:8:1 + | +LL | pub macro_rules! m2 { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/macros/pub-macro-rules-fail.rs b/src/test/ui/macros/pub-macro-rules-fail.rs new file mode 100644 index 0000000000000..bdb4c73f18b18 --- /dev/null +++ b/src/test/ui/macros/pub-macro-rules-fail.rs @@ -0,0 +1,28 @@ +#![feature(pub_macro_rules)] + +#[macro_use] +mod m { + pub macro_rules! mac { () => {} } + + // `pub` `macro_rules` cannot be redefined in the same module. + pub macro_rules! mac { () => {} } //~ ERROR the name `mac` is defined multiple times + + pub(self) macro_rules! private_mac { () => {} } +} + +const _: () = { + pub macro_rules! block_mac { () => {} } +}; + +mod n { + // Scope of `pub` `macro_rules` is not extended by `#[macro_use]`. + mac!(); //~ ERROR cannot find macro `mac` in this scope + + // `pub` `macro_rules` doesn't put the macro into the root module, unlike `#[macro_export]`. + crate::mac!(); //~ ERROR failed to resolve: maybe a missing crate `mac` + crate::block_mac!(); //~ ERROR failed to resolve: maybe a missing crate `block_mac` + + crate::m::private_mac!(); //~ ERROR macro `private_mac` is private +} + +fn main() {} diff --git a/src/test/ui/macros/pub-macro-rules-fail.stderr b/src/test/ui/macros/pub-macro-rules-fail.stderr new file mode 100644 index 0000000000000..588d79dd76a4b --- /dev/null +++ b/src/test/ui/macros/pub-macro-rules-fail.stderr @@ -0,0 +1,48 @@ +error[E0428]: the name `mac` is defined multiple times + --> $DIR/pub-macro-rules-fail.rs:8:5 + | +LL | pub macro_rules! mac { () => {} } + | -------------------- previous definition of the macro `mac` here +... +LL | pub macro_rules! mac { () => {} } + | ^^^^^^^^^^^^^^^^^^^^ `mac` redefined here + | + = note: `mac` must be defined only once in the macro namespace of this module + +error[E0433]: failed to resolve: maybe a missing crate `mac`? + --> $DIR/pub-macro-rules-fail.rs:22:12 + | +LL | crate::mac!(); + | ^^^ maybe a missing crate `mac`? + +error[E0433]: failed to resolve: maybe a missing crate `block_mac`? + --> $DIR/pub-macro-rules-fail.rs:23:12 + | +LL | crate::block_mac!(); + | ^^^^^^^^^ maybe a missing crate `block_mac`? + +error: cannot find macro `mac` in this scope + --> $DIR/pub-macro-rules-fail.rs:19:5 + | +LL | mac!(); + | ^^^ + | + = note: consider importing this macro: + m::mac + +error[E0603]: macro `private_mac` is private + --> $DIR/pub-macro-rules-fail.rs:25:15 + | +LL | crate::m::private_mac!(); + | ^^^^^^^^^^^ private macro + | +note: the macro `private_mac` is defined here + --> $DIR/pub-macro-rules-fail.rs:10:5 + | +LL | pub(self) macro_rules! private_mac { () => {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0428, E0433, E0603. +For more information about an error, try `rustc --explain E0428`. diff --git a/src/test/ui/macros/pub-macro-rules.rs b/src/test/ui/macros/pub-macro-rules.rs new file mode 100644 index 0000000000000..cd4a845f7c07d --- /dev/null +++ b/src/test/ui/macros/pub-macro-rules.rs @@ -0,0 +1,20 @@ +// check-pass + +#![feature(pub_macro_rules)] + +mod m { + // `pub` `macro_rules` can be used earlier in item order than they are defined. + foo!(); + + pub macro_rules! foo { () => {} } + + // `pub(...)` works too. + pub(super) macro_rules! bar { () => {} } +} + +// `pub` `macro_rules` are available by module path. +m::foo!(); + +m::bar!(); + +fn main() {} From b3000ec0cdb35b305bfe954db4b14ce32cbc255b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 19 Feb 2021 12:47:53 -0300 Subject: [PATCH 22/25] Update pub_macro_rules since version --- compiler/rustc_feature/src/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 56f5c3b79bef9..3f484ab568652 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -639,7 +639,7 @@ declare_features! ( (active, macro_attributes_in_derive_output, "1.51.0", Some(81119), None), /// Allows `pub` on `macro_rules` items. - (active, pub_macro_rules, "1.49.0", Some(78855), None), + (active, pub_macro_rules, "1.52.0", Some(78855), None), // ------------------------------------------------------------------------- // feature-group-end: actual feature gates From 1839748772a535cd694851092aa4ccab9374492c Mon Sep 17 00:00:00 2001 From: Alexander Ronald Altman Date: Fri, 1 Jan 2021 11:40:00 -0800 Subject: [PATCH 23/25] `impl PartialEq for char`; symmetry for #78636 Also fixes the "since" version of the original. --- library/proc_macro/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index a89e7b53e43c4..5f1f7d8cac418 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -842,13 +842,20 @@ impl fmt::Debug for Punct { } } -#[stable(feature = "proc_macro_punct_eq", since = "1.49.0")] +#[stable(feature = "proc_macro_punct_eq", since = "1.50.0")] impl PartialEq for Punct { fn eq(&self, rhs: &char) -> bool { self.as_char() == *rhs } } +#[stable(feature = "proc_macro_punct_eq_flipped", since = "1.52.0")] +impl PartialEq for char { + fn eq(&self, rhs: &Punct) -> bool { + *self == rhs.as_char() + } +} + /// An identifier (`ident`). #[derive(Clone)] #[stable(feature = "proc_macro_lib2", since = "1.29.0")] From e90674574d21f8245716c0644b0c8aa2e1702b54 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 20 Feb 2021 11:34:35 +0100 Subject: [PATCH 24/25] fn ptr pretty printing: fall back to raw ptr printing --- compiler/rustc_middle/src/ty/print/pretty.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f934e31a534d2..cc41fd855e83b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1018,7 +1018,7 @@ pub trait PrettyPrinter<'tcx>: p!(write("{:?}", char::try_from(int).unwrap())) } // Raw pointers - (Scalar::Int(int), ty::RawPtr(_)) => { + (Scalar::Int(int), ty::RawPtr(_) | ty::FnPtr(_)) => { let data = int.assert_bits(self.tcx().data_layout.pointer_size); self = self.typed_value( |mut this| { @@ -1040,8 +1040,7 @@ pub trait PrettyPrinter<'tcx>: " as ", )?; } - Some(_) => p!(""), - None => p!(""), + _ => self = self.pretty_print_const_pointer(ptr, ty, print_ty)?, } } // For function type zsts just printing the path is enough From a9c61888896da6feea45875813b894e7fa4067f6 Mon Sep 17 00:00:00 2001 From: Henry Boisdequin <65845077+henryboisdequin@users.noreply.github.com> Date: Sat, 20 Feb 2021 16:46:05 +0530 Subject: [PATCH 25/25] make `super_projection` take a `PlaceRef` --- compiler/rustc_middle/src/mir/visit.rs | 10 +++++----- compiler/rustc_mir/src/transform/simplify.rs | 3 +-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 66dd278b57840..9530efaedbce4 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1002,7 +1002,7 @@ macro_rules! visit_place_fns { context: PlaceContext, location: Location, ) { - self.super_projection(place_ref.local, place_ref.projection, context, location); + self.super_projection(place_ref, context, location); } fn visit_projection_elem( @@ -1037,15 +1037,15 @@ macro_rules! visit_place_fns { fn super_projection( &mut self, - local: Local, - projection: &[PlaceElem<'tcx>], + place_ref: PlaceRef<'tcx>, context: PlaceContext, location: Location, ) { - let mut cursor = projection; + // FIXME: Use PlaceRef::iter_projections, once that exists. + let mut cursor = place_ref.projection; while let &[ref proj_base @ .., elem] = cursor { cursor = proj_base; - self.visit_projection_elem(local, cursor, elem, context, location); + self.visit_projection_elem(place_ref.local, cursor, elem, context, location); } } diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index 289231e52cb41..d9abfec85c9e7 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -414,8 +414,7 @@ impl UsedLocals { } else { // A definition. Although, it still might use other locals for indexing. self.super_projection( - place.local, - &place.projection, + place.as_ref(), PlaceContext::MutatingUse(MutatingUseContext::Projection), location, );