1 use rustc_infer::infer::at::At; 2 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; 3 use rustc_infer::traits::{FulfillmentError, TraitEngine}; 4 use rustc_middle::ty::{self, Ty}; 5 6 use crate::traits::{query::evaluate_obligation::InferCtxtExt, NormalizeExt, Obligation}; 7 8 pub trait StructurallyNormalizeExt<'tcx> { structurally_normalize( &self, ty: Ty<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>9 fn structurally_normalize( 10 &self, 11 ty: Ty<'tcx>, 12 fulfill_cx: &mut dyn TraitEngine<'tcx>, 13 ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>; 14 } 15 16 impl<'tcx> StructurallyNormalizeExt<'tcx> for At<'_, 'tcx> { structurally_normalize( &self, mut ty: Ty<'tcx>, fulfill_cx: &mut dyn TraitEngine<'tcx>, ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>>17 fn structurally_normalize( 18 &self, 19 mut ty: Ty<'tcx>, 20 fulfill_cx: &mut dyn TraitEngine<'tcx>, 21 ) -> Result<Ty<'tcx>, Vec<FulfillmentError<'tcx>>> { 22 assert!(!ty.is_ty_var(), "should have resolved vars before calling"); 23 24 if self.infcx.next_trait_solver() { 25 while let ty::Alias(ty::Projection, projection_ty) = *ty.kind() { 26 let new_infer_ty = self.infcx.next_ty_var(TypeVariableOrigin { 27 kind: TypeVariableOriginKind::NormalizeProjectionType, 28 span: self.cause.span, 29 }); 30 let obligation = Obligation::new( 31 self.infcx.tcx, 32 self.cause.clone(), 33 self.param_env, 34 ty::Binder::dummy(ty::ProjectionPredicate { 35 projection_ty, 36 term: new_infer_ty.into(), 37 }), 38 ); 39 if self.infcx.predicate_may_hold(&obligation) { 40 fulfill_cx.register_predicate_obligation(self.infcx, obligation); 41 let errors = fulfill_cx.select_where_possible(self.infcx); 42 if !errors.is_empty() { 43 return Err(errors); 44 } 45 ty = self.infcx.resolve_vars_if_possible(new_infer_ty); 46 } else { 47 break; 48 } 49 } 50 Ok(ty) 51 } else { 52 Ok(self.normalize(ty).into_value_registering_obligations(self.infcx, fulfill_cx)) 53 } 54 } 55 } 56