diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index b3fa786a5177c..bc4593cae8fde 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -208,11 +208,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .unwrap_or_else(|_| bug!("struct tail should have been computable, since we computed it in HIR")) }; - let tail = tcx.struct_tail_raw( - ty, - structurally_normalize, - || {}, - ); + let tail = tcx.struct_tail_raw(ty, structurally_normalize, || {}, ObligationCause::dummy()); + Ok(tail) }, @@ -222,7 +219,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .unwrap_or_else(|guar| Ty::new_error(tcx, guar)) } else { let mut normalize = |ty| self.normalize(ty, location); - let tail = tcx.struct_tail_raw(ty, &mut normalize, || {}); + let tail = tcx.struct_tail_raw(ty, &mut normalize, || {}, ObligationCause::dummy()); normalize(tail) } } diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index 3776fb55c2e5f..e981c424fb015 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -11,6 +11,7 @@ use super::eval_queries::{mk_eval_cx_to_read_const_val, op_to_const}; use super::machine::CompileTimeInterpCx; use super::{VALTREE_MAX_NODES, ValTreeCreationError, ValTreeCreationResult}; use crate::const_eval::CanAccessMutGlobal; +use rustc_infer::traits::ObligationCause; use crate::errors::MaxNumNodesInConstErr; use crate::interpret::{ ImmTy, Immediate, InternKind, MPlaceTy, MemPlaceMeta, MemoryKind, PlaceTy, Projectable, Scalar, @@ -203,7 +204,9 @@ fn reconstruct_place_meta<'tcx>( last_valtree = *branches.last().unwrap(); debug!(?branches, ?last_valtree); }, + ObligationCause::dummy() ); + // Sanity-check that we got a tail we support. match tail.kind() { ty::Slice(..) | ty::Str => {} diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index a266286664cc2..e5a67c26463a3 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -34,6 +34,8 @@ use tracing::{debug, instrument}; use ty::TypingMode; use {rustc_attr_parsing as attr, rustc_hir as hir}; +use crate::traits::ObligationCause; + use super::compare_impl_item::check_type_bounds; use super::*; @@ -969,6 +971,7 @@ fn check_impl_items_against_trait<'tcx>( }) }, || (), + ObligationCause::dummy() ) .kind() { diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs index 6d95b6917e296..488b3517d52ec 100644 --- a/compiler/rustc_hir_typeck/src/expectation.rs +++ b/compiler/rustc_hir_typeck/src/expectation.rs @@ -4,6 +4,8 @@ use rustc_span::Span; use super::Expectation::*; use super::FnCtxt; +use rustc_infer::traits::ObligationCause; + /// When type-checking an expression, we propagate downward /// whatever type hint we are able in the form of an `Expectation`. #[derive(Copy, Clone, Debug)] @@ -75,7 +77,8 @@ impl<'a, 'tcx> Expectation<'tcx> { /// for examples of where this comes up,. pub(super) fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { // FIXME: This is not right, even in the old solver... - match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}).kind() { + match fcx.tcx.struct_tail_raw(ty, |ty| ty, || {}, ObligationCause::dummy()).kind() + { ty::Slice(_) | ty::Str | ty::Dynamic(..) => ExpectRvalueLikeUnsized(ty), _ => ExpectHasType(ty), } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index c82f7a91168af..b77dd01ac3ea0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -38,6 +38,7 @@ use rustc_trait_selection::traits::{ }; use tracing::{debug, instrument}; +use rustc_infer::traits::ObligationCause; use crate::callee::{self, DeferredCallResolution}; use crate::errors::{self, CtorIsPrivate}; use crate::method::{self, MethodCallee}; @@ -429,17 +430,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn require_type_has_static_alignment(&self, ty: Ty<'tcx>, span: Span) { if !ty.references_error() { - let tail = self.tcx.struct_tail_raw( - ty, - |ty| { - if self.next_trait_solver() { - self.try_structurally_resolve_type(span, ty) - } else { - self.normalize(span, ty) - } - }, - || {}, - ); + let tail = self.tcx.struct_tail_raw(ty, |ty| { + if self.next_trait_solver() { + self.try_structurally_resolve_type(span, ty) + } else { + self.normalize(span, ty) + } + }, || {}, ObligationCause::dummy()); // Sized types have static alignment, and so do slices. if tail.is_trivially_sized(self.tcx) || matches!(tail.kind(), ty::Slice(..)) { // Nothing else is required here. diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs index bd315577efb5e..69a1068cac85c 100644 --- a/compiler/rustc_middle/src/error.rs +++ b/compiler/rustc_middle/src/error.rs @@ -71,6 +71,8 @@ pub enum TypeMismatchReason { #[diag(middle_recursion_limit_reached)] #[help] pub(crate) struct RecursionLimitReached<'tcx> { + #[primary_span] + pub span: Span, pub ty: Ty<'tcx>, pub suggested_limit: rustc_session::Limit, } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ebb6a8c08a54c..96deba08c04ac 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -22,6 +22,7 @@ use rustc_target::spec::{ use tracing::debug; use {rustc_abi as abi, rustc_hir as hir}; +use crate::traits::ObligationCause; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::ty::normalize_erasing_regions::NormalizationError; @@ -398,6 +399,7 @@ impl<'tcx> SizeSkeleton<'tcx> { ), }, || {}, + ObligationCause::dummy(), ); match tail.kind() { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ce563c5925169..81038b00294fd 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -23,6 +23,7 @@ use ty::util::{AsyncDropGlueMorphology, IntTypeExt}; use super::GenericParamDefKind; use crate::infer::canonical::Canonical; +use crate::traits::ObligationCause; use crate::ty::InferTy::*; use crate::ty::{ self, AdtDef, BoundRegionKind, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, @@ -1702,7 +1703,12 @@ impl<'tcx> Ty<'tcx> { tcx: TyCtxt<'tcx>, normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, ) -> Result, Ty<'tcx>> { - let tail = tcx.struct_tail_raw(self, normalize, || {}); + let tail = tcx.struct_tail_raw( + self, + normalize, + || {}, + ObligationCause::dummy(), + ); match tail.kind() { // Sized types ty::Infer(ty::IntVar(_) | ty::FloatVar(_)) diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 0c68913904fc3..f58ebd99f6f3b 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -21,6 +21,7 @@ use tracing::{debug, instrument}; use super::TypingEnv; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use crate::traits::ObligationCause; use crate::mir; use crate::query::Providers; use crate::ty::fold::fold_regions; @@ -217,7 +218,12 @@ impl<'tcx> TyCtxt<'tcx> { typing_env: ty::TypingEnv<'tcx>, ) -> Ty<'tcx> { let tcx = self; - tcx.struct_tail_raw(ty, |ty| tcx.normalize_erasing_regions(typing_env, ty), || {}) + tcx.struct_tail_raw( + ty, + |ty| tcx.normalize_erasing_regions(typing_env, ty), + || {}, // ✅ Closure goes **before** ObligationCause + ObligationCause::dummy(), // ✅ ObligationCause is **last** + ) } /// Returns true if a type has metadata. @@ -250,23 +256,27 @@ impl<'tcx> TyCtxt<'tcx> { self, mut ty: Ty<'tcx>, mut normalize: impl FnMut(Ty<'tcx>) -> Ty<'tcx>, - // This is currently used to allow us to walk a ValTree - // in lockstep with the type in order to get the ValTree branch that - // corresponds to an unsized field. mut f: impl FnMut() -> (), + obligation_cause: ObligationCause<'tcx>, ) -> Ty<'tcx> { let recursion_limit = self.recursion_limit(); + for iteration in 0.. { if !recursion_limit.value_within_limit(iteration) { let suggested_limit = match recursion_limit { Limit(0) => Limit(2), limit => limit * 2, }; - let reported = self - .dcx() - .emit_err(crate::error::RecursionLimitReached { ty, suggested_limit }); + + let reported = self.dcx().emit_err(crate::error::RecursionLimitReached { + ty, + suggested_limit, + span: obligation_cause.span, + }); + return Ty::new_error(self, reported); } + match *ty.kind() { ty::Adt(def, args) => { if !def.is_struct() { @@ -302,14 +312,14 @@ impl<'tcx> TyCtxt<'tcx> { } } - _ => { - break; - } + _ => break, } } + ty } + /// Same as applying `struct_tail` on `source` and `target`, but only /// keeps going as long as the two types are instances of the same /// structure definitions. diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 4d9cf6620d623..fbcdc98c0338d 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1106,8 +1106,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( let tail = selcx.tcx().struct_tail_raw( self_ty, |ty| { - // We throw away any obligations we get from this, since we normalize - // and confirm these obligations once again during confirmation normalize_with_depth( selcx, obligation.param_env, @@ -1115,11 +1113,13 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( obligation.recursion_depth + 1, ty, ) - .value + .value }, - || {}, + || {}, // ✅ Move closure before ObligationCause + obligation.cause.clone(), // ✅ ObligationCause must be last ); + match tail.kind() { ty::Bool | ty::Char diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 7334beb52c9d5..5056839ccb1bf 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -22,6 +22,7 @@ use rustc_span::{Symbol, sym}; use tracing::{debug, instrument}; use {rustc_abi as abi, rustc_hir as hir}; +use rustc_infer::traits::ObligationCause; use crate::errors::{NonPrimitiveSimdType, OversizedSimdType, ZeroLengthSimdType}; mod invariant; @@ -318,7 +319,7 @@ fn layout_of_uncached<'tcx>( // error. match tcx.try_normalize_erasing_regions( cx.typing_env, - tcx.struct_tail_raw(pointee, |ty| ty, || {}), + tcx.struct_tail_raw(pointee, |ty| ty, || {}, ObligationCause::dummy()), ) { Ok(_) => {} Err(better_err) => {