]>
Commit | Line | Data |
---|---|---|
136023e0 | 1 | use crate::traits::query::evaluate_obligation::InferCtxtExt as _; |
ba9703b0 XL |
2 | use crate::traits::{self, TraitEngine, TraitEngineExt}; |
3 | ||
136023e0 | 4 | use rustc_hir::def_id::DefId; |
3dfed10e | 5 | use rustc_hir::lang_items::LangItem; |
ba9703b0 XL |
6 | use rustc_infer::traits::ObligationCause; |
7 | use rustc_middle::arena::ArenaAllocatable; | |
8 | use rustc_middle::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; | |
9 | use rustc_middle::traits::query::Fallible; | |
136023e0 XL |
10 | use rustc_middle::ty::subst::SubstsRef; |
11 | use rustc_middle::ty::ToPredicate; | |
064997fb | 12 | use rustc_middle::ty::{self, Ty, TypeFoldable, TypeVisitable}; |
ba9703b0 XL |
13 | use rustc_span::{Span, DUMMY_SP}; |
14 | ||
15 | use std::fmt::Debug; | |
16 | ||
17 | pub use rustc_infer::infer::*; | |
18 | ||
19 | pub trait InferCtxtExt<'tcx> { | |
20 | fn type_is_copy_modulo_regions( | |
21 | &self, | |
22 | param_env: ty::ParamEnv<'tcx>, | |
23 | ty: Ty<'tcx>, | |
24 | span: Span, | |
25 | ) -> bool; | |
26 | ||
f2b60f7d FG |
27 | fn type_is_sized_modulo_regions( |
28 | &self, | |
29 | param_env: ty::ParamEnv<'tcx>, | |
30 | ty: Ty<'tcx>, | |
31 | span: Span, | |
32 | ) -> bool; | |
33 | ||
ba9703b0 XL |
34 | fn partially_normalize_associated_types_in<T>( |
35 | &self, | |
136023e0 | 36 | cause: ObligationCause<'tcx>, |
ba9703b0 | 37 | param_env: ty::ParamEnv<'tcx>, |
fc512014 | 38 | value: T, |
ba9703b0 XL |
39 | ) -> InferOk<'tcx, T> |
40 | where | |
41 | T: TypeFoldable<'tcx>; | |
ba9703b0 | 42 | |
136023e0 XL |
43 | /// Check whether a `ty` implements given trait(trait_def_id). |
44 | /// The inputs are: | |
45 | /// | |
46 | /// - the def-id of the trait | |
47 | /// - the self type | |
48 | /// - the *other* type parameters of the trait, excluding the self-type | |
49 | /// - the parameter environment | |
94222f64 XL |
50 | /// |
51 | /// Invokes `evaluate_obligation`, so in the event that evaluating | |
52 | /// `Ty: Trait` causes overflow, EvaluatedToRecur (or EvaluatedToUnknown) | |
53 | /// will be returned. | |
136023e0 XL |
54 | fn type_implements_trait( |
55 | &self, | |
56 | trait_def_id: DefId, | |
57 | ty: Ty<'tcx>, | |
58 | params: SubstsRef<'tcx>, | |
59 | param_env: ty::ParamEnv<'tcx>, | |
60 | ) -> traits::EvaluationResult; | |
61 | } | |
2b03887a | 62 | impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { |
ba9703b0 XL |
63 | fn type_is_copy_modulo_regions( |
64 | &self, | |
65 | param_env: ty::ParamEnv<'tcx>, | |
66 | ty: Ty<'tcx>, | |
67 | span: Span, | |
68 | ) -> bool { | |
fc512014 | 69 | let ty = self.resolve_vars_if_possible(ty); |
ba9703b0 XL |
70 | |
71 | if !(param_env, ty).needs_infer() { | |
2b03887a | 72 | return ty.is_copy_modulo_regions(self.tcx, param_env); |
ba9703b0 XL |
73 | } |
74 | ||
3dfed10e | 75 | let copy_def_id = self.tcx.require_lang_item(LangItem::Copy, None); |
ba9703b0 XL |
76 | |
77 | // This can get called from typeck (by euv), and `moves_by_default` | |
78 | // rightly refuses to work with inference variables, but | |
79 | // moves_by_default has a cache, which we want to use in other | |
80 | // cases. | |
81 | traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) | |
82 | } | |
83 | ||
f2b60f7d FG |
84 | fn type_is_sized_modulo_regions( |
85 | &self, | |
86 | param_env: ty::ParamEnv<'tcx>, | |
87 | ty: Ty<'tcx>, | |
88 | span: Span, | |
89 | ) -> bool { | |
90 | let lang_item = self.tcx.require_lang_item(LangItem::Sized, None); | |
91 | traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, lang_item, span) | |
92 | } | |
93 | ||
ba9703b0 XL |
94 | /// Normalizes associated types in `value`, potentially returning |
95 | /// new obligations that must further be processed. | |
96 | fn partially_normalize_associated_types_in<T>( | |
97 | &self, | |
136023e0 | 98 | cause: ObligationCause<'tcx>, |
ba9703b0 | 99 | param_env: ty::ParamEnv<'tcx>, |
fc512014 | 100 | value: T, |
ba9703b0 XL |
101 | ) -> InferOk<'tcx, T> |
102 | where | |
103 | T: TypeFoldable<'tcx>, | |
104 | { | |
105 | debug!("partially_normalize_associated_types_in(value={:?})", value); | |
106 | let mut selcx = traits::SelectionContext::new(self); | |
ba9703b0 XL |
107 | let traits::Normalized { value, obligations } = |
108 | traits::normalize(&mut selcx, param_env, cause, value); | |
109 | debug!( | |
110 | "partially_normalize_associated_types_in: result={:?} predicates={:?}", | |
111 | value, obligations | |
112 | ); | |
113 | InferOk { value, obligations } | |
114 | } | |
136023e0 XL |
115 | |
116 | fn type_implements_trait( | |
117 | &self, | |
118 | trait_def_id: DefId, | |
119 | ty: Ty<'tcx>, | |
120 | params: SubstsRef<'tcx>, | |
121 | param_env: ty::ParamEnv<'tcx>, | |
122 | ) -> traits::EvaluationResult { | |
123 | debug!( | |
124 | "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}", | |
125 | trait_def_id, ty, params, param_env | |
126 | ); | |
127 | ||
128 | let trait_ref = | |
129 | ty::TraitRef { def_id: trait_def_id, substs: self.tcx.mk_substs_trait(ty, params) }; | |
130 | ||
131 | let obligation = traits::Obligation { | |
132 | cause: traits::ObligationCause::dummy(), | |
133 | param_env, | |
134 | recursion_depth: 0, | |
c295e0f8 | 135 | predicate: ty::Binder::dummy(trait_ref).without_const().to_predicate(self.tcx), |
136023e0 | 136 | }; |
94222f64 | 137 | self.evaluate_obligation(&obligation).unwrap_or(traits::EvaluationResult::EvaluatedToErr) |
136023e0 | 138 | } |
ba9703b0 XL |
139 | } |
140 | ||
141 | pub trait InferCtxtBuilderExt<'tcx> { | |
142 | fn enter_canonical_trait_query<K, R>( | |
143 | &mut self, | |
144 | canonical_key: &Canonical<'tcx, K>, | |
2b03887a | 145 | operation: impl FnOnce(&InferCtxt<'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>, |
ba9703b0 XL |
146 | ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>> |
147 | where | |
148 | K: TypeFoldable<'tcx>, | |
149 | R: Debug + TypeFoldable<'tcx>, | |
f035d41b | 150 | Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>; |
ba9703b0 XL |
151 | } |
152 | ||
153 | impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { | |
154 | /// The "main method" for a canonicalized trait query. Given the | |
155 | /// canonical key `canonical_key`, this method will create a new | |
156 | /// inference context, instantiate the key, and run your operation | |
157 | /// `op`. The operation should yield up a result (of type `R`) as | |
158 | /// well as a set of trait obligations that must be fully | |
159 | /// satisfied. These obligations will be processed and the | |
160 | /// canonical result created. | |
161 | /// | |
162 | /// Returns `NoSolution` in the event of any error. | |
163 | /// | |
164 | /// (It might be mildly nicer to implement this on `TyCtxt`, and | |
165 | /// not `InferCtxtBuilder`, but that is a bit tricky right now. | |
166 | /// In part because we would need a `for<'tcx>` sort of | |
167 | /// bound for the closure and in part because it is convenient to | |
168 | /// have `'tcx` be free on this function so that we can talk about | |
169 | /// `K: TypeFoldable<'tcx>`.) | |
170 | fn enter_canonical_trait_query<K, R>( | |
171 | &mut self, | |
172 | canonical_key: &Canonical<'tcx, K>, | |
2b03887a | 173 | operation: impl FnOnce(&InferCtxt<'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible<R>, |
ba9703b0 XL |
174 | ) -> Fallible<CanonicalizedQueryResponse<'tcx, R>> |
175 | where | |
176 | K: TypeFoldable<'tcx>, | |
177 | R: Debug + TypeFoldable<'tcx>, | |
f035d41b | 178 | Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>, |
ba9703b0 | 179 | { |
2b03887a FG |
180 | let (ref infcx, key, canonical_inference_vars) = |
181 | self.build_with_canonical(DUMMY_SP, canonical_key); | |
182 | let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); | |
183 | let value = operation(infcx, &mut *fulfill_cx, key)?; | |
184 | infcx.make_canonicalized_query_response(canonical_inference_vars, value, &mut *fulfill_cx) | |
ba9703b0 XL |
185 | } |
186 | } |