From 8b5a96ec45886bc42090fe313150e648e488eee1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Dec 2022 10:45:35 +0000 Subject: [PATCH 1/5] Some tracing cleanups --- compiler/rustc_borrowck/src/type_check/mod.rs | 6 ++---- compiler/rustc_middle/src/mir/tcx.rs | 7 +++---- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 8d4a720f8ce9b..36397227d88d0 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1153,6 +1153,7 @@ 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; @@ -1170,10 +1171,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 8d2a8f33d6aa9..599f0b9d3fab4 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 From 562d846ff03af63ede8e12c0b02046fa54889ee3 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Dec 2022 12:10:26 +0000 Subject: [PATCH 2/5] Make it easier to debug where a region error was created --- .../src/diagnostics/region_errors.rs | 20 +++++++++++++++++-- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index b5a0044e9e8cd..500ce9038bbb9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::Region; use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::{self, RegionVid, Ty}; 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,23 @@ 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>; +#[derive(Default)] +pub(crate) struct RegionErrors<'tcx>(Vec>); + +impl<'tcx> RegionErrors<'tcx> { + #[track_caller] + pub fn push(&mut self, val: impl Into>) { + let val = val.into(); + ty::tls::with(|tcx| tcx.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 0d03346ef0a5e..7ccc3cc289637 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::default(); // If this is a closure, we can propagate unsatisfied // `outlives_requirements` to our creator, so create a vector From 8b1530260c66069ce1f5cd8d5d32a98b9e1b49cb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Dec 2022 12:49:10 +0000 Subject: [PATCH 3/5] Replace a `find` with a loop to simplify the logic. --- .../rustc_borrowck/src/region_infer/mod.rs | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 7ccc3cc289637..931732af90414 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -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))] From e405dabf7dc99cbcd5f483592e8f9b5ea621d110 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Dec 2022 13:14:03 +0000 Subject: [PATCH 4/5] Some style nits --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_mir_build/src/build/expr/as_constant.rs | 4 ++-- compiler/rustc_mir_build/src/build/matches/mod.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 36397227d88d0..2973f8b7f85f9 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1163,7 +1163,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { tcx, self.param_env, proj, - |this, field, _| { + |this, field, ()| { let ty = this.field_ty(tcx, field); self.normalize(ty, locations) }, 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 3b7ed818dc9b7..1d96893c7a3ea 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 7edcd46a34f29..f90aba80bf3cf 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)) }, From c9588d5bf8db14d80249b029b07f79026956ae85 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Dec 2022 13:14:22 +0000 Subject: [PATCH 5/5] Hackily fix an opaque type ICE --- .../rustc_borrowck/src/diagnostics/region_errors.rs | 10 ++++++---- compiler/rustc_borrowck/src/region_infer/mod.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 6 ++++++ src/test/ui/type-alias-impl-trait/destructuring.rs | 10 ++++++++++ 4 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/destructuring.rs diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 500ce9038bbb9..bcc8afbfd952d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -18,9 +18,9 @@ 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, DUMMY_SP}; @@ -70,14 +70,16 @@ 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. -#[derive(Default)] -pub(crate) struct 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(); - ty::tls::with(|tcx| tcx.sess.delay_span_bug(DUMMY_SP, "{val:?}")); + self.1.sess.delay_span_bug(DUMMY_SP, "{val:?}"); self.0.push(val); } pub fn is_empty(&self) -> bool { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 931732af90414..308f6e19a73e8 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::default(); + 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 diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 2973f8b7f85f9..247607ff29e20 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1159,6 +1159,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { 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, 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 0000000000000..b752e58380a89 --- /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); +}