3 use rustc_infer::infer::canonical::Canonical;
4 use rustc_infer::traits::query::NoSolution;
5 use rustc_middle::mir::ConstraintCategory;
6 use rustc_middle::ty::{self, ToPredicate, TypeFoldable};
7 use rustc_span::def_id::DefId;
9 use rustc_trait_selection::traits::query::type_op::{self, TypeOpOutput};
10 use rustc_trait_selection::traits::query::Fallible;
12 use crate::diagnostics::{ToUniverseInfo, UniverseInfo};
14 use super::{Locations, NormalizeLocation, TypeChecker};
16 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
17 /// Given some operation `op` that manipulates types, proves
18 /// predicates, or otherwise uses the inference context, executes
19 /// `op` and then executes all the further obligations that `op`
20 /// returns. This will yield a set of outlives constraints amongst
21 /// regions which are extracted and stored as having occurred at
24 /// **Any `rustc_infer::infer` operations that might generate region
25 /// constraints should occur within this method so that those
26 /// constraints can be properly localized!**
27 pub(super) fn fully_perform_op<R, Op>(
30 category: ConstraintCategory,
34 Op: type_op::TypeOp<'tcx, Output = R>,
35 Canonical<'tcx, Op>: ToUniverseInfo<'tcx>,
37 let old_universe = self.infcx.universe();
39 let TypeOpOutput { output, constraints, canonicalized_query } =
40 op.fully_perform(self.infcx)?;
42 if let Some(data) = &constraints {
43 self.push_region_constraints(locations, category, data);
46 let universe = self.infcx.universe();
48 if old_universe != universe {
49 let universe_info = match canonicalized_query {
50 Some(canonicalized_query) => canonicalized_query.to_universe_info(old_universe),
51 None => UniverseInfo::other(),
53 for u in old_universe..universe {
57 .insert(u + 1, universe_info.clone());
64 pub(super) fn instantiate_canonical_with_fresh_inference_vars<T>(
67 canonical: &Canonical<'tcx, T>,
70 T: TypeFoldable<'tcx>,
72 let (instantiated, _) =
73 self.infcx.instantiate_canonical_with_fresh_inference_vars(span, canonical);
75 for u in 0..canonical.max_universe.as_u32() {
76 let info = UniverseInfo::other();
80 .insert(ty::UniverseIndex::from_u32(u), info);
86 pub(super) fn prove_trait_ref(
88 trait_ref: ty::TraitRef<'tcx>,
90 category: ConstraintCategory,
92 self.prove_predicates(
93 Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
95 constness: ty::BoundConstness::NotConst,
102 pub(super) fn normalize_and_prove_instantiated_predicates(
105 instantiated_predicates: ty::InstantiatedPredicates<'tcx>,
106 locations: Locations,
108 for (predicate, span) in instantiated_predicates
111 .zip(instantiated_predicates.spans.into_iter())
113 let predicate = self.normalize(predicate, locations);
114 self.prove_predicate(predicate, locations, ConstraintCategory::Predicate(def_id, span));
118 pub(super) fn prove_predicates(
120 predicates: impl IntoIterator<Item = impl ToPredicate<'tcx>>,
121 locations: Locations,
122 category: ConstraintCategory,
124 for predicate in predicates {
125 let predicate = predicate.to_predicate(self.tcx());
126 debug!("prove_predicates(predicate={:?}, locations={:?})", predicate, locations,);
128 self.prove_predicate(predicate, locations, category);
132 pub(super) fn prove_predicate(
134 predicate: ty::Predicate<'tcx>,
135 locations: Locations,
136 category: ConstraintCategory,
138 debug!("prove_predicate(predicate={:?}, location={:?})", predicate, locations,);
140 let param_env = self.param_env;
141 self.fully_perform_op(
144 param_env.and(type_op::prove_predicate::ProvePredicate::new(predicate)),
146 .unwrap_or_else(|NoSolution| {
147 span_mirbug!(self, NoSolution, "could not prove {:?}", predicate);
151 pub(super) fn normalize<T>(&mut self, value: T, location: impl NormalizeLocation) -> T
153 T: type_op::normalize::Normalizable<'tcx> + fmt::Display + Copy + 'tcx,
155 debug!("normalize(value={:?}, location={:?})", value, location);
156 let param_env = self.param_env;
157 self.fully_perform_op(
158 location.to_locations(),
159 ConstraintCategory::Boring,
160 param_env.and(type_op::normalize::Normalize::new(value)),
162 .unwrap_or_else(|NoSolution| {
163 span_mirbug!(self, NoSolution, "failed to normalize `{:?}`", value);