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