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