rustc_trait_selection/traits/
structural_normalize.rs
1use rustc_infer::infer::at::At;
2use rustc_infer::traits::TraitEngine;
3use rustc_macros::extension;
4use rustc_middle::ty::{self, Ty};
5
6use crate::traits::{NormalizeExt, Obligation};
7
8#[extension(pub trait StructurallyNormalizeExt<'tcx>)]
9impl<'tcx> At<'_, 'tcx> {
10 fn structurally_normalize_ty<E: 'tcx>(
11 &self,
12 ty: Ty<'tcx>,
13 fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
14 ) -> Result<Ty<'tcx>, Vec<E>> {
15 self.structurally_normalize_term(ty.into(), fulfill_cx).map(|term| term.expect_type())
16 }
17
18 fn structurally_normalize_const<E: 'tcx>(
19 &self,
20 ct: ty::Const<'tcx>,
21 fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
22 ) -> Result<ty::Const<'tcx>, Vec<E>> {
23 if self.infcx.tcx.features().generic_const_exprs() {
24 return Ok(super::evaluate_const(&self.infcx, ct, self.param_env));
25 }
26
27 self.structurally_normalize_term(ct.into(), fulfill_cx).map(|term| term.expect_const())
28 }
29
30 fn structurally_normalize_term<E: 'tcx>(
31 &self,
32 term: ty::Term<'tcx>,
33 fulfill_cx: &mut dyn TraitEngine<'tcx, E>,
34 ) -> Result<ty::Term<'tcx>, Vec<E>> {
35 assert!(!term.is_infer(), "should have resolved vars before calling");
36
37 if self.infcx.next_trait_solver() {
38 if let None = term.to_alias_term() {
39 return Ok(term);
40 }
41
42 let new_infer = match term.unpack() {
43 ty::TermKind::Ty(_) => self.infcx.next_ty_var(self.cause.span).into(),
44 ty::TermKind::Const(_) => self.infcx.next_const_var(self.cause.span).into(),
45 };
46
47 let obligation = Obligation::new(
51 self.infcx.tcx,
52 self.cause.clone(),
53 self.param_env,
54 ty::PredicateKind::AliasRelate(term, new_infer, ty::AliasRelationDirection::Equate),
55 );
56
57 fulfill_cx.register_predicate_obligation(self.infcx, obligation);
58 let errors = fulfill_cx.select_where_possible(self.infcx);
59 if !errors.is_empty() {
60 return Err(errors);
61 }
62
63 Ok(self.infcx.resolve_vars_if_possible(new_infer))
64 } else {
65 Ok(self.normalize(term).into_value_registering_obligations(self.infcx, fulfill_cx))
66 }
67 }
68}