1 //! Code for the 'normalization' query. This consists of a wrapper
2 //! which folds deeply, invoking the underlying
3 //! `normalize_projection_ty` query when it encounters projections.
5 use crate::infer::at::At;
6 use crate::infer::canonical::OriginalQueryValues;
7 use crate::infer::{InferCtxt, InferOk};
8 use crate::traits::error_reporting::InferCtxtExt;
9 use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal};
10 use rustc_data_structures::stack::ensure_sufficient_stack;
11 use rustc_infer::traits::Normalized;
12 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder};
13 use rustc_middle::ty::subst::Subst;
14 use rustc_middle::ty::{self, Ty, TyCtxt};
16 use super::NoSolution;
18 pub use rustc_middle::traits::query::NormalizationResult;
20 pub trait AtExt<'tcx> {
21 fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
23 T: TypeFoldable<'tcx>;
26 impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> {
27 /// Normalize `value` in the context of the inference context,
28 /// yielding a resulting type, or an error if `value` cannot be
29 /// normalized. If you don't care about regions, you should prefer
30 /// `normalize_erasing_regions`, which is more efficient.
32 /// If the normalization succeeds and is unambiguous, returns back
33 /// the normalized value along with various outlives relations (in
34 /// the form of obligations that must be discharged).
36 /// N.B., this will *eventually* be the main means of
37 /// normalizing, but for now should be used only when we actually
38 /// know that normalization will succeed, since error reporting
39 /// and other details are still "under development".
40 fn normalize<T>(&self, value: &T) -> Result<Normalized<'tcx, T>, NoSolution>
42 T: TypeFoldable<'tcx>,
45 "normalize::<{}>(value={:?}, param_env={:?})",
46 ::std::any::type_name::<T>(),
50 if !value.has_projections() {
51 return Ok(Normalized { value: value.clone(), obligations: vec![] });
54 let mut normalizer = QueryNormalizer {
57 param_env: self.param_env,
63 let result = value.fold_with(&mut normalizer);
65 "normalize::<{}>: result={:?} with {} obligations",
66 ::std::any::type_name::<T>(),
68 normalizer.obligations.len(),
71 "normalize::<{}>: obligations={:?}",
72 ::std::any::type_name::<T>(),
73 normalizer.obligations,
78 Ok(Normalized { value: result, obligations: normalizer.obligations })
83 struct QueryNormalizer<'cx, 'tcx> {
84 infcx: &'cx InferCtxt<'cx, 'tcx>,
85 cause: &'cx ObligationCause<'tcx>,
86 param_env: ty::ParamEnv<'tcx>,
87 obligations: Vec<PredicateObligation<'tcx>>,
92 impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
93 fn tcx<'c>(&'c self) -> TyCtxt<'tcx> {
97 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
98 if !ty.has_projections() {
102 let ty = ty.super_fold_with(self);
104 ty::Opaque(def_id, substs) => {
105 // Only normalize `impl Trait` after type-checking, usually in codegen.
106 match self.param_env.reveal() {
107 Reveal::UserFacing => ty,
110 let recursion_limit = self.tcx().sess.recursion_limit();
111 if !recursion_limit.value_within_limit(self.anon_depth) {
112 let obligation = Obligation::with_depth(
118 self.infcx.report_overflow_error(&obligation, true);
121 let generic_ty = self.tcx().type_of(def_id);
122 let concrete_ty = generic_ty.subst(self.tcx(), substs);
123 self.anon_depth += 1;
124 if concrete_ty == ty {
126 "infinite recursion generic_ty: {:#?}, substs: {:#?}, \
127 concrete_ty: {:#?}, ty: {:#?}",
134 let folded_ty = ensure_sufficient_stack(|| self.fold_ty(concrete_ty));
135 self.anon_depth -= 1;
141 ty::Projection(ref data) if !data.has_escaping_bound_vars() => {
142 // This is kind of hacky -- we need to be able to
143 // handle normalization within binders because
144 // otherwise we wind up a need to normalize when doing
145 // trait matching (since you can have a trait
146 // obligation like `for<'a> T::B: Fn(&'a i32)`), but
147 // we can't normalize with bound regions in scope. So
148 // far now we just ignore binders but only normalize
149 // if all bound regions are gone (and then we still
150 // have to renormalize whenever we instantiate a
151 // binder). It would be better to normalize in a
152 // binding-aware fashion.
154 let tcx = self.infcx.tcx;
156 let mut orig_values = OriginalQueryValues::default();
157 // HACK(matthewjasper) `'static` is special-cased in selection,
158 // so we cannot canonicalize it.
161 .canonicalize_hr_query_hack(&self.param_env.and(*data), &mut orig_values);
162 debug!("QueryNormalizer: c_data = {:#?}", c_data);
163 debug!("QueryNormalizer: orig_values = {:#?}", orig_values);
164 match tcx.normalize_projection_ty(c_data) {
166 // We don't expect ambiguity.
167 if result.is_ambiguous() {
172 match self.infcx.instantiate_query_response_and_region_obligations(
178 Ok(InferOk { value: result, obligations }) => {
179 debug!("QueryNormalizer: result = {:#?}", result);
180 debug!("QueryNormalizer: obligations = {:#?}", obligations);
181 self.obligations.extend(obligations);
203 fn fold_const(&mut self, constant: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
204 let constant = constant.super_fold_with(self);
205 constant.eval(self.infcx.tcx, self.param_env)