• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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