diff options
25 files changed, 285 insertions, 87 deletions
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 66941e49a9a..2a659a97db5 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -859,6 +859,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { |lint| { let mut err = lint.build(&format!("moving {} bytes", layout.size.bytes())); err.span_label(source_info.span, "value moved from here"); + err.note(&format!(r#"The current maximum size is {}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`"#, limit.bytes())); err.emit(); }, ); diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 6082cdb78e4..52fce7c0553 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -279,7 +279,6 @@ impl ToJson for Endian { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)] #[derive(HashStable_Generic)] pub struct Size { - // The top 3 bits are ALWAYS zero. raw: u64, } @@ -287,22 +286,9 @@ impl Size { pub const ZERO: Size = Size { raw: 0 }; /// Rounds `bits` up to the next-higher byte boundary, if `bits` is - /// is not aligned. + /// not a multiple of 8. pub fn from_bits(bits: impl TryInto<u64>) -> Size { let bits = bits.try_into().ok().unwrap(); - - #[cold] - fn overflow(bits: u64) -> ! { - panic!("Size::from_bits({}) has overflowed", bits); - } - - // This is the largest value of `bits` that does not cause overflow - // during rounding, and guarantees that the resulting number of bytes - // cannot cause overflow when multiplied by 8. - if bits > 0xffff_ffff_ffff_fff8 { - overflow(bits); - } - // Avoid potential overflow from `bits + 7`. Size { raw: bits / 8 + ((bits % 8) + 7) / 8 } } @@ -325,7 +311,12 @@ impl Size { #[inline] pub fn bits(self) -> u64 { - self.raw << 3 + #[cold] + fn overflow(bytes: u64) -> ! { + panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes) + } + + self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes())) } #[inline] diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index 468c7a3c55b..d83781170e8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2285,10 +2285,10 @@ impl<'v> Visitor<'v> for FindTypeParam { } } -pub fn recursive_type_with_infinite_size_error( - tcx: TyCtxt<'_>, +pub fn recursive_type_with_infinite_size_error<'tcx>( + tcx: TyCtxt<'tcx>, type_def_id: DefId, - spans: Vec<Span>, + spans: Vec<(Span, Option<hir::HirId>)>, ) { assert!(type_def_id.is_local()); let span = tcx.hir().span_if_local(type_def_id).unwrap(); @@ -2297,7 +2297,7 @@ pub fn recursive_type_with_infinite_size_error( let mut err = struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path); err.span_label(span, "recursive type has infinite size"); - for &span in &spans { + for &(span, _) in &spans { err.span_label(span, "recursive without indirection"); } let msg = format!( @@ -2305,16 +2305,25 @@ pub fn recursive_type_with_infinite_size_error( path, ); if spans.len() <= 4 { + // FIXME(compiler-errors): This suggestion might be erroneous if Box is shadowed err.multipart_suggestion( &msg, spans - .iter() - .flat_map(|&span| { - [ - (span.shrink_to_lo(), "Box<".to_string()), - (span.shrink_to_hi(), ">".to_string()), - ] - .into_iter() + .into_iter() + .flat_map(|(span, field_id)| { + if let Some(generic_span) = get_option_generic_from_field_id(tcx, field_id) { + // If we match an `Option` and can grab the span of the Option's generic, then + // suggest boxing the generic arg for a non-null niche optimization. + vec![ + (generic_span.shrink_to_lo(), "Box<".to_string()), + (generic_span.shrink_to_hi(), ">".to_string()), + ] + } else { + vec![ + (span.shrink_to_lo(), "Box<".to_string()), + (span.shrink_to_hi(), ">".to_string()), + ] + } }) .collect(), Applicability::HasPlaceholders, @@ -2325,6 +2334,34 @@ pub fn recursive_type_with_infinite_size_error( err.emit(); } +/// Extract the span for the generic type `T` of `Option<T>` in a field definition +fn get_option_generic_from_field_id(tcx: TyCtxt<'_>, field_id: Option<hir::HirId>) -> Option<Span> { + let node = tcx.hir().find(field_id?); + + // Expect a field from our field_id + let Some(hir::Node::Field(field_def)) = node + else { bug!("Expected HirId corresponding to FieldDef, found: {:?}", node) }; + + // Match a type that is a simple QPath with no Self + let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = &field_def.ty.kind + else { return None }; + + // Check if the path we're checking resolves to Option + let hir::def::Res::Def(_, did) = path.res + else { return None }; + + // Bail if this path doesn't describe `::core::option::Option` + if !tcx.is_diagnostic_item(sym::Option, did) { + return None; + } + + // Match a single generic arg in the 0th path segment + let generic_arg = path.segments.last()?.args?.args.get(0)?; + + // Take the span out of the type, if it's a type + if let hir::GenericArg::Type(generic_ty) = generic_arg { Some(generic_ty.span) } else { None } +} + /// Summarizes information #[derive(Clone)] pub enum ArgKind { diff --git a/compiler/rustc_ty_utils/src/representability.rs b/compiler/rustc_ty_utils/src/representability.rs index b8f3efe6462..7efc82efd15 100644 --- a/compiler/rustc_ty_utils/src/representability.rs +++ b/compiler/rustc_ty_utils/src/representability.rs @@ -17,12 +17,20 @@ use std::cmp; pub enum Representability { Representable, ContainsRecursive, - SelfRecursive(Vec<Span>), + /// Return a list of types that are included in themselves: + /// the spans where they are self-included, and (if found) + /// the HirId of the FieldDef that defines the self-inclusion. + SelfRecursive(Vec<(Span, Option<hir::HirId>)>), } /// Check whether a type is representable. This means it cannot contain unboxed /// structural recursion. This check is needed for structs and enums. -pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> Representability { +pub fn ty_is_representable<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, +) -> Representability { debug!("is_type_representable: {:?}", ty); // To avoid a stack overflow when checking an enum variant or struct that // contains a different, structurally recursive type, maintain a stack of @@ -38,11 +46,12 @@ pub fn ty_is_representable<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, sp: Span) -> R let mut force_result = false; let r = is_type_structurally_recursive( tcx, - sp, &mut seen, &mut shadow_seen, &mut representable_cache, ty, + sp, + field_id, &mut force_result, ); debug!("is_type_representable: {:?} is {:?}", ty, r); @@ -61,11 +70,12 @@ fn fold_repr<It: Iterator<Item = Representability>>(iter: It) -> Representabilit fn are_inner_types_recursive<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec<Ty<'tcx>>, shadow_seen: &mut Vec<ty::AdtDef<'tcx>>, representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, force_result: &mut bool, ) -> Representability { debug!("are_inner_types_recursive({:?}, {:?}, {:?})", ty, seen, shadow_seen); @@ -75,11 +85,12 @@ fn are_inner_types_recursive<'tcx>( fold_repr(fields.iter().map(|ty| { is_type_structurally_recursive( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ) })) @@ -88,20 +99,26 @@ fn are_inner_types_recursive<'tcx>( // FIXME(#11924) Behavior undecided for zero-length vectors. ty::Array(ty, _) => is_type_structurally_recursive( tcx, - sp, seen, shadow_seen, representable_cache, *ty, + sp, + field_id, force_result, ), ty::Adt(def, substs) => { // Find non representable fields with their spans fold_repr(def.all_fields().map(|field| { let ty = field.ty(tcx, substs); - let span = match field.did.as_local().and_then(|id| tcx.hir().find_by_def_id(id)) { - Some(hir::Node::Field(field)) => field.ty.span, - _ => sp, + let (sp, field_id) = match field + .did + .as_local() + .map(|id| tcx.hir().local_def_id_to_hir_id(id)) + .and_then(|id| tcx.hir().find(id)) + { + Some(hir::Node::Field(field)) => (field.ty.span, Some(field.hir_id)), + _ => (sp, field_id), }; let mut result = None; @@ -130,7 +147,7 @@ fn are_inner_types_recursive<'tcx>( // result without adjusting). if shadow_seen.len() > seen.len() && shadow_seen.first() == Some(def) { *force_result = true; - result = Some(Representability::SelfRecursive(vec![span])); + result = Some(Representability::SelfRecursive(vec![(sp, field_id)])); } if result == None { @@ -161,16 +178,17 @@ fn are_inner_types_recursive<'tcx>( result = Some( match is_type_structurally_recursive( tcx, - span, &mut nested_seen, shadow_seen, representable_cache, raw_adt_ty, + sp, + field_id, force_result, ) { Representability::SelfRecursive(_) => { if *force_result { - Representability::SelfRecursive(vec![span]) + Representability::SelfRecursive(vec![(sp, field_id)]) } else { Representability::ContainsRecursive } @@ -208,15 +226,16 @@ fn are_inner_types_recursive<'tcx>( result = Some( match is_type_structurally_recursive( tcx, - span, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ) { Representability::SelfRecursive(_) => { - Representability::SelfRecursive(vec![span]) + Representability::SelfRecursive(vec![(sp, field_id)]) } x => x, }, @@ -247,29 +266,31 @@ fn same_adt<'tcx>(ty: Ty<'tcx>, def: ty::AdtDef<'tcx>) -> bool { // contain any types on stack `seen`? fn is_type_structurally_recursive<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec<Ty<'tcx>>, shadow_seen: &mut Vec<ty::AdtDef<'tcx>>, representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, force_result: &mut bool, ) -> Representability { - debug!("is_type_structurally_recursive: {:?} {:?}", ty, sp); + debug!("is_type_structurally_recursive: {:?} {:?} {:?}", ty, sp, field_id); if let Some(representability) = representable_cache.get(&ty) { debug!( - "is_type_structurally_recursive: {:?} {:?} - (cached) {:?}", - ty, sp, representability + "is_type_structurally_recursive: {:?} {:?} {:?} - (cached) {:?}", + ty, sp, field_id, representability ); return representability.clone(); } let representability = is_type_structurally_recursive_inner( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ); @@ -279,11 +300,12 @@ fn is_type_structurally_recursive<'tcx>( fn is_type_structurally_recursive_inner<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec<Ty<'tcx>>, shadow_seen: &mut Vec<ty::AdtDef<'tcx>>, representable_cache: &mut FxHashMap<Ty<'tcx>, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option<hir::HirId>, force_result: &mut bool, ) -> Representability { match ty.kind() { @@ -305,7 +327,7 @@ fn is_type_structurally_recursive_inner<'tcx>( if let Some(&seen_adt) = iter.next() { if same_adt(seen_adt, *def) { debug!("SelfRecursive: {:?} contains {:?}", seen_adt, ty); - return Representability::SelfRecursive(vec![sp]); + return Representability::SelfRecursive(vec![(sp, field_id)]); } } @@ -335,11 +357,12 @@ fn is_type_structurally_recursive_inner<'tcx>( shadow_seen.push(*def); let out = are_inner_types_recursive( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ); shadow_seen.pop(); @@ -350,11 +373,12 @@ fn is_type_structurally_recursive_inner<'tcx>( // No need to push in other cases. are_inner_types_recursive( tcx, - sp, seen, shadow_seen, representable_cache, ty, + sp, + field_id, force_result, ) } diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 5362ca8d719..7cb478d7888 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -1045,7 +1045,7 @@ pub(super) fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalD // recursive type. It is only necessary to throw an error on those that // contain themselves. For case 2, there must be an inner type that will be // caught by case 1. - match representability::ty_is_representable(tcx, rty, sp) { + match representability::ty_is_representable(tcx, rty, sp, None) { Representability::SelfRecursive(spans) => { recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans); return false; diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index a9edec80540..c11a35ab947 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -65,9 +65,10 @@ //! For reference, the `std` library requires `AtomicBool`s and pointer-sized atomics, although //! `core` does not. //! -//! Currently you'll need to use `#[cfg(target_arch)]` primarily to -//! conditionally compile in code with atomics. There is an unstable -//! `#[cfg(target_has_atomic)]` as well which may be stabilized in the future. +//! The `#[cfg(target_has_atomic)]` attribute can be used to conditionally +//! compile based on the target's supported bit widths. It is a key-value +//! option set for each supported size, with values "8", "16", "32", "64", +//! "128", and "ptr" for pointer-sized atomics. //! //! [lock-free]: https://en.wikipedia.org/wiki/Non-blocking_algorithm //! diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index be70d00cb1a..bb4e4ee9aa7 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -522,7 +522,7 @@ pub mod guard { // new thread stack_ptr.addr() - current_stack.ss_size }; - Some(stack_ptr.with_addr(stack_addr)) + Some(stack_ptr.with_addr(stackaddr)) } #[cfg(any( diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c8b76809aba..339b7a8d1e6 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1998,7 +1998,6 @@ impl Step for Crate { compile::std_cargo(builder, target, compiler.stage, &mut cargo); } Mode::Rustc => { - builder.ensure(compile::Rustc { compiler, target }); compile::rustc_cargo(builder, &mut cargo, target); } _ => panic!("can only test libraries"), diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6c9a5a955d7..1223b6c8002 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -465,7 +465,7 @@ fn extra_info_tags(item: &clean::Item, parent: &clean::Item, tcx: TyCtxt<'_>) -> fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) { let header = it.fn_header(cx.tcx()).expect("printing a function which isn't a function"); let constness = print_constness_with_space(&header.constness, it.const_stability(cx.tcx())); - let unsafety = header.unsafety.print_with_space().to_string(); + let unsafety = header.unsafety.print_with_space(); let abi = print_abi_with_space(header.abi).to_string(); let asyncness = header.asyncness.print_with_space(); let visibility = it.visibility.print_with_space(it.def_id, cx).to_string(); diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml index 823ea67b1b0..ff792eced70 100644 --- a/src/test/rustdoc-gui/search-result-display.goml +++ b/src/test/rustdoc-gui/search-result-display.goml @@ -2,8 +2,7 @@ goto: file://|DOC_PATH|/test_docs/index.html size: (900, 1000) write: (".search-input", "test") -// Waiting for the search results to appear... -wait-for: "#titles" +wait-for: "#search-settings" // The width is returned by "getComputedStyle" which returns the exact number instead of the // CSS rule which is "50%"... assert-css: (".search-results div.desc", {"width": "295px"}) diff --git a/src/test/ui/async-await/large_moves.attribute.stderr b/src/test/ui/async-await/large_moves.attribute.stderr index 39b7e7cb345..8d3f0b77f43 100644 --- a/src/test/ui/async-await/large_moves.attribute.stderr +++ b/src/test/ui/async-await/large_moves.attribute.stderr @@ -15,24 +15,31 @@ note: the lint level is defined here | LL | #![deny(large_assignments)] | ^^^^^^^^^^^^^^^^^ + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: moving 10024 bytes --> $DIR/large_moves.rs:18:14 | LL | let z = (x, 42); | ^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: moving 10024 bytes --> $DIR/large_moves.rs:18:13 | LL | let z = (x, 42); | ^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: moving 10024 bytes --> $DIR/large_moves.rs:20:13 | LL | let a = z.0; | ^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: aborting due to 4 previous errors diff --git a/src/test/ui/async-await/large_moves.option.stderr b/src/test/ui/async-await/large_moves.option.stderr index 39b7e7cb345..8d3f0b77f43 100644 --- a/src/test/ui/async-await/large_moves.option.stderr +++ b/src/test/ui/async-await/large_moves.option.stderr @@ -15,24 +15,31 @@ note: the lint level is defined here | LL | #![deny(large_assignments)] | ^^^^^^^^^^^^^^^^^ + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: moving 10024 bytes --> $DIR/large_moves.rs:18:14 | LL | let z = (x, 42); | ^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: moving 10024 bytes --> $DIR/large_moves.rs:18:13 | LL | let z = (x, 42); | ^^^^^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: moving 10024 bytes --> $DIR/large_moves.rs:20:13 | LL | let a = z.0; | ^^^ value moved from here + | + = note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr index 4d739a3823b..db32eb952ba 100644 --- a/src/test/ui/issues/issue-17431-1.stderr +++ b/src/test/ui/issues/issue-17431-1.stderr @@ -8,8 +8,8 @@ LL | struct Foo { foo: Option<Option<Foo>> } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { foo: Box<Option<Option<Foo>>> } - | ++++ + +LL | struct Foo { foo: Option<Box<Option<Foo>>> } + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr index e53134c5238..d23fd1474ac 100644 --- a/src/test/ui/issues/issue-17431-2.stderr +++ b/src/test/ui/issues/issue-17431-2.stderr @@ -8,8 +8,8 @@ LL | struct Baz { q: Option<Foo> } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable | -LL | struct Baz { q: Box<Option<Foo>> } - | ++++ + +LL | struct Baz { q: Option<Box<Foo>> } + | ++++ + error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-2.rs:4:1 @@ -21,8 +21,8 @@ LL | struct Foo { q: Option<Baz> } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { q: Box<Option<Baz>> } - | ++++ + +LL | struct Foo { q: Option<Box<Baz>> } + | ++++ + error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr index f5aeeec7337..ddf669b8fd1 100644 --- a/src/test/ui/issues/issue-17431-4.stderr +++ b/src/test/ui/issues/issue-17431-4.stderr @@ -8,8 +8,8 @@ LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> } - | ++++ + +LL | struct Foo<T> { foo: Option<Box<Option<Foo<T>>>>, marker: marker::PhantomData<T> } + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr index aeaadaa6917..6f8a7e3867b 100644 --- a/src/test/ui/issues/issue-17431-7.stderr +++ b/src/test/ui/issues/issue-17431-7.stderr @@ -8,8 +8,8 @@ LL | enum Foo { Voo(Option<Option<Foo>>) } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | enum Foo { Voo(Box<Option<Option<Foo>>>) } - | ++++ + +LL | enum Foo { Voo(Option<Box<Option<Foo>>>) } + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr index 6a21472848a..e853d0f8c89 100644 --- a/src/test/ui/issues/issue-3779.stderr +++ b/src/test/ui/issues/issue-3779.stderr @@ -9,8 +9,8 @@ LL | element: Option<S> | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable | -LL | element: Box<Option<S>> - | ++++ + +LL | element: Option<Box<S>> + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr index 0726b16a919..536510814c5 100644 --- a/src/test/ui/sized-cycle-note.stderr +++ b/src/test/ui/sized-cycle-note.stderr @@ -8,8 +8,8 @@ LL | struct Baz { q: Option<Foo> } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable | -LL | struct Baz { q: Box<Option<Foo>> } - | ++++ + +LL | struct Baz { q: Option<Box<Foo>> } + | ++++ + error[E0072]: recursive type `Foo` has infinite size --> $DIR/sized-cycle-note.rs:11:1 @@ -21,8 +21,8 @@ LL | struct Foo { q: Option<Baz> } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { q: Box<Option<Baz>> } - | ++++ + +LL | struct Foo { q: Option<Box<Baz>> } + | ++++ + error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 98e92751360..882ed577cf3 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -9,8 +9,8 @@ LL | tail: Option<ListNode>, | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable | -LL | tail: Box<Option<ListNode>>, - | ++++ + +LL | tail: Option<Box<ListNode>>, + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr index cb71a55b09e..acfc60b51f3 100644 --- a/src/test/ui/span/multiline-span-E0072.stderr +++ b/src/test/ui/span/multiline-span-E0072.stderr @@ -12,8 +12,8 @@ LL | | } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable | -LL | tail: Box<Option<ListNode>>, - | ++++ + +LL | tail: Option<Box<ListNode>>, + | ++++ + error: aborting due to previous error diff --git a/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr b/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr index c6d2434e424..80a494f3f65 100644 --- a/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr +++ b/src/test/ui/structs-enums/struct-rec/mutual-struct-recursion.stderr @@ -37,8 +37,8 @@ LL | y: Option<Option<D<T>>>, | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `C` representable | -LL | y: Box<Option<Option<D<T>>>>, - | ++++ + +LL | y: Option<Box<Option<D<T>>>>, + | ++++ + error[E0072]: recursive type `D` has infinite size --> $DIR/mutual-struct-recursion.rs:18:1 @@ -51,8 +51,8 @@ LL | z: Option<Option<C<T>>>, | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `D` representable | -LL | z: Box<Option<Option<C<T>>>>, - | ++++ + +LL | z: Option<Box<Option<C<T>>>>, + | ++++ + error: aborting due to 4 previous errors diff --git a/src/test/ui/type/type-recursive-box-shadowed.rs b/src/test/ui/type/type-recursive-box-shadowed.rs new file mode 100644 index 00000000000..e141c2149ff --- /dev/null +++ b/src/test/ui/type/type-recursive-box-shadowed.rs @@ -0,0 +1,12 @@ +//FIXME(compiler-errors): This fixup should suggest the full box path, not just `Box` + +struct Box<T> { + t: T, +} + +struct Foo { + //~^ ERROR recursive type `Foo` has infinite size + inner: Foo, +} + +fn main() {} diff --git a/src/test/ui/type/type-recursive-box-shadowed.stderr b/src/test/ui/type/type-recursive-box-shadowed.stderr new file mode 100644 index 00000000000..c22d848f379 --- /dev/null +++ b/src/test/ui/type/type-recursive-box-shadowed.stderr @@ -0,0 +1,17 @@ +error[E0072]: recursive type `Foo` has infinite size + --> $DIR/type-recursive-box-shadowed.rs:7:1 + | +LL | struct Foo { + | ^^^^^^^^^^ recursive type has infinite size +LL | +LL | inner: Foo, + | --- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable + | +LL | inner: Box<Foo>, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. diff --git a/src/test/ui/type/type-recursive.rs b/src/test/ui/type/type-recursive.rs index 8558f761ee8..e8084f0d082 100644 --- a/src/test/ui/type/type-recursive.rs +++ b/src/test/ui/type/type-recursive.rs @@ -1,6 +1,30 @@ struct T1 { //~ ERROR E0072 foo: isize, - foolish: T1 + foolish: T1, +} + +struct T2 { //~ ERROR E0072 + inner: Option<T2>, +} + +type OptionT3 = Option<T3>; + +struct T3 { //~ ERROR E0072 + inner: OptionT3, +} + +struct T4(Option<T4>); //~ ERROR E0072 + +enum T5 { //~ ERROR E0072 + Variant(Option<T5>), +} + +enum T6 { //~ ERROR E0072 + Variant{ field: Option<T6> }, +} + +struct T7 { //~ ERROR E0072 + foo: std::cell::Cell<Option<T7>>, } fn main() { } diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr index 5a94a0fd683..04392f7390d 100644 --- a/src/test/ui/type/type-recursive.stderr +++ b/src/test/ui/type/type-recursive.stderr @@ -4,14 +4,93 @@ error[E0072]: recursive type `T1` has infinite size LL | struct T1 { | ^^^^^^^^^ recursive type has infinite size LL | foo: isize, -LL | foolish: T1 +LL | foolish: T1, | -- recursive without indirection | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable | -LL | foolish: Box<T1> +LL | foolish: Box<T1>, | ++++ + -error: aborting due to previous error +error[E0072]: recursive type `T2` has infinite size + --> $DIR/type-recursive.rs:6:1 + | +LL | struct T2 { + | ^^^^^^^^^ recursive type has infinite size +LL | inner: Option<T2>, + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T2` representable + | +LL | inner: Option<Box<T2>>, + | ++++ + + +error[E0072]: recursive type `T3` has infinite size + --> $DIR/type-recursive.rs:12:1 + | +LL | struct T3 { + | ^^^^^^^^^ recursive type has infinite size +LL | inner: OptionT3, + | -------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T3` representable + | +LL | inner: Box<OptionT3>, + | ++++ + + +error[E0072]: recursive type `T4` has infinite size + --> $DIR/type-recursive.rs:16:1 + | +LL | struct T4(Option<T4>); + | ^^^^^^^^^^----------^^ + | | | + | | recursive without indirection + | recursive type has infinite size + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T4` representable + | +LL | struct T4(Option<Box<T4>>); + | ++++ + + +error[E0072]: recursive type `T5` has infinite size + --> $DIR/type-recursive.rs:18:1 + | +LL | enum T5 { + | ^^^^^^^ recursive type has infinite size +LL | Variant(Option<T5>), + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T5` representable + | +LL | Variant(Option<Box<T5>>), + | ++++ + + +error[E0072]: recursive type `T6` has infinite size + --> $DIR/type-recursive.rs:22:1 + | +LL | enum T6 { + | ^^^^^^^ recursive type has infinite size +LL | Variant{ field: Option<T6> }, + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T6` representable + | +LL | Variant{ field: Option<Box<T6>> }, + | ++++ + + +error[E0072]: recursive type `T7` has infinite size + --> $DIR/type-recursive.rs:26:1 + | +LL | struct T7 { + | ^^^^^^^^^ recursive type has infinite size +LL | foo: std::cell::Cell<Option<T7>>, + | --------------------------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T7` representable + | +LL | foo: Box<std::cell::Cell<Option<T7>>>, + | ++++ + + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0072`. |
