From 182d4b32d506bb061f30069fcb38090c11f08775 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 27 Mar 2022 15:13:17 -0700 Subject: [PATCH 1/7] Update target_has_atomic documentation for stabilization --- library/core/src/sync/atomic.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index a9edec80540dd..c11a35ab947a8 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 //! From d7cada17670c03c7029441e17381845bbe8fa3cc Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 31 Mar 2022 12:50:53 +0200 Subject: [PATCH 2/7] obligation cause: `RepeatVec` -> `RepeatValueCopy` --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +++- compiler/rustc_middle/src/traits/mod.rs | 11 ++++++----- compiler/rustc_mir_build/src/thir/pattern/mod.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 7dc292ffb6579..e9fa33f656f31 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1899,7 +1899,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ObligationCause::new( span, self.tcx().hir().local_def_id_to_hir_id(def_id), - traits::ObligationCauseCode::RepeatVec(is_const_fn), + traits::ObligationCauseCode::RepeatElementCopy { + is_const_fn, + }, ), self.param_env, ty::Binder::dummy(ty::TraitRef::new( diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 3d0a0d2a58e1f..1f18260d9154f 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -236,11 +236,12 @@ pub enum ObligationCauseCode<'tcx> { SizedBoxType, /// Inline asm operand type must be `Sized`. InlineAsmSized, - /// `[T, ..n]` implies that `T` must be `Copy`. - /// If the function in the array repeat expression is a `const fn`, - /// display a help message suggesting to move the function call to a - /// new `const` item while saying that `T` doesn't implement `Copy`. - RepeatVec(bool), + /// `[expr; N]` requires `type_of(expr): Copy`. + RepeatElementCopy { + /// If element is a `const fn` we display a help message suggesting to move the + /// function call to a new `const` item while saying that `T` doesn't implement `Copy`. + is_const_fn: bool, + }, /// Types of fields (other than the last, except for packed structs) in a struct must be sized. FieldSized { diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 57aec86785657..72b597bb13d29 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -198,7 +198,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let kind = match pat.kind { hir::PatKind::Wild => PatKind::Wild, - hir::PatKind::Lit(ref value) => self.lower_lit(value), + hir::PatKind::Lit(value) => self.lower_lit(value), hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => { let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref()); diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 505d78d800a3a..58e002b336081 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -1988,7 +1988,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ObligationCauseCode::Coercion { source: _, target } => { err.note(&format!("required by cast to type `{}`", self.ty_to_string(target))); } - ObligationCauseCode::RepeatVec(is_const_fn) => { + ObligationCauseCode::RepeatElementCopy { is_const_fn } => { err.note( "the `Copy` trait is required because the repeated element will be copied", ); From 89c66eb42d385975c91d79de139b50c298414d71 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 31 Mar 2022 15:41:52 +0200 Subject: [PATCH 3/7] update comment --- .../rustc_borrowck/src/type_check/free_region_relations.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs index 0b9d0a0e9220b..f8439d2e16355 100644 --- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs +++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs @@ -253,8 +253,10 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> { let constraint_sets: Vec<_> = unnormalized_input_output_tys .flat_map(|ty| { debug!("build: input_or_output={:?}", ty); - // We add implied bounds from both the unnormalized and normalized ty - // See issue #87748 + // We only add implied bounds for the normalized type as the unnormalized + // type may not actually get checked by the caller. + // + // Can otherwise be unsound, see #91068. let TypeOpOutput { output: norm_ty, constraints: constraints1, .. } = self .param_env .and(type_op::normalize::Normalize::new(ty)) From bd49581dcf7dc5ed85dcd1e721daf1e0c90f0545 Mon Sep 17 00:00:00 2001 From: bstrie <865233+bstrie@users.noreply.github.com> Date: Thu, 31 Mar 2022 09:56:36 -0400 Subject: [PATCH 4/7] Fix typos in core::ptr docs --- library/core/src/ptr/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index 6a7841d3de6af..68d80022b4c80 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -84,7 +84,7 @@ //! have to change, and is it worse or better now? Would any patterns become truly inexpressible? //! Could we carve out special exceptions for those patterns? Should we? //! -//! A secondary goal of this project is to see if we can disamiguate the many functions of +//! A secondary goal of this project is to see if we can disambiguate the many functions of //! pointer<->integer casts enough for the definition of `usize` to be loosened so that it //! isn't *pointer*-sized but address-space/offset/allocation-sized (we'll probably continue //! to conflate these notions). This would potentially make it possible to more efficiently @@ -163,7 +163,7 @@ //! of pointers and `usize` (and `isize`), and defining a pointer to semantically contain the //! following information: //! -//! * The **address-space** it is part of (i.e. "data" vs "code" in WASM). +//! * The **address-space** it is part of (e.g. "data" vs "code" in WASM). //! * The **address** it points to, which can be represented by a `usize`. //! * The **provenance** it has, defining the memory it has permission to access. //! @@ -246,7 +246,7 @@ //! be using AtomicPtr instead. If that messes up the way you atomically manipulate pointers, //! we would like to know why, and what needs to be done to fix it.) //! -//! Something more complicated and just generally *evil* like a XOR-List requires more significant +//! Something more complicated and just generally *evil* like an XOR-List requires more significant //! changes like allocating all nodes in a pre-allocated Vec or Arena and using a pointer //! to the whole allocation to reconstitute the XORed addresses. //! @@ -257,7 +257,7 @@ //! special attention at all, because they're generally accessing memory outside the scope of //! "the abstract machine", or already using "I know what I'm doing" annotations like "volatile". //! -//! Under [Strict Provenance] is is Undefined Behaviour to: +//! Under [Strict Provenance] it is Undefined Behaviour to: //! //! * Access memory through a pointer that does not have provenance over that memory. //! From de04c05dea10fc03cb626338ce1d55f4c90f58b0 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 30 Nov 2021 21:30:05 -0800 Subject: [PATCH 5/7] Specialize suggestion for Option --- .../src/traits/error_reporting/mod.rs | 63 +++++++++++--- .../rustc_ty_utils/src/representability.rs | 70 ++++++++++----- compiler/rustc_typeck/src/check/check.rs | 2 +- src/test/ui/issues/issue-17431-1.stderr | 4 +- src/test/ui/issues/issue-17431-2.stderr | 8 +- src/test/ui/issues/issue-17431-4.stderr | 4 +- src/test/ui/issues/issue-17431-7.stderr | 4 +- src/test/ui/issues/issue-3779.stderr | 4 +- src/test/ui/sized-cycle-note.stderr | 8 +- src/test/ui/span/E0072.stderr | 4 +- src/test/ui/span/multiline-span-E0072.stderr | 4 +- .../struct-rec/mutual-struct-recursion.stderr | 8 +- src/test/ui/type/type-recursive.rs | 26 +++++- src/test/ui/type/type-recursive.stderr | 85 ++++++++++++++++++- 14 files changed, 231 insertions(+), 63 deletions(-) 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 468c7a3c55b36..53acffc5098ed 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, + spans: Vec<(Span, Option)>, ) { 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: This suggestion might be erroneous if Option or Box are 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,38 @@ pub fn recursive_type_with_infinite_size_error( err.emit(); } +/// Extract the span for the generic type `T` of `Option` in a field definition +fn get_option_generic_from_field_id(tcx: TyCtxt<'_>, field_id: Option) -> Option { + 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.get(0)?.args?.args.get(0); + + // Take the span out of the type, if it's a type + if let Some(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 b8f3efe6462ea..7efc82efd15c3 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), + /// 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)>), } /// 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, +) -> 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>(iter: It) -> Representabilit fn are_inner_types_recursive<'tcx>( tcx: TyCtxt<'tcx>, - sp: Span, seen: &mut Vec>, shadow_seen: &mut Vec>, representable_cache: &mut FxHashMap, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option, 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>, shadow_seen: &mut Vec>, representable_cache: &mut FxHashMap, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option, 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>, shadow_seen: &mut Vec>, representable_cache: &mut FxHashMap, Representability>, ty: Ty<'tcx>, + sp: Span, + field_id: Option, 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 5362ca8d71978..7cb478d78880a 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/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr index 4d739a3823b10..db32eb952ba79 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> } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { foo: Box>> } - | ++++ + +LL | struct Foo { foo: Option>> } + | ++++ + 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 e53134c5238c6..d23fd1474ac12 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 } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable | -LL | struct Baz { q: Box> } - | ++++ + +LL | struct Baz { q: Option> } + | ++++ + error[E0072]: recursive type `Foo` has infinite size --> $DIR/issue-17431-2.rs:4:1 @@ -21,8 +21,8 @@ LL | struct Foo { q: Option } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { q: Box> } - | ++++ + +LL | struct Foo { q: Option> } + | ++++ + 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 f5aeeec733711..ddf669b8fd1cb 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 { foo: Option>>, marker: marker::PhantomData | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { foo: Box>>>, marker: marker::PhantomData } - | ++++ + +LL | struct Foo { foo: Option>>>, marker: marker::PhantomData } + | ++++ + 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 aeaadaa69175e..6f8a7e3867b09 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>) } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | enum Foo { Voo(Box>>) } - | ++++ + +LL | enum Foo { Voo(Option>>) } + | ++++ + 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 6a21472848a74..e853d0f8c8932 100644 --- a/src/test/ui/issues/issue-3779.stderr +++ b/src/test/ui/issues/issue-3779.stderr @@ -9,8 +9,8 @@ LL | element: Option | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable | -LL | element: Box> - | ++++ + +LL | element: Option> + | ++++ + 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 0726b16a91948..536510814c57c 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 } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable | -LL | struct Baz { q: Box> } - | ++++ + +LL | struct Baz { q: Option> } + | ++++ + error[E0072]: recursive type `Foo` has infinite size --> $DIR/sized-cycle-note.rs:11:1 @@ -21,8 +21,8 @@ LL | struct Foo { q: Option } | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable | -LL | struct Foo { q: Box> } - | ++++ + +LL | struct Foo { q: Option> } + | ++++ + error: aborting due to 2 previous errors diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr index 98e92751360cf..882ed577cf366 100644 --- a/src/test/ui/span/E0072.stderr +++ b/src/test/ui/span/E0072.stderr @@ -9,8 +9,8 @@ LL | tail: Option, | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable | -LL | tail: Box>, - | ++++ + +LL | tail: Option>, + | ++++ + 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 cb71a55b09eaf..acfc60b51f330 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>, - | ++++ + +LL | tail: Option>, + | ++++ + 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 c6d2434e424b1..80a494f3f65eb 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>>, | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `C` representable | -LL | y: Box>>>, - | ++++ + +LL | y: Option>>>, + | ++++ + error[E0072]: recursive type `D` has infinite size --> $DIR/mutual-struct-recursion.rs:18:1 @@ -51,8 +51,8 @@ LL | z: Option>>, | help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `D` representable | -LL | z: Box>>>, - | ++++ + +LL | z: Option>>>, + | ++++ + error: aborting due to 4 previous errors diff --git a/src/test/ui/type/type-recursive.rs b/src/test/ui/type/type-recursive.rs index 8558f761ee8f5..e8084f0d0826a 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, +} + +type OptionT3 = Option; + +struct T3 { //~ ERROR E0072 + inner: OptionT3, +} + +struct T4(Option); //~ ERROR E0072 + +enum T5 { //~ ERROR E0072 + Variant(Option), +} + +enum T6 { //~ ERROR E0072 + Variant{ field: Option }, +} + +struct T7 { //~ ERROR E0072 + foo: std::cell::Cell>, } fn main() { } diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr index 5a94a0fd6831a..04392f7390dfc 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 +LL | foolish: Box, | ++++ + -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, + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T2` representable + | +LL | inner: Option>, + | ++++ + + +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, + | ++++ + + +error[E0072]: recursive type `T4` has infinite size + --> $DIR/type-recursive.rs:16:1 + | +LL | struct T4(Option); + | ^^^^^^^^^^----------^^ + | | | + | | 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>); + | ++++ + + +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), + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T5` representable + | +LL | Variant(Option>), + | ++++ + + +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 }, + | ---------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T6` representable + | +LL | Variant{ field: Option> }, + | ++++ + + +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>, + | --------------------------- recursive without indirection + | +help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T7` representable + | +LL | foo: Box>>, + | ++++ + + +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0072`. From c74f7a310fe8fcf9a2edf927cee0bc15a3abe399 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 17 Feb 2022 19:49:45 -0800 Subject: [PATCH 6/7] address comments, add test for shadowed Box type --- .../src/traits/error_reporting/mod.rs | 10 +++------- src/test/ui/type/type-recursive-box-shadowed.rs | 12 ++++++++++++ .../ui/type/type-recursive-box-shadowed.stderr | 17 +++++++++++++++++ 3 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/type/type-recursive-box-shadowed.rs create mode 100644 src/test/ui/type/type-recursive-box-shadowed.stderr 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 53acffc5098ed..d83781170e8c3 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2305,7 +2305,7 @@ pub fn recursive_type_with_infinite_size_error<'tcx>( path, ); if spans.len() <= 4 { - // FIXME: This suggestion might be erroneous if Option or Box are shadowed + // FIXME(compiler-errors): This suggestion might be erroneous if Box is shadowed err.multipart_suggestion( &msg, spans @@ -2356,14 +2356,10 @@ fn get_option_generic_from_field_id(tcx: TyCtxt<'_>, field_id: Option { + 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 0000000000000..c22d848f3797e --- /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, + | ++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0072`. From a5c68d747e1bc787ddb38f95d7e9fac9e68c33ca Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 31 Mar 2022 16:52:47 +0200 Subject: [PATCH 7/7] remove unused field from `infcx` --- compiler/rustc_infer/src/infer/at.rs | 1 - compiler/rustc_infer/src/infer/mod.rs | 27 ++------------------ compiler/rustc_typeck/src/check/inherited.rs | 7 ----- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- 4 files changed, 3 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_infer/src/infer/at.rs b/compiler/rustc_infer/src/infer/at.rs index 71ee4f1e76d6d..09b02ba74a8de 100644 --- a/compiler/rustc_infer/src/infer/at.rs +++ b/compiler/rustc_infer/src/infer/at.rs @@ -65,7 +65,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { Self { tcx: self.tcx.clone(), defining_use_anchor: self.defining_use_anchor.clone(), - reveal_defining_opaque_types: self.reveal_defining_opaque_types.clone(), in_progress_typeck_results: self.in_progress_typeck_results.clone(), inner: self.inner.clone(), skip_leak_check: self.skip_leak_check.clone(), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index a9b4451e77b08..bd59bf4dea883 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -290,10 +290,6 @@ pub struct InferCtxt<'a, 'tcx> { /// to the outside until the end up in an `InferCtxt` for typeck or borrowck. pub defining_use_anchor: Option, - /// Used by WF-checking to not have to figure out hidden types itself, but - /// to just invoke type_of to get the already computed hidden type from typeck. - pub reveal_defining_opaque_types: bool, - /// During type-checking/inference of a body, `in_progress_typeck_results` /// contains a reference to the typeck results being built up, which are /// used for reading closure kinds/signatures as they are inferred, @@ -569,7 +565,6 @@ pub struct InferCtxtBuilder<'tcx> { tcx: TyCtxt<'tcx>, fresh_typeck_results: Option>>, defining_use_anchor: Option, - reveal_defining_opaque_types: bool, } pub trait TyCtxtInferExt<'tcx> { @@ -578,12 +573,7 @@ pub trait TyCtxtInferExt<'tcx> { impl<'tcx> TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { - InferCtxtBuilder { - tcx: self, - defining_use_anchor: None, - fresh_typeck_results: None, - reveal_defining_opaque_types: false, - } + InferCtxtBuilder { tcx: self, defining_use_anchor: None, fresh_typeck_results: None } } } @@ -607,13 +597,6 @@ impl<'tcx> InferCtxtBuilder<'tcx> { self } - /// WF-checking doesn't need to recompute opaque types and can instead use - /// the type_of query to get them from typeck. - pub fn reveal_defining_opaque_types(mut self) -> Self { - self.reveal_defining_opaque_types = true; - self - } - /// Given a canonical value `C` as a starting point, create an /// inference context that contains each of the bound values /// within instantiated as a fresh variable. The `f` closure is @@ -638,17 +621,11 @@ impl<'tcx> InferCtxtBuilder<'tcx> { } pub fn enter(&mut self, f: impl for<'a> FnOnce(InferCtxt<'a, 'tcx>) -> R) -> R { - let InferCtxtBuilder { - tcx, - defining_use_anchor, - reveal_defining_opaque_types, - ref fresh_typeck_results, - } = *self; + let InferCtxtBuilder { tcx, defining_use_anchor, ref fresh_typeck_results } = *self; let in_progress_typeck_results = fresh_typeck_results.as_ref(); f(InferCtxt { tcx, defining_use_anchor, - reveal_defining_opaque_types, in_progress_typeck_results, inner: RefCell::new(InferCtxtInner::new()), lexical_region_resolutions: RefCell::new(None), diff --git a/compiler/rustc_typeck/src/check/inherited.rs b/compiler/rustc_typeck/src/check/inherited.rs index b775f24f8efd8..e7cfa3a7c1493 100644 --- a/compiler/rustc_typeck/src/check/inherited.rs +++ b/compiler/rustc_typeck/src/check/inherited.rs @@ -95,13 +95,6 @@ impl<'tcx> InheritedBuilder<'tcx> { let def_id = self.def_id; self.infcx.enter(|infcx| f(Inherited::new(infcx, def_id))) } - - /// WF-checking doesn't need to recompute opaque types and can instead use - /// the type_of query to get them from typeck. - pub fn reveal_defining_opaque_types(mut self) -> Self { - self.infcx = self.infcx.reveal_defining_opaque_types(); - self - } } impl<'a, 'tcx> Inherited<'a, 'tcx> { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5b3aee7428829..bd08da9529a5f 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -968,7 +968,7 @@ fn for_item<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'_>) -> CheckWfFcxBuilder< fn for_id(tcx: TyCtxt<'_>, def_id: LocalDefId, span: Span) -> CheckWfFcxBuilder<'_> { CheckWfFcxBuilder { - inherited: Inherited::build(tcx, def_id).reveal_defining_opaque_types(), + inherited: Inherited::build(tcx, def_id), id: hir::HirId::make_owner(def_id), span, param_env: tcx.param_env(def_id),