diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b5a0044e9e8c..bcc8afbfd952 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -18,11 +18,11 @@ use rustc_infer::infer::{ use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::subst::InternalSubsts; -use rustc_middle::ty::Region; use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::{self, RegionVid, Ty}; +use rustc_middle::ty::{Region, TyCtxt}; use rustc_span::symbol::{kw, Ident}; -use rustc_span::Span; +use rustc_span::{Span, DUMMY_SP}; use crate::borrowck_errors; use crate::session_diagnostics::{ @@ -70,7 +70,25 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { /// /// Usually we expect this to either be empty or contain a small number of items, so we can avoid /// allocation most of the time. -pub(crate) type RegionErrors<'tcx> = Vec>; +pub(crate) struct RegionErrors<'tcx>(Vec>, TyCtxt<'tcx>); + +impl<'tcx> RegionErrors<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>) -> Self { + Self(vec![], tcx) + } + #[track_caller] + pub fn push(&mut self, val: impl Into>) { + let val = val.into(); + self.1.sess.delay_span_bug(DUMMY_SP, "{val:?}"); + self.0.push(val); + } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + pub fn into_iter(self) -> impl Iterator> { + self.0.into_iter() + } +} #[derive(Clone, Debug)] pub(crate) enum RegionErrorKind<'tcx> { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 0d03346ef0a5..308f6e19a73e 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -562,7 +562,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mir_def_id = body.source.def_id(); self.propagate_constraints(body); - let mut errors_buffer = RegionErrors::new(); + let mut errors_buffer = RegionErrors::new(infcx.tcx); // If this is a closure, we can propagate unsatisfied // `outlives_requirements` to our creator, so create a vector @@ -1647,26 +1647,29 @@ impl<'tcx> RegionInferenceContext<'tcx> { let longer_fr_scc = self.constraint_sccs.scc(longer_fr); debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,); - // If we have some bound universal region `'a`, then the only - // elements it can contain is itself -- we don't know anything - // else about it! - let Some(error_element) = ({ - self.scc_values.elements_contained_in(longer_fr_scc).find(|element| match element { - RegionElement::Location(_) => true, - RegionElement::RootUniversalRegion(_) => true, - RegionElement::PlaceholderRegion(placeholder1) => placeholder != *placeholder1, - }) - }) else { - return; - }; - debug!("check_bound_universal_region: error_element = {:?}", error_element); + for error_element in self.scc_values.elements_contained_in(longer_fr_scc) { + match error_element { + RegionElement::Location(_) | RegionElement::RootUniversalRegion(_) => {} + // If we have some bound universal region `'a`, then the only + // elements it can contain is itself -- we don't know anything + // else about it! + RegionElement::PlaceholderRegion(placeholder1) => { + if placeholder == placeholder1 { + continue; + } + } + } - // Find the region that introduced this `error_element`. - errors_buffer.push(RegionErrorKind::BoundUniversalRegionError { - longer_fr, - error_element, - placeholder, - }); + errors_buffer.push(RegionErrorKind::BoundUniversalRegionError { + longer_fr, + error_element, + placeholder, + }); + + // Stop after the first error, it gets too noisy otherwise, and does not provide more information. + break; + } + debug!("check_bound_universal_region: all bounds satisfied"); } #[instrument(level = "debug", skip(self, infcx, errors_buffer))] diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8d4a720f8ce9..247607ff29e2 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1153,16 +1153,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { category: ConstraintCategory<'tcx>, ) -> Fallible<()> { let annotated_type = self.user_type_annotations[user_ty.base].inferred_ty; + trace!(?annotated_type); let mut curr_projected_ty = PlaceTy::from_ty(annotated_type); let tcx = self.infcx.tcx; for proj in &user_ty.projs { + if let ty::Alias(ty::Opaque, ..) = curr_projected_ty.ty.kind() { + // There is nothing that we can compare here if we go through an opaque type. + // We're always in its defining scope as we can otherwise not project through + // it, so we're constraining it anyways. + return Ok(()); + } let projected_ty = curr_projected_ty.projection_ty_core( tcx, self.param_env, proj, - |this, field, _| { + |this, field, ()| { let ty = this.field_ty(tcx, field); self.normalize(ty, locations) }, @@ -1170,10 +1177,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); curr_projected_ty = projected_ty; } - debug!( - "user_ty base: {:?} freshened: {:?} projs: {:?} yields: {:?}", - user_ty.base, annotated_type, user_ty.projs, curr_projected_ty - ); + trace!(?curr_projected_ty); let ty = curr_projected_ty.ty; self.relate_types(ty, v.xform(ty::Variance::Contravariant), a, locations, category)?; diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 8d2a8f33d6aa..599f0b9d3fab 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -32,8 +32,9 @@ impl<'tcx> PlaceTy<'tcx> { /// not carry a `Ty` for `T`.) /// /// Note that the resulting type has not been normalized. + #[instrument(level = "debug", skip(tcx), ret)] pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> { - let answer = match self.ty.kind() { + match self.ty.kind() { ty::Adt(adt_def, substs) => { let variant_def = match self.variant_index { None => adt_def.non_enum_variant(), @@ -47,9 +48,7 @@ impl<'tcx> PlaceTy<'tcx> { } ty::Tuple(tys) => tys[f.index()], _ => bug!("extracting field of non-tuple non-adt: {:?}", self), - }; - debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer); - answer + } } /// Convenience wrapper around `projection_ty_core` for diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3b7ed818dc9b..1d96893c7a3e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -66,14 +66,14 @@ pub fn as_constant_inner<'tcx>( let literal = ConstantKind::Val(ConstValue::Scalar(Scalar::Int(lit)), ty); - Constant { span, user_ty: user_ty, literal } + Constant { span, user_ty, literal } } ExprKind::ZstLiteral { ref user_ty } => { let user_ty = user_ty.as_ref().map(push_cuta).flatten(); let literal = ConstantKind::Val(ConstValue::ZeroSized, ty); - Constant { span, user_ty: user_ty, literal } + Constant { span, user_ty, literal } } ExprKind::NamedConst { def_id, substs, ref user_ty } => { let user_ty = user_ty.as_ref().map(push_cuta).flatten(); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 7edcd46a34f2..f90aba80bf3c 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -2210,7 +2210,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { BindingMode::ByValue => ty::BindingMode::BindByValue(mutability), BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability), }; - let local = LocalDecl::<'tcx> { + let local = LocalDecl { mutability, ty: var_ty, user_ty: if user_ty.is_empty() { None } else { Some(Box::new(user_ty)) }, diff --git a/src/test/ui/type-alias-impl-trait/destructuring.rs b/src/test/ui/type-alias-impl-trait/destructuring.rs new file mode 100644 index 000000000000..b752e58380a8 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/destructuring.rs @@ -0,0 +1,10 @@ +#![feature(type_alias_impl_trait)] + +// check-pass + +// issue: https://github.com/rust-lang/rust/issues/104551 + +fn main() { + type T = impl Sized; + let (_a, _b): T = (1u32, 2u32); +}