diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs index aca3fbbca13..24da75114a6 100644 --- a/compiler/rustc_attr/src/builtin.rs +++ b/compiler/rustc_attr/src/builtin.rs @@ -1035,14 +1035,14 @@ pub fn find_transparency( pub fn allow_internal_unstable<'a>( sess: &'a Session, attrs: &'a [Attribute], -) -> Option + 'a> { +) -> 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> { +) -> impl Iterator + 'a { allow_unstable(sess, attrs, sym::rustc_allow_const_fn_unstable) } @@ -1050,7 +1050,7 @@ 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 - })) + }) } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index b0aed812460..f5ae406faec 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( diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index e3dc793a7fa..ca304c05cdc 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -756,8 +756,8 @@ pub fn new( 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_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 5ebe38b2d7e..449b3a82dcb 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -266,7 +266,7 @@ pub fn get_bytes_mut( 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 @@ fn check_relocations( /// 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 @@ fn clear_relocations( // Forget all the relocations. self.relocations.remove_range(first..last); - - Ok(()) } /// Errors if there are relocations overlapping with the edges of the diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 0b592ca4710..12dcb95187c 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -130,6 +130,7 @@ fn repr_discr<'tcx>( 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/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index c4039f2f15e..d36b3a7d9b5 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -23,11 +23,7 @@ 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 @@ pub fn emulate_intrinsic( 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 => { diff --git a/compiler/rustc_mir/src/transform/check_consts/mod.rs b/compiler/rustc_mir/src/transform/check_consts/mod.rs index ba7bea4ac54..19aee033a69 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_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index fa05df6805f..28bfaea4555 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -426,7 +426,7 @@ fn parse_range_expr( 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 @@ fn parse_prefix_range_expr(&mut self, attrs: Option) -> PResult<'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())) }) } @@ -1041,7 +1041,7 @@ fn parse_index_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> /// 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; @@ -2396,12 +2396,12 @@ fn mk_range( 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) } } @@ -2421,11 +2421,11 @@ fn mk_call(&self, f: P, args: Vec>) -> ExprKind { 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 { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 0f907859a19..f3f5fc9af64 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1679,7 +1679,7 @@ pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> { 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 ace4134b1f6..1292286bc18 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1202,12 +1202,8 @@ fn recover_incorrect_vis_restriction(&mut self) -> PResult<'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. diff --git a/compiler/rustc_passes/src/check_const.rs b/compiler/rustc_passes/src/check_const.rs index 9328f7cd9ec..da713566c31 100644 --- a/compiler/rustc_passes/src/check_const.rs +++ b/compiler/rustc_passes/src/check_const.rs @@ -106,7 +106,7 @@ fn const_check_violated(&self, expr: NonConstExpr, span: Span) { // 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 { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 32bf0ab7e85..2faf128c491 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -1348,7 +1348,6 @@ fn report_missing_fields( span: Span, remaining_fields: FxHashMap, ) { - let tcx = self.tcx; let len = remaining_fields.len(); let mut displayable_field_names = @@ -1356,25 +1355,29 @@ fn report_missing_fields( 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/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index d13061d2203..d4fd7545d9b 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -11,8 +11,9 @@ 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 @@ macro_rules! array_impl_default { /// 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 @@ fn drop(&mut self) { /// ``` #[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 @@ pub fn as_mut_slice(&mut self) -> &mut [T] { /// ``` #[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 @@ pub fn as_mut_slice(&mut self) -> &mut [T] { /// ``` #[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: 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: 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: 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 +} diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index cb772458e50..cce1242d84f 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1619,17 +1619,18 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { /// 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 diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 16733b7ccd3..5e46d2c17c9 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 16272aa0571..22c98d7ade9 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -11,7 +11,41 @@ #[cfg(test)] mod tests; -#[doc(include = "char.md")] +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")] + pub type $Alias = $Real; + } +} + +// 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 = "82363")] + $( $Cfg )* + pub type $NZAlias = $NZReal; + } +} + +type_alias! { "char.md", c_char = u8, NonZero_c_char = NonZeroU8; #[cfg(any( all( target_os = "linux", @@ -52,10 +86,8 @@ ) ), 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, NonZero_c_char = NonZeroI8; #[cfg(not(any( all( target_os = "linux", @@ -96,55 +128,25 @@ ) ), 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, 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)] diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1cfa6090ef4..98e1299df2f 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 1c2d2ad626c..dbf202a7321 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -26,10 +26,7 @@ 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 @@ /// 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` @@ -67,7 +64,7 @@ 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)>>, @@ -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 } @@ -140,16 +137,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) @@ -511,7 +506,7 @@ pub(crate) fn init_lints( 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), diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index a81fd55f6f1..b7854bbf82b 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1124,6 +1124,7 @@ fn push(s: &mut String, text_length: &mut usize, text: &str) { 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 9da3072ec28..994fe8206e8 100644 --- a/src/librustdoc/html/markdown/tests.rs +++ b/src/librustdoc/html/markdown/tests.rs @@ -230,6 +230,7 @@ fn t(input: &str, expect: &str) { 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```", ""); diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 7ca355ed11c..7f122bb8cb5 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1548,7 +1548,10 @@ fn render_item(&self, it: &clean::Item, pushname: bool) -> String { } 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!( diff --git a/src/test/rustdoc/description.rs b/src/test/rustdoc/description.rs new file mode 100644 index 00000000000..05ec4282208 --- /dev/null +++ b/src/test/rustdoc/description.rs @@ -0,0 +1,24 @@ +#![crate_name = "foo"] +//! # Description test crate +//! +//! This is the contents of the test crate docstring. +//! It should not show up in the description. + +// @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.' +// @!has - '//meta[@name="description"]/@content' 'Second paragraph' +/// First paragraph description. +/// +/// Second paragraph should not show up. +pub mod foo_mod { + pub struct __Thing {} +} + +// @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 new file mode 100644 index 00000000000..21d8e04d3f9 --- /dev/null +++ b/src/test/rustdoc/description_default.rs @@ -0,0 +1,14 @@ +#![crate_name = "foo"] + +// @has 'foo/index.html' '//meta[@name="description"]/@content' \ +// 'API documentation for the Rust `foo` crate.' + +// @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 {} +} + +// @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() {} diff --git a/src/test/ui/error-codes/E0063.rs b/src/test/ui/error-codes/E0063.rs index 37fc0a2987d..58527cc0c5d 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 5d366e0c1c4..5dc4927071b 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 fb54b36940d..b94278bfdd2 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 33dbd85032e..b8c7d4f23a2 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/layout/hexagon-enum.rs b/src/test/ui/layout/hexagon-enum.rs new file mode 100644 index 00000000000..4bcfa58f7cf --- /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 00000000000..390eff6e5b9 --- /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 + diff --git a/src/test/ui/parser/issue-52496.rs b/src/test/ui/parser/issue-52496.rs index 4e945365373..05461f8b8c4 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 10fcc46f344..9dbf26ef4b6 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 58c40b3d96a..645abd9c719 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 cfb1f820147..bfb8a931b64 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