diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2023-07-15 19:42:51 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-07-15 19:42:51 +0200 |
| commit | da18cf8572dc391abffc96b48041287f0e1d26d8 (patch) | |
| tree | a1b1e30ff7edfaaaad677977a7749e16e1f82cec /compiler | |
| parent | 7a17f577b3d437179cad254e299b2ace972487c5 (diff) | |
| parent | 7fb27e4717b0fadfd0807d568fbac7731886a7f7 (diff) | |
| download | rust-da18cf8572dc391abffc96b48041287f0e1d26d8.tar.gz rust-da18cf8572dc391abffc96b48041287f0e1d26d8.zip | |
Rollup merge of #113625 - compiler-errors:structurally-norm-in-selection, r=lcnr
Structurally normalize in selection We need to do this because of the fact that we're checking the `Ty::kind` on a type during selection, but goals passed into select are not necessarily normalized. Right now, we're (kinda) unnecessarily normalizing the RHS of a trait upcasting goal, which is broken for different reasons (#113393). But I'm waiting for this PR to land before discussing that one. r? `@lcnr`
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs | 39 |
1 files changed, 33 insertions, 6 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 8af9d090164..a6d118d8cc2 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, InferOk}; use rustc_infer::traits::util::supertraits; use rustc_infer::traits::{ - Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, + Obligation, PolyTraitObligation, PredicateObligation, Selection, SelectionResult, TraitEngine, }; use rustc_middle::traits::solve::{CanonicalInput, Certainty, Goal}; use rustc_middle::traits::{ @@ -20,6 +20,8 @@ use crate::solve::eval_ctxt::{EvalCtxt, GenerateProofTree}; use crate::solve::inspect::ProofTreeBuilder; use crate::solve::search_graph::OverflowHandler; use crate::traits::vtable::{count_own_vtable_entries, prepare_vtable_segments, VtblSegment}; +use crate::traits::StructurallyNormalizeExt; +use crate::traits::TraitEngineExt; pub trait InferCtxtSelectExt<'tcx> { fn select_in_new_trait_solver( @@ -228,18 +230,24 @@ fn rematch_object<'tcx>( goal: Goal<'tcx, ty::TraitPredicate<'tcx>>, mut nested: Vec<PredicateObligation<'tcx>>, ) -> SelectionResult<'tcx, Selection<'tcx>> { - let self_ty = goal.predicate.self_ty(); - let ty::Dynamic(data, _, source_kind) = *self_ty.kind() else { bug!() }; - let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, self_ty); + let a_ty = structurally_normalize(goal.predicate.self_ty(), infcx, goal.param_env, &mut nested); + let ty::Dynamic(data, _, source_kind) = *a_ty.kind() else { bug!() }; + let source_trait_ref = data.principal().unwrap().with_self_ty(infcx.tcx, a_ty); let (is_upcasting, target_trait_ref_unnormalized) = if Some(goal.predicate.def_id()) == infcx.tcx.lang_items().unsize_trait() { assert_eq!(source_kind, ty::Dyn, "cannot upcast dyn*"); - if let ty::Dynamic(data, _, ty::Dyn) = goal.predicate.trait_ref.args.type_at(1).kind() { + let b_ty = structurally_normalize( + goal.predicate.trait_ref.args.type_at(1), + infcx, + goal.param_env, + &mut nested, + ); + if let ty::Dynamic(data, _, ty::Dyn) = *b_ty.kind() { // FIXME: We also need to ensure that the source lifetime outlives the // target lifetime. This doesn't matter for codegen, though, and only // *really* matters if the goal's certainty is ambiguous. - (true, data.principal().unwrap().with_self_ty(infcx.tcx, self_ty)) + (true, data.principal().unwrap().with_self_ty(infcx.tcx, a_ty)) } else { bug!() } @@ -447,3 +455,22 @@ fn rematch_unsize<'tcx>( Ok(Some(ImplSource::Builtin(nested))) } + +fn structurally_normalize<'tcx>( + ty: Ty<'tcx>, + infcx: &InferCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + nested: &mut Vec<PredicateObligation<'tcx>>, +) -> Ty<'tcx> { + if matches!(ty.kind(), ty::Alias(..)) { + let mut engine = <dyn TraitEngine<'tcx>>::new(infcx); + let normalized_ty = infcx + .at(&ObligationCause::dummy(), param_env) + .structurally_normalize(ty, &mut *engine) + .expect("normalization shouldn't fail if we got to here"); + nested.extend(engine.pending_obligations()); + normalized_ty + } else { + ty + } +} |
