From c675af82b4a5422620d2d8f8db8862320e448ecd Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Sun, 14 Feb 2021 14:42:47 +0100 Subject: [PATCH 01/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 d6b9d9a1d6a73cd99b0a1f959d3afa77a44bb8bd Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 17 Feb 2021 19:51:27 +0000 Subject: [PATCH 02/25] std::src::os::raw: Refactor, introducing macro type_alias! This file contained a lot of repetitive code. This was about to get considerably worse, with introduction of a slew of new aliases. No functional change. I've eyeballed the docs and they don't seem to have changed either. Signed-off-by: Ian Jackson --- library/std/src/os/raw/mod.rs | 81 ++++++++++++----------------------- 1 file changed, 27 insertions(+), 54 deletions(-) diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 16272aa05712f..1a2158555e6a9 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -11,7 +11,16 @@ #[cfg(test)] mod tests; -#[doc(include = "char.md")] +macro_rules! type_alias { + { $Docfile:tt, $Alias:ident = $Real:ty; $( $Cfg:tt )* } => { + #[doc(include = $Docfile)] + $( $Cfg )* + #[stable(feature = "raw_os", since = "1.1.0")] + pub type $Alias = $Real; + } +} + +type_alias! { "char.md", c_char = u8; #[cfg(any( all( target_os = "linux", @@ -52,10 +61,8 @@ mod tests; ) ), all(target_os = "fuchsia", target_arch = "aarch64") -))] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_char = u8; -#[doc(include = "char.md")] +))]} +type_alias! { "char.md", c_char = i8; #[cfg(not(any( all( target_os = "linux", @@ -96,55 +103,21 @@ pub type c_char = u8; ) ), all(target_os = "fuchsia", target_arch = "aarch64") -)))] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_char = i8; -#[doc(include = "schar.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_schar = i8; -#[doc(include = "uchar.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_uchar = u8; -#[doc(include = "short.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_short = i16; -#[doc(include = "ushort.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_ushort = u16; -#[doc(include = "int.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_int = i32; -#[doc(include = "uint.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_uint = u32; -#[doc(include = "long.md")] -#[cfg(any(target_pointer_width = "32", windows))] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_long = i32; -#[doc(include = "ulong.md")] -#[cfg(any(target_pointer_width = "32", windows))] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_ulong = u32; -#[doc(include = "long.md")] -#[cfg(all(target_pointer_width = "64", not(windows)))] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_long = i64; -#[doc(include = "ulong.md")] -#[cfg(all(target_pointer_width = "64", not(windows)))] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_ulong = u64; -#[doc(include = "longlong.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_longlong = i64; -#[doc(include = "ulonglong.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_ulonglong = u64; -#[doc(include = "float.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_float = f32; -#[doc(include = "double.md")] -#[stable(feature = "raw_os", since = "1.1.0")] -pub type c_double = f64; +)))]} +type_alias! { "schar.md", c_schar = i8; } +type_alias! { "uchar.md", c_uchar = u8; } +type_alias! { "short.md", c_short = i16; } +type_alias! { "ushort.md", c_ushort = u16; } +type_alias! { "int.md", c_int = i32; } +type_alias! { "uint.md", c_uint = u32; } +type_alias! { "long.md", c_long = i32; #[cfg(any(target_pointer_width = "32", windows))] } +type_alias! { "ulong.md", c_ulong = u32; #[cfg(any(target_pointer_width = "32", windows))] } +type_alias! { "long.md", c_long = i64; #[cfg(all(target_pointer_width = "64", not(windows)))] } +type_alias! { "ulong.md", c_ulong = u64; #[cfg(all(target_pointer_width = "64", not(windows)))] } +type_alias! { "longlong.md", c_longlong = i64; } +type_alias! { "ulonglong.md", c_ulonglong = u64; } +type_alias! { "float.md", c_float = f32; } +type_alias! { "double.md", c_double = f64; } #[stable(feature = "raw_os", since = "1.1.0")] #[doc(no_inline)] From e78b5012f5a1bd690490c03c8615f1918939f102 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 17 Feb 2021 20:40:23 +0000 Subject: [PATCH 03/25] Provide NonZero_c_* integers I'm pretty sure I am going want this for #73125 and it seems like an omission that would be in any case good to remedy. It's a shame we don't have competent token pasting and case mangling for use in macro_rules!. Signed-off-by: Ian Jackson --- library/std/src/lib.rs | 1 + library/std/src/os/raw/mod.rs | 65 +++++++++++++++++++++++++---------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bc9b47029417d..bef13e71c55d8 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -263,6 +263,7 @@ #![feature(exact_size_is_empty)] #![feature(exhaustive_patterns)] #![feature(extend_one)] +#![feature(extended_key_value_attributes)] #![feature(external_doc)] #![feature(fn_traits)] #![feature(format_args_nl)] diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 1a2158555e6a9..3dc97a0c458af 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -11,8 +11,13 @@ #[cfg(test)] mod tests; -macro_rules! type_alias { - { $Docfile:tt, $Alias:ident = $Real:ty; $( $Cfg:tt )* } => { +use core::num::*; + +macro_rules! type_alias_no_nz { + { + $Docfile:tt, $Alias:ident = $Real:ty; + $( $Cfg:tt )* + } => { #[doc(include = $Docfile)] $( $Cfg )* #[stable(feature = "raw_os", since = "1.1.0")] @@ -20,7 +25,27 @@ macro_rules! type_alias { } } -type_alias! { "char.md", c_char = u8; +// To verify that the NonZero types in this file's macro invocations correspond +// +// perl -n < library/std/src/os/raw/mod.rs -e 'next unless m/type_alias\!/; die "$_ ?" unless m/, (c_\w+) = (\w+), NonZero_(\w+) = NonZero(\w+)/; die "$_ ?" unless $3 eq $1 and $4 eq ucfirst $2' +// +// NB this does not check that the main c_* types are right. + +macro_rules! type_alias { + { + $Docfile:tt, $Alias:ident = $Real:ty, $NZAlias:ident = $NZReal:ty; + $( $Cfg:tt )* + } => { + type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* } + + #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")] + #[unstable(feature = "raw_os_nonzero", issue = "none")] + $( $Cfg )* + pub type $NZAlias = $NZReal; + } +} + +type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8; #[cfg(any( all( target_os = "linux", @@ -62,7 +87,7 @@ type_alias! { "char.md", c_char = u8; ), all(target_os = "fuchsia", target_arch = "aarch64") ))]} -type_alias! { "char.md", c_char = i8; +type_alias! { "char.md", c_char = i8, NonZero_c_char = NonZeroI8; #[cfg(not(any( all( target_os = "linux", @@ -104,20 +129,24 @@ type_alias! { "char.md", c_char = i8; ), all(target_os = "fuchsia", target_arch = "aarch64") )))]} -type_alias! { "schar.md", c_schar = i8; } -type_alias! { "uchar.md", c_uchar = u8; } -type_alias! { "short.md", c_short = i16; } -type_alias! { "ushort.md", c_ushort = u16; } -type_alias! { "int.md", c_int = i32; } -type_alias! { "uint.md", c_uint = u32; } -type_alias! { "long.md", c_long = i32; #[cfg(any(target_pointer_width = "32", windows))] } -type_alias! { "ulong.md", c_ulong = u32; #[cfg(any(target_pointer_width = "32", windows))] } -type_alias! { "long.md", c_long = i64; #[cfg(all(target_pointer_width = "64", not(windows)))] } -type_alias! { "ulong.md", c_ulong = u64; #[cfg(all(target_pointer_width = "64", not(windows)))] } -type_alias! { "longlong.md", c_longlong = i64; } -type_alias! { "ulonglong.md", c_ulonglong = u64; } -type_alias! { "float.md", c_float = f32; } -type_alias! { "double.md", c_double = f64; } +type_alias! { "schar.md", c_schar = i8, NonZero_c_schar = NonZeroI8; } +type_alias! { "uchar.md", c_uchar = u8, NonZero_c_uchar = NonZeroU8; } +type_alias! { "short.md", c_short = i16, NonZero_c_short = NonZeroI16; } +type_alias! { "ushort.md", c_ushort = u16, NonZero_c_ushort = NonZeroU16; } +type_alias! { "int.md", c_int = i32, NonZero_c_int = NonZeroI32; } +type_alias! { "uint.md", c_uint = u32, NonZero_c_uint = NonZeroU32; } +type_alias! { "long.md", c_long = i32, NonZero_c_long = NonZeroI32; +#[cfg(any(target_pointer_width = "32", windows))] } +type_alias! { "ulong.md", c_ulong = u32, NonZero_c_ulong = NonZeroU32; +#[cfg(any(target_pointer_width = "32", windows))] } +type_alias! { "long.md", c_long = i64, NonZero_c_long = NonZeroI64; +#[cfg(all(target_pointer_width = "64", not(windows)))] } +type_alias! { "ulong.md", c_ulong = u64, NonZero_c_ulong = NonZeroU64; +#[cfg(all(target_pointer_width = "64", not(windows)))] } +type_alias! { "longlong.md", c_longlong = i64, NonZero_c_longlong = NonZeroI64; } +type_alias! { "ulonglong.md", c_ulonglong = u64, NonZero_c_ulonglong = NonZeroU64; } +type_alias_no_nz! { "float.md", c_float = f32; } +type_alias_no_nz! { "double.md", c_double = f64; } #[stable(feature = "raw_os", since = "1.1.0")] #[doc(no_inline)] From 447ce2719810f7654bb3e5a3d20fb459bb191547 Mon Sep 17 00:00:00 2001 From: r00ster91 Date: Sat, 20 Feb 2021 18:32:02 +0100 Subject: [PATCH 04/25] Make "missing field" error message more natural --- compiler/rustc_typeck/src/check/expr.rs | 31 ++++++++++--------- src/test/ui/error-codes/E0063.rs | 2 +- src/test/ui/error-codes/E0063.stderr | 4 +-- src/test/ui/issues/issue-79593.rs | 2 +- src/test/ui/issues/issue-79593.stderr | 4 +-- src/test/ui/parser/issue-52496.rs | 2 +- src/test/ui/parser/issue-52496.stderr | 4 +-- .../parser/struct-field-numeric-shorthand.rs | 2 +- .../struct-field-numeric-shorthand.stderr | 4 +-- 9 files changed, 29 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index fa09c26c800ae..58cab950b2892 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1348,7 +1348,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, remaining_fields: FxHashMap, ) { - let tcx = self.tcx; let len = remaining_fields.len(); let mut displayable_field_names = @@ -1356,25 +1355,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { displayable_field_names.sort(); - let truncated_fields_error = if len <= 3 { - String::new() - } else { - format!(" and {} other field{}", (len - 3), if len - 3 == 1 { "" } else { "s" }) + let mut truncated_fields_error = String::new(); + let remaining_fields_names = match &displayable_field_names[..] { + [field1] => format!("`{}`", field1), + [field1, field2] => format!("`{}` and `{}`", field1, field2), + [field1, field2, field3] => format!("`{}`, `{}` and `{}`", field1, field2, field3), + _ => { + truncated_fields_error = + format!(" and {} other field{}", len - 3, pluralize!(len - 3)); + displayable_field_names + .iter() + .take(3) + .map(|n| format!("`{}`", n)) + .collect::>() + .join(", ") + } }; - let remaining_fields_names = displayable_field_names - .iter() - .take(3) - .map(|n| format!("`{}`", n)) - .collect::>() - .join(", "); - struct_span_err!( - tcx.sess, + self.tcx.sess, span, E0063, "missing field{} {}{} in initializer of `{}`", - pluralize!(remaining_fields.len()), + pluralize!(len), remaining_fields_names, truncated_fields_error, adt_ty diff --git a/src/test/ui/error-codes/E0063.rs b/src/test/ui/error-codes/E0063.rs index 37fc0a2987d3f..58527cc0c5dd7 100644 --- a/src/test/ui/error-codes/E0063.rs +++ b/src/test/ui/error-codes/E0063.rs @@ -32,7 +32,7 @@ fn main() { let w = SingleFoo { }; //~^ ERROR missing field `x` in initializer of `SingleFoo` let x = PluralFoo {x: 1}; - //~^ ERROR missing fields `y`, `z` in initializer of `PluralFoo` + //~^ ERROR missing fields `y` and `z` in initializer of `PluralFoo` let y = TruncatedFoo{x:1}; //~^ missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` let z = TruncatedPluralFoo{x:1}; diff --git a/src/test/ui/error-codes/E0063.stderr b/src/test/ui/error-codes/E0063.stderr index 5d366e0c1c47d..5dc4927071b6b 100644 --- a/src/test/ui/error-codes/E0063.stderr +++ b/src/test/ui/error-codes/E0063.stderr @@ -4,11 +4,11 @@ error[E0063]: missing field `x` in initializer of `SingleFoo` LL | let w = SingleFoo { }; | ^^^^^^^^^ missing `x` -error[E0063]: missing fields `y`, `z` in initializer of `PluralFoo` +error[E0063]: missing fields `y` and `z` in initializer of `PluralFoo` --> $DIR/E0063.rs:34:13 | LL | let x = PluralFoo {x: 1}; - | ^^^^^^^^^ missing `y`, `z` + | ^^^^^^^^^ missing `y` and `z` error[E0063]: missing fields `a`, `b`, `y` and 1 other field in initializer of `TruncatedFoo` --> $DIR/E0063.rs:36:13 diff --git a/src/test/ui/issues/issue-79593.rs b/src/test/ui/issues/issue-79593.rs index fb54b36940d51..b94278bfdd221 100644 --- a/src/test/ui/issues/issue-79593.rs +++ b/src/test/ui/issues/issue-79593.rs @@ -23,7 +23,7 @@ fn wrong() { foo::Enum::Variant { x: () }; //~^ ERROR missing field `y` in initializer of `Enum` foo::Enum::Variant { }; - //~^ ERROR missing fields `x`, `y` in initializer of `Enum` + //~^ ERROR missing fields `x` and `y` in initializer of `Enum` } fn main() {} diff --git a/src/test/ui/issues/issue-79593.stderr b/src/test/ui/issues/issue-79593.stderr index 33dbd85032eab..b8c7d4f23a28f 100644 --- a/src/test/ui/issues/issue-79593.stderr +++ b/src/test/ui/issues/issue-79593.stderr @@ -22,11 +22,11 @@ error[E0063]: missing field `y` in initializer of `Enum` LL | foo::Enum::Variant { x: () }; | ^^^^^^^^^^^^^^^^^^ missing `y` -error[E0063]: missing fields `x`, `y` in initializer of `Enum` +error[E0063]: missing fields `x` and `y` in initializer of `Enum` --> $DIR/issue-79593.rs:25:5 | LL | foo::Enum::Variant { }; - | ^^^^^^^^^^^^^^^^^^ missing `x`, `y` + | ^^^^^^^^^^^^^^^^^^ missing `x` and `y` error: aborting due to 5 previous errors diff --git a/src/test/ui/parser/issue-52496.rs b/src/test/ui/parser/issue-52496.rs index 4e9453653735a..05461f8b8c413 100644 --- a/src/test/ui/parser/issue-52496.rs +++ b/src/test/ui/parser/issue-52496.rs @@ -7,6 +7,6 @@ fn main() { let bar = 1.5f32; let _ = Foo { bar.into(), bat: -1, . }; //~^ ERROR expected one of - //~| ERROR missing fields `bar`, `baz` in initializer of `Foo` + //~| ERROR missing fields `bar` and `baz` in initializer of `Foo` //~| ERROR expected identifier, found `.` } diff --git a/src/test/ui/parser/issue-52496.stderr b/src/test/ui/parser/issue-52496.stderr index 10fcc46f344eb..9dbf26ef4b68c 100644 --- a/src/test/ui/parser/issue-52496.stderr +++ b/src/test/ui/parser/issue-52496.stderr @@ -26,11 +26,11 @@ error[E0063]: missing field `bat` in initializer of `Foo` LL | let _ = Foo { bar: .5, baz: 42 }; | ^^^ missing `bat` -error[E0063]: missing fields `bar`, `baz` in initializer of `Foo` +error[E0063]: missing fields `bar` and `baz` in initializer of `Foo` --> $DIR/issue-52496.rs:8:13 | LL | let _ = Foo { bar.into(), bat: -1, . }; - | ^^^ missing `bar`, `baz` + | ^^^ missing `bar` and `baz` error: aborting due to 5 previous errors diff --git a/src/test/ui/parser/struct-field-numeric-shorthand.rs b/src/test/ui/parser/struct-field-numeric-shorthand.rs index 58c40b3d96a49..645abd9c7192d 100644 --- a/src/test/ui/parser/struct-field-numeric-shorthand.rs +++ b/src/test/ui/parser/struct-field-numeric-shorthand.rs @@ -5,5 +5,5 @@ fn main() { //~^ ERROR expected identifier, found `0` //~| ERROR expected identifier, found `1` //~| ERROR expected identifier, found `2` - //~| ERROR missing fields `0`, `1`, `2` in initializer of `Rgb` + //~| ERROR missing fields `0`, `1` and `2` in initializer of `Rgb` } diff --git a/src/test/ui/parser/struct-field-numeric-shorthand.stderr b/src/test/ui/parser/struct-field-numeric-shorthand.stderr index cfb1f82014754..bfb8a931b6406 100644 --- a/src/test/ui/parser/struct-field-numeric-shorthand.stderr +++ b/src/test/ui/parser/struct-field-numeric-shorthand.stderr @@ -22,11 +22,11 @@ LL | let _ = Rgb { 0, 1, 2 }; | | | while parsing this struct -error[E0063]: missing fields `0`, `1`, `2` in initializer of `Rgb` +error[E0063]: missing fields `0`, `1` and `2` in initializer of `Rgb` --> $DIR/struct-field-numeric-shorthand.rs:4:13 | LL | let _ = Rgb { 0, 1, 2 }; - | ^^^ missing `0`, `1`, `2` + | ^^^ missing `0`, `1` and `2` error: aborting due to 4 previous errors From 553852806dfea7b9d8fb03a1ca4f51d8e31b3a3c Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 Feb 2021 14:43:25 -0700 Subject: [PATCH 05/25] Use the first paragraph, instead of cookie-cutter text, for rustdoc descriptions Fixes #82283 --- src/librustdoc/html/render/mod.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index f5eb92c1bb5aa..d7d69bc29f81e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -534,12 +534,17 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if !root_path.ends_with('/') { root_path.push('/'); } + let description = krate + .module + .as_ref() + .and_then(|item| Some(plain_text_summary(item.doc_value()?.as_str()))) + .unwrap_or_else(|| String::from("List of all items in this crate")); let mut page = layout::Page { title: "List of all items in this crate", css_class: "mod", root_path: "../", static_root_path: self.shared.static_root_path.as_deref(), - description: "List of all items in this crate", + description: description.as_str(), keywords: BASIC_KEYWORDS, resource_suffix: &self.shared.resource_suffix, extra_scripts: &[], @@ -1548,7 +1553,10 @@ impl Context<'_> { } title.push_str(" - Rust"); let tyname = it.type_(); - let desc = if it.is_crate() { + let desc = it.doc_value().as_ref().map(|doc| plain_text_summary(&doc)); + let desc = if let Some(desc) = desc { + desc + } else if it.is_crate() { format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate) } else { format!( From 1bedd4d6781aaf5e45d19b1f85db6cc28bfd2f4e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 Feb 2021 16:45:56 -0700 Subject: [PATCH 06/25] Cut off plain text descriptions after headers Before: The Rust Standard LibraryThe Rust Standard Library is the foundation of portable Rust software, a set of minimal and battle-tested shared abstractions for the broader Rust ecosystem. It offers core types, like `Vec` and `Option`, library-defined operations on language primitives, standard macros, I/O and multithreading, among many other things. After: The Rust Standard Library --- src/librustdoc/html/markdown.rs | 1 + src/librustdoc/html/markdown/tests.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a81fd55f6f192..b7854bbf82b17 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1124,6 +1124,7 @@ crate fn plain_text_summary(md: &str) -> String { Event::HardBreak | Event::SoftBreak => s.push(' '), Event::Start(Tag::CodeBlock(..)) => break, Event::End(Tag::Paragraph) => break, + Event::End(Tag::Heading(..)) => break, _ => (), } } diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs index 9da3072ec282f..994fe8206e8d4 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -230,6 +230,7 @@ fn test_plain_text_summary() { t("code `let x = i32;` ...", "code `let x = i32;` ..."); t("type `Type<'static>` ...", "type `Type<'static>` ..."); t("# top header", "top header"); + t("# top header\n\nfollowed by some text", "top header"); t("## header", "header"); t("first paragraph\n\nsecond paragraph", "first paragraph"); t("```\nfn main() {}\n```", ""); From bcef5e70774c792b17b5092859392f131f78bd3a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 Feb 2021 17:26:05 -0700 Subject: [PATCH 07/25] Revert changes to all.html This code wasn't actually working, and trying to SEO optimize that page is pointless anyway. --- src/librustdoc/html/render/mod.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index d7d69bc29f81e..87b5ae49d7fbc 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -534,17 +534,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { if !root_path.ends_with('/') { root_path.push('/'); } - let description = krate - .module - .as_ref() - .and_then(|item| Some(plain_text_summary(item.doc_value()?.as_str()))) - .unwrap_or_else(|| String::from("List of all items in this crate")); let mut page = layout::Page { title: "List of all items in this crate", css_class: "mod", root_path: "../", static_root_path: self.shared.static_root_path.as_deref(), - description: description.as_str(), + description: "List of all items in this crate", keywords: BASIC_KEYWORDS, resource_suffix: &self.shared.resource_suffix, extra_scripts: &[], From 8b3b1c922e323a9598e1225c67a7fbc81276cb1e Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 Feb 2021 17:38:41 -0700 Subject: [PATCH 08/25] Add rustdoc UI tests for new description behaviour --- src/test/rustdoc/description.rs | 19 +++++++++++++++++++ src/test/rustdoc/description_default.rs | 12 ++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 src/test/rustdoc/description.rs create mode 100644 src/test/rustdoc/description_default.rs diff --git a/src/test/rustdoc/description.rs b/src/test/rustdoc/description.rs new file mode 100644 index 0000000000000..869950a844aab --- /dev/null +++ b/src/test/rustdoc/description.rs @@ -0,0 +1,19 @@ +#![crate_name = "foo"] +//! # Description test crate +//! +//! This is the contents of the test crate docstring. It should not show up in the description. + +// @matches 'foo/index.html' '//meta[@name="description"]/@content' 'Description test crate' + +// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' 'First paragraph description.' +/// First paragraph description. +/// +/// Second paragraph should not show up. +pub mod foo_mod { + pub struct __Thing {} +} + +// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' 'Only paragraph.' +/// Only paragraph. +pub fn foo_fn() {} + diff --git a/src/test/rustdoc/description_default.rs b/src/test/rustdoc/description_default.rs new file mode 100644 index 0000000000000..e36f2be00e48f --- /dev/null +++ b/src/test/rustdoc/description_default.rs @@ -0,0 +1,12 @@ +#![crate_name = "foo"] + +// @matches 'foo/index.html' '//meta[@name="description"]/@content' 'API documentation for the Rust `foo` crate.' + +// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' 'API documentation for the Rust `foo_mod` mod in crate `foo`.' +pub mod foo_mod { + pub struct __Thing {} +} + +// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' 'API documentation for the Rust `foo_fn` fn in crate `foo`.' +pub fn foo_fn() {} + From dcf49916e4fac986b602f345b60b712cd536494d Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 Feb 2021 17:50:01 -0700 Subject: [PATCH 09/25] Fix formatting for description rustdoc UI tests --- src/test/rustdoc/description.rs | 13 ++++++++----- src/test/rustdoc/description_default.rs | 10 ++++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/test/rustdoc/description.rs b/src/test/rustdoc/description.rs index 869950a844aab..45aff9a29f919 100644 --- a/src/test/rustdoc/description.rs +++ b/src/test/rustdoc/description.rs @@ -1,11 +1,14 @@ #![crate_name = "foo"] //! # Description test crate //! -//! This is the contents of the test crate docstring. It should not show up in the description. +//! This is the contents of the test crate docstring. +//! It should not show up in the description. -// @matches 'foo/index.html' '//meta[@name="description"]/@content' 'Description test crate' +// @matches 'foo/index.html' '//meta[@name="description"]/@content' \ +// 'Description test crate' -// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' 'First paragraph description.' +// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ +// 'First paragraph description.' /// First paragraph description. /// /// Second paragraph should not show up. @@ -13,7 +16,7 @@ pub mod foo_mod { pub struct __Thing {} } -// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' 'Only paragraph.' +// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \ +// 'Only paragraph.' /// Only paragraph. pub fn foo_fn() {} - diff --git a/src/test/rustdoc/description_default.rs b/src/test/rustdoc/description_default.rs index e36f2be00e48f..6868dd3bfd232 100644 --- a/src/test/rustdoc/description_default.rs +++ b/src/test/rustdoc/description_default.rs @@ -1,12 +1,14 @@ #![crate_name = "foo"] -// @matches 'foo/index.html' '//meta[@name="description"]/@content' 'API documentation for the Rust `foo` crate.' +// @matches 'foo/index.html' '//meta[@name="description"]/@content' \ +// 'API documentation for the Rust `foo` crate.' -// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' 'API documentation for the Rust `foo_mod` mod in crate `foo`.' +// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ +// 'API documentation for the Rust `foo_mod` mod in crate `foo`.' pub mod foo_mod { pub struct __Thing {} } -// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' 'API documentation for the Rust `foo_fn` fn in crate `foo`.' +// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \ +// 'API documentation for the Rust `foo_fn` fn in crate `foo`.' pub fn foo_fn() {} - From fd5a710092fe1e7668c55999c12104c122da732a Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sat, 20 Feb 2021 17:51:41 -0700 Subject: [PATCH 10/25] Use has for non-regexes --- src/test/rustdoc/description.rs | 6 +++--- src/test/rustdoc/description_default.rs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/rustdoc/description.rs b/src/test/rustdoc/description.rs index 45aff9a29f919..79990203c4053 100644 --- a/src/test/rustdoc/description.rs +++ b/src/test/rustdoc/description.rs @@ -4,10 +4,10 @@ //! This is the contents of the test crate docstring. //! It should not show up in the description. -// @matches 'foo/index.html' '//meta[@name="description"]/@content' \ +// @has 'foo/index.html' '//meta[@name="description"]/@content' \ // 'Description test crate' -// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ +// @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ // 'First paragraph description.' /// First paragraph description. /// @@ -16,7 +16,7 @@ pub mod foo_mod { pub struct __Thing {} } -// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \ +// @has 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \ // 'Only paragraph.' /// Only paragraph. pub fn foo_fn() {} diff --git a/src/test/rustdoc/description_default.rs b/src/test/rustdoc/description_default.rs index 6868dd3bfd232..21d8e04d3f95a 100644 --- a/src/test/rustdoc/description_default.rs +++ b/src/test/rustdoc/description_default.rs @@ -1,14 +1,14 @@ #![crate_name = "foo"] -// @matches 'foo/index.html' '//meta[@name="description"]/@content' \ +// @has 'foo/index.html' '//meta[@name="description"]/@content' \ // 'API documentation for the Rust `foo` crate.' -// @matches 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ +// @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ // 'API documentation for the Rust `foo_mod` mod in crate `foo`.' pub mod foo_mod { pub struct __Thing {} } -// @matches 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \ +// @has 'foo/fn.foo_fn.html' '//meta[@name="description"]/@content' \ // 'API documentation for the Rust `foo_fn` fn in crate `foo`.' pub fn foo_fn() {} From 6a85719b6a21d13a7ab9fcd0306b6fafb8b25e09 Mon Sep 17 00:00:00 2001 From: Camelid Date: Sat, 20 Feb 2021 17:12:22 -0800 Subject: [PATCH 11/25] rustdoc: Remove unnecessary `Cell` around `param_env` --- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/core.rs | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1cfa6090ef48d..98e1299df2f26 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1519,7 +1519,7 @@ fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option> { let lifted = ty.lift_to_tcx(cx.tcx).unwrap(); let normalized = cx.tcx.infer_ctxt().enter(|infcx| { infcx - .at(&ObligationCause::dummy(), cx.param_env.get()) + .at(&ObligationCause::dummy(), cx.param_env) .normalize(lifted) .map(|resolved| infcx.resolve_vars_if_possible(resolved.value)) }); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1c2d2ad626c5a..1813367f789a1 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -26,10 +26,7 @@ use rustc_span::DUMMY_SP; use std::mem; use std::rc::Rc; -use std::{ - cell::{Cell, RefCell}, - collections::hash_map::Entry, -}; +use std::{cell::RefCell, collections::hash_map::Entry}; use crate::clean; use crate::clean::inline::build_external_trait; @@ -49,7 +46,7 @@ crate struct DocContext<'tcx> { /// Used for normalization. /// /// Most of this logic is copied from rustc_lint::late. - crate param_env: Cell>, + crate param_env: ParamEnv<'tcx>, /// Later on moved into `cache` crate renderinfo: RefCell, /// Later on moved through `clean::Crate` into `cache` @@ -89,9 +86,9 @@ impl<'tcx> DocContext<'tcx> { } crate fn with_param_env T>(&mut self, def_id: DefId, f: F) -> T { - let old_param_env = self.param_env.replace(self.tcx.param_env(def_id)); + let old_param_env = mem::replace(&mut self.param_env, self.tcx.param_env(def_id)); let ret = f(self); - self.param_env.set(old_param_env); + self.param_env = old_param_env; ret } @@ -511,7 +508,7 @@ crate fn run_global_ctxt( let mut ctxt = DocContext { tcx, resolver, - param_env: Cell::new(ParamEnv::empty()), + param_env: ParamEnv::empty(), external_traits: Default::default(), active_extern_traits: Default::default(), renderinfo: RefCell::new(renderinfo), From 60a9dcc4e3a98362bc4c4a3bfa4918c1f4f639b1 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 21 Feb 2021 19:43:42 +1000 Subject: [PATCH 12/25] update tracking issue for raw_os_nonzero --- library/std/src/os/raw/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 3dc97a0c458af..22c98d7ade992 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -39,7 +39,7 @@ macro_rules! type_alias { type_alias_no_nz! { $Docfile, $Alias = $Real; $( $Cfg )* } #[doc = concat!("Type alias for `NonZero` version of [`", stringify!($Alias), "`]")] - #[unstable(feature = "raw_os_nonzero", issue = "none")] + #[unstable(feature = "raw_os_nonzero", issue = "82363")] $( $Cfg )* pub type $NZAlias = $NZReal; } From 4cb649bdb1c5f176c48a692a4271489dd3fe5ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 12:52:51 +0100 Subject: [PATCH 13/25] remove unneccessary wrapping of return value of allow_unstable(), it would always return Some(thing) --- compiler/rustc_attr/src/builtin.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index aca3fbbca1357..378911f0c4ebd 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -1036,21 +1036,21 @@ pub fn allow_internal_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], ) -> Option + 'a> { - allow_unstable(sess, attrs, sym::allow_internal_unstable) + Some(allow_unstable(sess, attrs, sym::allow_internal_unstable)) } pub fn rustc_allow_const_fn_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], ) -> Option + 'a> { - allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable) + Some(allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)) } fn allow_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], symbol: Symbol, -) -> Option + 'a> { +) -> impl Iterator + 'a { let attrs = sess.filter_by_name(attrs, symbol); let list = attrs .filter_map(move |attr| { @@ -1064,7 +1064,7 @@ fn allow_unstable<'a>( }) .flatten(); - Some(list.into_iter().filter_map(move |it| { + list.into_iter().filter_map(move |it| { let name = it.ident().map(|ident| ident.name); if name.is_none() { sess.diagnostic().span_err( @@ -1073,5 +1073,5 @@ fn allow_unstable<'a>( ); } name - })) + }) } From 12080dc3a3ebee0e343d528ca15835ac2d4c75c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 12:54:49 +0100 Subject: [PATCH 14/25] rustc_parse: remove unneccessary wrapping of return value in fn mk_range() which would always return Ok(..) --- compiler/rustc_parse/src/parser/expr.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index fa05df6805f51..34b4d3200a9d8 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -426,7 +426,7 @@ impl<'a> Parser<'a> { let span = self.mk_expr_sp(&lhs, lhs.span, rhs_span); let limits = if op == AssocOp::DotDot { RangeLimits::HalfOpen } else { RangeLimits::Closed }; - Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits)?, AttrVec::new())) + Ok(self.mk_expr(span, self.mk_range(Some(lhs), rhs, limits), AttrVec::new())) } fn is_at_start_of_range_notation_rhs(&self) -> bool { @@ -474,7 +474,7 @@ impl<'a> Parser<'a> { } else { (lo, None) }; - Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits)?, attrs.into())) + Ok(this.mk_expr(span, this.mk_range(None, opt_end, limits), attrs.into())) }) } @@ -2396,12 +2396,12 @@ impl<'a> Parser<'a> { start: Option>, end: Option>, limits: RangeLimits, - ) -> PResult<'a, ExprKind> { + ) -> ExprKind { if end.is_none() && limits == RangeLimits::Closed { self.error_inclusive_range_with_no_end(self.prev_token.span); - Ok(ExprKind::Err) + ExprKind::Err } else { - Ok(ExprKind::Range(start, end, limits)) + ExprKind::Range(start, end, limits) } } From 00bc134e43f30142ea5208dc70dce8ef1e6ac3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 13:01:01 +0100 Subject: [PATCH 15/25] remove unneccessary wrapping of return value in mk_await_expr() --- compiler/rustc_parse/src/parser/expr.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 34b4d3200a9d8..28bfaea4555b5 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { - return self.mk_await_expr(self_arg, lo); + return Ok(self.mk_await_expr(self_arg, lo)); } let fn_span_lo = self.token.span; @@ -2421,11 +2421,11 @@ impl<'a> Parser<'a> { ExprKind::Call(f, args) } - fn mk_await_expr(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { + fn mk_await_expr(&mut self, self_arg: P, lo: Span) -> P { let span = lo.to(self.prev_token.span); let await_expr = self.mk_expr(span, ExprKind::Await(self_arg), AttrVec::new()); self.recover_from_await_method_call(); - Ok(await_expr) + await_expr } crate fn mk_expr(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P { From 85bd00fd85bd2e00b97ca45f58d7686e44f554e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 13:06:00 +0100 Subject: [PATCH 16/25] parser: remove unneccessary wrapping of return value in parse_extern() --- compiler/rustc_parse/src/parser/item.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0f907859a19a6..f3f5fc9af64fe 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1679,7 +1679,7 @@ impl<'a> Parser<'a> { let constness = self.parse_constness(); let asyncness = self.parse_asyncness(); let unsafety = self.parse_unsafety(); - let ext = self.parse_extern()?; + let ext = self.parse_extern(); if let Async::Yes { span, .. } = asyncness { self.ban_async_in_2015(span); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index ace4134b1f698..1292286bc18b0 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1202,12 +1202,8 @@ impl<'a> Parser<'a> { } /// Parses `extern string_literal?`. - fn parse_extern(&mut self) -> PResult<'a, Extern> { - Ok(if self.eat_keyword(kw::Extern) { - Extern::from_abi(self.parse_abi()) - } else { - Extern::None - }) + fn parse_extern(&mut self) -> Extern { + if self.eat_keyword(kw::Extern) { Extern::from_abi(self.parse_abi()) } else { Extern::None } } /// Parses a string literal as an ABI spec. From 393878b15bbdf553e678dac3a7dd288bd6af879e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 13:25:28 +0100 Subject: [PATCH 17/25] remove redundant return value Ok(()) of clear_relocations() --- .../rustc_middle/src/mir/interpret/allocation.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5ebe38b2d7e09..449b3a82dcbb7 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -266,7 +266,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { let range = self.check_bounds(ptr.offset, size); self.mark_init(ptr, size, true); - self.clear_relocations(cx, ptr, size)?; + self.clear_relocations(cx, ptr, size); AllocationExtra::memory_written(self, ptr, size)?; @@ -484,18 +484,13 @@ impl<'tcx, Tag: Copy, Extra> Allocation { /// uninitialized. This is a somewhat odd "spooky action at a distance", /// but it allows strictly more code to run than if we would just error /// immediately in that case. - fn clear_relocations( - &mut self, - cx: &impl HasDataLayout, - ptr: Pointer, - size: Size, - ) -> InterpResult<'tcx> { + fn clear_relocations(&mut self, cx: &impl HasDataLayout, ptr: Pointer, size: Size) { // Find the start and end of the given range and its outermost relocations. let (first, last) = { // Find all relocations overlapping the given range. let relocations = self.get_relocations(cx, ptr, size); if relocations.is_empty() { - return Ok(()); + return; } ( @@ -517,8 +512,6 @@ impl<'tcx, Tag: Copy, Extra> Allocation { // Forget all the relocations. self.relocations.remove_range(first..last); - - Ok(()) } /// Errors if there are relocations overlapping with the edges of the From 76b9b16b4d589a72364b3be1c3a61816a99c3715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 13:40:39 +0100 Subject: [PATCH 18/25] rustc_codegen_ssa: remove unneeded wrapping of return type of execute_copy_from_cache_work_item (always returns Ok(..)) --- compiler/rustc_codegen_ssa/src/back/write.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index b0aed81246007..f5ae406faec2d 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -735,7 +735,7 @@ fn execute_work_item( match work_item { WorkItem::Optimize(module) => execute_optimize_work_item(cgcx, module, module_config), WorkItem::CopyPostLtoArtifacts(module) => { - execute_copy_from_cache_work_item(cgcx, module, module_config) + Ok(execute_copy_from_cache_work_item(cgcx, module, module_config)) } WorkItem::LTO(module) => execute_lto_work_item(cgcx, module, module_config), } @@ -844,7 +844,7 @@ fn execute_copy_from_cache_work_item( cgcx: &CodegenContext, module: CachedModuleCodegen, module_config: &ModuleConfig, -) -> Result, FatalError> { +) -> WorkItemResult { let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let mut object = None; if let Some(saved_file) = module.source.saved_file { @@ -870,13 +870,13 @@ fn execute_copy_from_cache_work_item( assert_eq!(object.is_some(), module_config.emit_obj != EmitObj::None); - Ok(WorkItemResult::Compiled(CompiledModule { + WorkItemResult::Compiled(CompiledModule { name: module.name, kind: ModuleKind::Regular, object, dwarf_object: None, bytecode: None, - })) + }) } fn execute_lto_work_item( From a9b90c02a2aaa53881aa650d3792726135402403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 13:44:16 +0100 Subject: [PATCH 19/25] rustc_mir: remove redundant wrapping of return type in numeric_intrinsic() --- compiler/rustc_mir/src/interpret/intrinsics.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index c4039f2f15e94..d36b3a7d9b56e 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -23,11 +23,7 @@ use super::{ mod caller_location; mod type_name; -fn numeric_intrinsic<'tcx, Tag>( - name: Symbol, - bits: u128, - kind: Primitive, -) -> InterpResult<'tcx, Scalar> { +fn numeric_intrinsic(name: Symbol, bits: u128, kind: Primitive) -> Scalar { let size = match kind { Primitive::Int(integer, _) => integer.size(), _ => bug!("invalid `{}` argument: {:?}", name, bits), @@ -41,7 +37,7 @@ fn numeric_intrinsic<'tcx, Tag>( sym::bitreverse => (bits << extra).reverse_bits(), _ => bug!("not a numeric intrinsic: {}", name), }; - Ok(Scalar::from_uint(bits_out, size)) + Scalar::from_uint(bits_out, size) } /// The logic for all nullary intrinsics is implemented here. These intrinsics don't get evaluated @@ -208,7 +204,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if nonzero && bits == 0 { throw_ub_format!("`{}_nonzero` called on 0", intrinsic_name); } - let out_val = numeric_intrinsic(intrinsic_name, bits, kind)?; + let out_val = numeric_intrinsic(intrinsic_name, bits, kind); self.write_scalar(out_val, dest)?; } sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => { From 12608832c3b624c3d59b1371f3935804e8364127 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 21 Feb 2021 17:24:19 +0100 Subject: [PATCH 20/25] improve UnsafeCell docs --- library/core/src/cell.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cb772458e50b6..cce1242d84f52 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1619,17 +1619,18 @@ impl fmt::Display for RefMut<'_, T> { /// The core primitive for interior mutability in Rust. /// -/// `UnsafeCell` is a type that wraps some `T` and indicates unsafe interior operations on the -/// wrapped type. Types with an `UnsafeCell` field are considered to have an 'unsafe interior'. -/// The `UnsafeCell` type is the only legal way to obtain aliasable data that is considered -/// mutable. In general, transmuting a `&T` type into a `&mut T` is considered undefined behavior. +/// If you have a reference `&T`, then normally in Rust the compiler performs optimizations based on +/// the knowledge that `&T` points to immutable data. Mutating that data, for example through an +/// alias or by transmuting an `&T` into an `&mut T`, is considered undefined behavior. +/// `UnsafeCell` opts-out of the immutability guarantee for `&T`: a shared reference +/// `&UnsafeCell` may point to data that is being mutated. This is called "interior mutability". /// -/// If you have a reference `&SomeStruct`, then normally in Rust all fields of `SomeStruct` are -/// immutable. The compiler makes optimizations based on the knowledge that `&T` is not mutably -/// aliased or mutated, and that `&mut T` is unique. `UnsafeCell` is the only core language -/// feature to work around the restriction that `&T` may not be mutated. All other types that -/// allow internal mutability, such as `Cell` and `RefCell`, use `UnsafeCell` to wrap their -/// internal data. There is *no* legal way to obtain aliasing `&mut`, not even with `UnsafeCell`. +/// All other types that allow internal mutability, such as `Cell` and `RefCell`, internally +/// use `UnsafeCell` to wrap their data. +/// +/// Note that only the immutability guarantee for shared references is affected by `UnsafeCell`. The +/// uniqueness guarantee for mutable references is unaffected. There is *no* legal way to obtain +/// aliasing `&mut`, not even with `UnsafeCell`. /// /// The `UnsafeCell` API itself is technically very simple: [`.get()`] gives you a raw pointer /// `*mut T` to its contents. It is up to _you_ as the abstraction designer to use that raw pointer From a6b85fbc78280c8caae26769191b787ad8543ddf Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 21 Feb 2021 09:31:23 -0700 Subject: [PATCH 21/25] Update src/test/rustdoc/description.rs Co-authored-by: Joshua Nelson --- src/test/rustdoc/description.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc/description.rs b/src/test/rustdoc/description.rs index 79990203c4053..a95f177f6b0b0 100644 --- a/src/test/rustdoc/description.rs +++ b/src/test/rustdoc/description.rs @@ -9,6 +9,7 @@ // @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ // 'First paragraph description.' +// @!has - '//meta[@name="description"]/@content' 'Second paragraph' /// First paragraph description. /// /// Second paragraph should not show up. From 575c75b324ee7557b776f6dce6f4f77f5f7887a1 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Sun, 21 Feb 2021 09:31:39 -0700 Subject: [PATCH 22/25] Update src/test/rustdoc/description.rs Co-authored-by: Joshua Nelson --- src/test/rustdoc/description.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/rustdoc/description.rs b/src/test/rustdoc/description.rs index a95f177f6b0b0..05ec428220847 100644 --- a/src/test/rustdoc/description.rs +++ b/src/test/rustdoc/description.rs @@ -6,6 +6,7 @@ // @has 'foo/index.html' '//meta[@name="description"]/@content' \ // 'Description test crate' +// @!has - '//meta[@name="description"]/@content' 'should not show up' // @has 'foo/foo_mod/index.html' '//meta[@name="description"]/@content' \ // 'First paragraph description.' From da9a588d4fda02c2fe6d52db651ec4c83b2b3e49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 21 Feb 2021 18:11:27 +0100 Subject: [PATCH 23/25] remove redundant wrapping of return types of allow_internal_unstable() and rustc_allow_const_fn_unstable() --- compiler/rustc_attr/src/builtin.rs | 8 ++++---- compiler/rustc_expand/src/base.rs | 4 ++-- compiler/rustc_mir/src/transform/check_consts/mod.rs | 3 +-- compiler/rustc_passes/src/check_const.rs | 2 +- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index 378911f0c4ebd..24da75114a656 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -1035,15 +1035,15 @@ pub fn find_transparency( pub fn allow_internal_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], -) -> Option + 'a> { - Some(allow_unstable(sess, attrs, sym::allow_internal_unstable)) +) -> impl Iterator + 'a { + allow_unstable(sess, attrs, sym::allow_internal_unstable) } pub fn rustc_allow_const_fn_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], -) -> Option + 'a> { - Some(allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable)) +) -> impl Iterator + 'a { + allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable) } fn allow_unstable<'a>( diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e3dc793a7fac4..ca304c05cdce3 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -756,8 +756,8 @@ impl SyntaxExtension { name: Symbol, attrs: &[ast::Attribute], ) -> SyntaxExtension { - let allow_internal_unstable = attr::allow_internal_unstable(sess, &attrs) - .map(|features| features.collect::>().into()); + let allow_internal_unstable = + Some(attr::allow_internal_unstable(sess, &attrs).collect::>().into()); let mut local_inner_macros = false; if let Some(macro_export) = sess.find_by_name(attrs, sym::macro_export) { diff --git a/compiler/rustc_mir/src/transform/check_consts/mod.rs b/compiler/rustc_mir/src/transform/check_consts/mod.rs index ba7bea4ac54e1..19aee033a6923 100644 --- a/compiler/rustc_mir/src/transform/check_consts/mod.rs +++ b/compiler/rustc_mir/src/transform/check_consts/mod.rs @@ -85,8 +85,7 @@ pub fn rustc_allow_const_fn_unstable( feature_gate: Symbol, ) -> bool { let attrs = tcx.get_attrs(def_id); - attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs) - .map_or(false, |mut features| features.any(|name| name == feature_gate)) + attr::rustc_allow_const_fn_unstable(&tcx.sess, attrs).any(|name| name == feature_gate) } // Returns `true` if the given `const fn` is "const-stable". diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 9328f7cd9ec7b..da713566c3121 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -106,7 +106,7 @@ impl<'tcx> CheckConstVisitor<'tcx> { // However, we cannot allow stable `const fn`s to use unstable features without an explicit // opt-in via `rustc_allow_const_fn_unstable`. attr::rustc_allow_const_fn_unstable(&tcx.sess, &tcx.get_attrs(def_id)) - .map_or(false, |mut features| features.any(|name| name == feature_gate)) + .any(|name| name == feature_gate) }; match required_gates { From 7130e462eeecb3fd0f5614f577896712b1b7bb2a Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Mon, 22 Feb 2021 00:22:15 +0200 Subject: [PATCH 24/25] Fix sizes of repr(C) enums on hexagon Enums on hexagon use a smallest size (but at least 1 byte) that fits all the enumeration values. This is unlike many other ABIs where enums are at least 32 bits. --- compiler/rustc_middle/src/ty/layout.rs | 1 + src/test/ui/layout/hexagon-enum.rs | 33 ++ src/test/ui/layout/hexagon-enum.stderr | 442 +++++++++++++++++++++++++ 3 files changed, 476 insertions(+) create mode 100644 src/test/ui/layout/hexagon-enum.rs create mode 100644 src/test/ui/layout/hexagon-enum.stderr diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0b592ca4710b6..12dcb95187cff 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -130,6 +130,7 @@ impl IntegerExt for Integer { if repr.c() { match &tcx.sess.target.arch[..] { + "hexagon" => min_from_extern = Some(I8), // WARNING: the ARM EABI has two variants; the one corresponding // to `at_least == I32` appears to be used on Linux and NetBSD, // but some systems may use the variant corresponding to no diff --git a/src/test/ui/layout/hexagon-enum.rs b/src/test/ui/layout/hexagon-enum.rs new file mode 100644 index 0000000000000..4bcfa58f7cf15 --- /dev/null +++ b/src/test/ui/layout/hexagon-enum.rs @@ -0,0 +1,33 @@ +// compile-flags: --target hexagon-unknown-linux-musl +// +// Verify that the hexagon targets implement the repr(C) for enums correctly. +// +// See #82100 +#![feature(never_type, rustc_attrs, type_alias_impl_trait, no_core, lang_items)] +#![crate_type = "lib"] +#![no_core] + +#[lang="sized"] +trait Sized {} + +#[rustc_layout(debug)] +#[repr(C)] +enum A { Apple } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum B { Banana = 255, } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum C { Chaenomeles = 256, } //~ ERROR: layout_of + +#[rustc_layout(debug)] +#[repr(C)] +enum P { Peach = 0x1000_0000isize, } //~ ERROR: layout_of + +const TANGERINE: usize = 0x8100_0000; // hack to get negative numbers without negation operator! + +#[rustc_layout(debug)] +#[repr(C)] +enum T { Tangerine = TANGERINE as isize } //~ ERROR: layout_of diff --git a/src/test/ui/layout/hexagon-enum.stderr b/src/test/ui/layout/hexagon-enum.stderr new file mode 100644 index 0000000000000..390eff6e5b957 --- /dev/null +++ b/src/test/ui/layout/hexagon-enum.stderr @@ -0,0 +1,442 @@ +error: layout_of(A) = Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I8, + false, + ), + valid_range: 0..=0, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, +} + --> $DIR/hexagon-enum.rs:15:1 + | +LL | enum A { Apple } + | ^^^^^^^^^^^^^^^^ + +error: layout_of(B) = Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I8, + false, + ), + valid_range: 255..=255, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 0, + }, + pref: Align { + pow2: 0, + }, + }, + size: Size { + raw: 1, + }, +} + --> $DIR/hexagon-enum.rs:19:1 + | +LL | enum B { Banana = 255, } + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(C) = Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 1, + }, + pref: Align { + pow2: 1, + }, + }, + size: Size { + raw: 2, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I16, + false, + ), + valid_range: 256..=256, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 1, + }, + pref: Align { + pow2: 1, + }, + }, + size: Size { + raw: 2, + }, +} + --> $DIR/hexagon-enum.rs:23:1 + | +LL | enum C { Chaenomeles = 256, } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(P) = Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + false, + ), + valid_range: 268435456..=268435456, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, +} + --> $DIR/hexagon-enum.rs:27:1 + | +LL | enum P { Peach = 0x1000_0000isize, } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: layout_of(T) = Layout { + fields: Arbitrary { + offsets: [ + Size { + raw: 0, + }, + ], + memory_index: [ + 0, + ], + }, + variants: Multiple { + tag: Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + tag_encoding: Direct, + tag_field: 0, + variants: [ + Layout { + fields: Arbitrary { + offsets: [], + memory_index: [], + }, + variants: Single { + index: 0, + }, + abi: Aggregate { + sized: true, + }, + largest_niche: None, + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, + }, + ], + }, + abi: Scalar( + Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + ), + largest_niche: Some( + Niche { + offset: Size { + raw: 0, + }, + scalar: Scalar { + value: Int( + I32, + true, + ), + valid_range: 2164260864..=2164260864, + }, + }, + ), + align: AbiAndPrefAlign { + abi: Align { + pow2: 2, + }, + pref: Align { + pow2: 2, + }, + }, + size: Size { + raw: 4, + }, +} + --> $DIR/hexagon-enum.rs:33:1 + | +LL | enum T { Tangerine = TANGERINE as isize } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + From 45673e2d443a7bc02469281c138b833c4d12528e Mon Sep 17 00:00:00 2001 From: Camelid Date: Sun, 21 Feb 2021 17:52:23 -0800 Subject: [PATCH 25/25] rustdoc: Remove `fake_def_ids` RefCell --- src/librustdoc/core.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 1c2d2ad626c5a..1d249f1b91398 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -67,7 +67,7 @@ crate struct DocContext<'tcx> { crate ct_substs: RefCell>, /// Table synthetic type parameter for `impl Trait` in argument position -> bounds crate impl_trait_bounds: RefCell>>, - crate fake_def_ids: RefCell>, + crate fake_def_ids: FxHashMap, /// Auto-trait or blanket impls processed so far, as `(self_ty, trait_def_id)`. // FIXME(eddyb) make this a `ty::TraitRef<'tcx>` set. crate generated_synthetics: RefCell, DefId)>>, @@ -140,16 +140,14 @@ impl<'tcx> DocContext<'tcx> { /// [`RefCell`]: std::cell::RefCell /// [`Debug`]: std::fmt::Debug /// [`clean::Item`]: crate::clean::types::Item - crate fn next_def_id(&self, crate_num: CrateNum) -> DefId { - let mut fake_ids = self.fake_def_ids.borrow_mut(); - - let def_index = match fake_ids.entry(crate_num) { + crate fn next_def_id(&mut self, crate_num: CrateNum) -> DefId { + let def_index = match self.fake_def_ids.entry(crate_num) { Entry::Vacant(e) => { let num_def_idx = { let num_def_idx = if crate_num == LOCAL_CRATE { self.tcx.hir().definitions().def_path_table().num_def_ids() } else { - self.enter_resolver(|r| r.cstore().num_def_ids(crate_num)) + self.resolver.borrow_mut().access(|r| r.cstore().num_def_ids(crate_num)) }; DefIndex::from_usize(num_def_idx)