]>
Commit | Line | Data |
---|---|---|
0bf4aa26 XL |
1 | use rustc::infer::at::ToTrace; |
2 | use rustc::infer::canonical::{Canonical, QueryResponse}; | |
8faf50e0 | 3 | use rustc::infer::InferCtxt; |
9fa01778 | 4 | use rustc::hir; |
0bf4aa26 | 5 | use rustc::hir::def_id::DefId; |
0bf4aa26 | 6 | use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType; |
8faf50e0 XL |
7 | use rustc::traits::query::type_op::eq::Eq; |
8 | use rustc::traits::query::type_op::normalize::Normalize; | |
9 | use rustc::traits::query::type_op::prove_predicate::ProvePredicate; | |
10 | use rustc::traits::query::type_op::subtype::Subtype; | |
11 | use rustc::traits::query::{Fallible, NoSolution}; | |
0bf4aa26 | 12 | use rustc::traits::{ |
0731742a | 13 | Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt, |
0bf4aa26 | 14 | }; |
8faf50e0 | 15 | use rustc::ty::query::Providers; |
0731742a | 16 | use rustc::ty::subst::{Kind, Subst, UserSubsts, UserSelfTy}; |
0bf4aa26 XL |
17 | use rustc::ty::{ |
18 | FnSig, Lift, ParamEnv, ParamEnvAnd, PolyFnSig, Predicate, Ty, TyCtxt, TypeFoldable, Variance, | |
19 | }; | |
8faf50e0 XL |
20 | use rustc_data_structures::sync::Lrc; |
21 | use std::fmt; | |
0bf4aa26 | 22 | use syntax_pos::DUMMY_SP; |
8faf50e0 | 23 | |
9fa01778 | 24 | crate fn provide(p: &mut Providers<'_>) { |
8faf50e0 | 25 | *p = Providers { |
0bf4aa26 | 26 | type_op_ascribe_user_type, |
8faf50e0 XL |
27 | type_op_eq, |
28 | type_op_prove_predicate, | |
29 | type_op_subtype, | |
30 | type_op_normalize_ty, | |
31 | type_op_normalize_predicate, | |
32 | type_op_normalize_fn_sig, | |
33 | type_op_normalize_poly_fn_sig, | |
34 | ..*p | |
35 | }; | |
36 | } | |
37 | ||
0bf4aa26 XL |
38 | fn type_op_ascribe_user_type<'tcx>( |
39 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
40 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, AscribeUserType<'tcx>>>, | |
41 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> { | |
42 | tcx.infer_ctxt() | |
43 | .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { | |
44 | let ( | |
9fa01778 | 45 | param_env, AscribeUserType { mir_ty, def_id, user_substs } |
0bf4aa26 XL |
46 | ) = key.into_parts(); |
47 | ||
48 | debug!( | |
9fa01778 XL |
49 | "type_op_ascribe_user_type: mir_ty={:?} def_id={:?} user_substs={:?}", |
50 | mir_ty, def_id, user_substs | |
0bf4aa26 XL |
51 | ); |
52 | ||
0731742a | 53 | let mut cx = AscribeUserTypeCx { infcx, param_env, fulfill_cx }; |
9fa01778 | 54 | cx.relate_mir_and_user_ty(mir_ty, def_id, user_substs)?; |
0bf4aa26 XL |
55 | |
56 | Ok(()) | |
57 | }) | |
58 | } | |
59 | ||
60 | struct AscribeUserTypeCx<'me, 'gcx: 'tcx, 'tcx: 'me> { | |
61 | infcx: &'me InferCtxt<'me, 'gcx, 'tcx>, | |
62 | param_env: ParamEnv<'tcx>, | |
0731742a | 63 | fulfill_cx: &'me mut dyn TraitEngine<'tcx>, |
0bf4aa26 XL |
64 | } |
65 | ||
66 | impl AscribeUserTypeCx<'me, 'gcx, 'tcx> { | |
67 | fn normalize<T>(&mut self, value: T) -> T | |
68 | where | |
69 | T: TypeFoldable<'tcx>, | |
70 | { | |
71 | self.infcx | |
72 | .partially_normalize_associated_types_in( | |
73 | DUMMY_SP, | |
9fa01778 | 74 | hir::CRATE_HIR_ID, |
0bf4aa26 XL |
75 | self.param_env, |
76 | &value, | |
77 | ) | |
78 | .into_value_registering_obligations(self.infcx, self.fulfill_cx) | |
79 | } | |
80 | ||
81 | fn relate<T>(&mut self, a: T, variance: Variance, b: T) -> Result<(), NoSolution> | |
82 | where | |
83 | T: ToTrace<'tcx>, | |
84 | { | |
85 | Ok(self.infcx | |
86 | .at(&ObligationCause::dummy(), self.param_env) | |
87 | .relate(a, variance, b)? | |
88 | .into_value_registering_obligations(self.infcx, self.fulfill_cx)) | |
89 | } | |
90 | ||
91 | fn prove_predicate(&mut self, predicate: Predicate<'tcx>) { | |
92 | self.fulfill_cx.register_predicate_obligation( | |
93 | self.infcx, | |
94 | Obligation::new(ObligationCause::dummy(), self.param_env, predicate), | |
95 | ); | |
96 | } | |
97 | ||
98 | fn tcx(&self) -> TyCtxt<'me, 'gcx, 'tcx> { | |
99 | self.infcx.tcx | |
100 | } | |
101 | ||
102 | fn subst<T>(&self, value: T, substs: &[Kind<'tcx>]) -> T | |
103 | where | |
104 | T: TypeFoldable<'tcx>, | |
105 | { | |
106 | value.subst(self.tcx(), substs) | |
107 | } | |
108 | ||
109 | fn relate_mir_and_user_ty( | |
110 | &mut self, | |
111 | mir_ty: Ty<'tcx>, | |
0bf4aa26 XL |
112 | def_id: DefId, |
113 | user_substs: UserSubsts<'tcx>, | |
0bf4aa26 XL |
114 | ) -> Result<(), NoSolution> { |
115 | let UserSubsts { | |
0bf4aa26 | 116 | user_self_ty, |
0731742a | 117 | substs, |
0bf4aa26 | 118 | } = user_substs; |
0bf4aa26 XL |
119 | let tcx = self.tcx(); |
120 | ||
121 | let ty = tcx.type_of(def_id); | |
122 | let ty = self.subst(ty, substs); | |
123 | debug!("relate_type_and_user_type: ty of def-id is {:?}", ty); | |
124 | let ty = self.normalize(ty); | |
125 | ||
9fa01778 | 126 | self.relate(mir_ty, Variance::Invariant, ty)?; |
0bf4aa26 | 127 | |
0bf4aa26 XL |
128 | // Prove the predicates coming along with `def_id`. |
129 | // | |
130 | // Also, normalize the `instantiated_predicates` | |
131 | // because otherwise we wind up with duplicate "type | |
132 | // outlives" error messages. | |
133 | let instantiated_predicates = self.tcx() | |
134 | .predicates_of(def_id) | |
135 | .instantiate(self.tcx(), substs); | |
136 | for instantiated_predicate in instantiated_predicates.predicates { | |
137 | let instantiated_predicate = self.normalize(instantiated_predicate); | |
138 | self.prove_predicate(instantiated_predicate); | |
139 | } | |
140 | ||
0731742a XL |
141 | if let Some(UserSelfTy { |
142 | impl_def_id, | |
143 | self_ty, | |
144 | }) = user_self_ty { | |
145 | let impl_self_ty = self.tcx().type_of(impl_def_id); | |
146 | let impl_self_ty = self.subst(impl_self_ty, &substs); | |
147 | let impl_self_ty = self.normalize(impl_self_ty); | |
148 | ||
149 | self.relate(self_ty, Variance::Invariant, impl_self_ty)?; | |
150 | ||
151 | self.prove_predicate(Predicate::WellFormed(impl_self_ty)); | |
152 | } | |
153 | ||
0bf4aa26 XL |
154 | // In addition to proving the predicates, we have to |
155 | // prove that `ty` is well-formed -- this is because | |
156 | // the WF of `ty` is predicated on the substs being | |
157 | // well-formed, and we haven't proven *that*. We don't | |
158 | // want to prove the WF of types from `substs` directly because they | |
159 | // haven't been normalized. | |
160 | // | |
161 | // FIXME(nmatsakis): Well, perhaps we should normalize | |
162 | // them? This would only be relevant if some input | |
163 | // type were ill-formed but did not appear in `ty`, | |
164 | // which...could happen with normalization... | |
165 | self.prove_predicate(Predicate::WellFormed(ty)); | |
0bf4aa26 XL |
166 | Ok(()) |
167 | } | |
168 | } | |
169 | ||
8faf50e0 XL |
170 | fn type_op_eq<'tcx>( |
171 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
172 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Eq<'tcx>>>, | |
0bf4aa26 | 173 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> { |
8faf50e0 XL |
174 | tcx.infer_ctxt() |
175 | .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { | |
176 | let (param_env, Eq { a, b }) = key.into_parts(); | |
177 | Ok(infcx | |
178 | .at(&ObligationCause::dummy(), param_env) | |
179 | .eq(a, b)? | |
180 | .into_value_registering_obligations(infcx, fulfill_cx)) | |
181 | }) | |
182 | } | |
183 | ||
184 | fn type_op_normalize<T>( | |
185 | infcx: &InferCtxt<'_, 'gcx, 'tcx>, | |
0731742a | 186 | fulfill_cx: &mut dyn TraitEngine<'tcx>, |
8faf50e0 XL |
187 | key: ParamEnvAnd<'tcx, Normalize<T>>, |
188 | ) -> Fallible<T> | |
189 | where | |
190 | T: fmt::Debug + TypeFoldable<'tcx> + Lift<'gcx>, | |
191 | { | |
192 | let (param_env, Normalize { value }) = key.into_parts(); | |
193 | let Normalized { value, obligations } = infcx | |
194 | .at(&ObligationCause::dummy(), param_env) | |
195 | .normalize(&value)?; | |
196 | fulfill_cx.register_predicate_obligations(infcx, obligations); | |
197 | Ok(value) | |
198 | } | |
199 | ||
200 | fn type_op_normalize_ty( | |
201 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
202 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Ty<'tcx>>>>, | |
0bf4aa26 | 203 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, Ty<'tcx>>>>, NoSolution> { |
8faf50e0 XL |
204 | tcx.infer_ctxt() |
205 | .enter_canonical_trait_query(&canonicalized, type_op_normalize) | |
206 | } | |
207 | ||
208 | fn type_op_normalize_predicate( | |
209 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
210 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<Predicate<'tcx>>>>, | |
0bf4aa26 | 211 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, Predicate<'tcx>>>>, NoSolution> { |
8faf50e0 XL |
212 | tcx.infer_ctxt() |
213 | .enter_canonical_trait_query(&canonicalized, type_op_normalize) | |
214 | } | |
215 | ||
216 | fn type_op_normalize_fn_sig( | |
217 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
218 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<FnSig<'tcx>>>>, | |
0bf4aa26 | 219 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, FnSig<'tcx>>>>, NoSolution> { |
8faf50e0 XL |
220 | tcx.infer_ctxt() |
221 | .enter_canonical_trait_query(&canonicalized, type_op_normalize) | |
222 | } | |
223 | ||
224 | fn type_op_normalize_poly_fn_sig( | |
225 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
226 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Normalize<PolyFnSig<'tcx>>>>, | |
0bf4aa26 | 227 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, PolyFnSig<'tcx>>>>, NoSolution> { |
8faf50e0 XL |
228 | tcx.infer_ctxt() |
229 | .enter_canonical_trait_query(&canonicalized, type_op_normalize) | |
230 | } | |
231 | ||
232 | fn type_op_subtype<'tcx>( | |
233 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
234 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, Subtype<'tcx>>>, | |
0bf4aa26 | 235 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> { |
8faf50e0 XL |
236 | tcx.infer_ctxt() |
237 | .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { | |
238 | let (param_env, Subtype { sub, sup }) = key.into_parts(); | |
239 | Ok(infcx | |
240 | .at(&ObligationCause::dummy(), param_env) | |
241 | .sup(sup, sub)? | |
242 | .into_value_registering_obligations(infcx, fulfill_cx)) | |
243 | }) | |
244 | } | |
245 | ||
246 | fn type_op_prove_predicate<'tcx>( | |
247 | tcx: TyCtxt<'_, 'tcx, 'tcx>, | |
248 | canonicalized: Canonical<'tcx, ParamEnvAnd<'tcx, ProvePredicate<'tcx>>>, | |
0bf4aa26 | 249 | ) -> Result<Lrc<Canonical<'tcx, QueryResponse<'tcx, ()>>>, NoSolution> { |
8faf50e0 XL |
250 | tcx.infer_ctxt() |
251 | .enter_canonical_trait_query(&canonicalized, |infcx, fulfill_cx, key| { | |
252 | let (param_env, ProvePredicate { predicate }) = key.into_parts(); | |
253 | fulfill_cx.register_predicate_obligation( | |
254 | infcx, | |
255 | Obligation::new(ObligationCause::dummy(), param_env, predicate), | |
256 | ); | |
257 | Ok(()) | |
258 | }) | |
259 | } |