]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
abe05a73 | 11 | use infer::{RegionObligation, InferCtxt, InferOk}; |
3b2f2976 | 12 | use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate}; |
cc61c64b | 13 | use ty::error::ExpectedFound; |
a7813a04 XL |
14 | use rustc_data_structures::obligation_forest::{ObligationForest, Error}; |
15 | use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor}; | |
16 | use std::marker::PhantomData; | |
476ff2be | 17 | use hir::def_id::DefId; |
1a4d82fc JJ |
18 | |
19 | use super::CodeAmbiguity; | |
20 | use super::CodeProjectionError; | |
21 | use super::CodeSelectionError; | |
8bb4bdeb XL |
22 | use super::{FulfillmentError, FulfillmentErrorCode}; |
23 | use super::{ObligationCause, PredicateObligation, Obligation}; | |
1a4d82fc JJ |
24 | use super::project; |
25 | use super::select::SelectionContext; | |
ea8adc8c | 26 | use super::{Unimplemented, ConstEvalFailure}; |
a7813a04 XL |
27 | |
28 | impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { | |
29 | type Predicate = ty::Predicate<'tcx>; | |
30 | ||
31 | fn as_predicate(&self) -> &Self::Predicate { &self.obligation.predicate } | |
32 | } | |
1a4d82fc JJ |
33 | |
34 | /// The fulfillment context is used to drive trait resolution. It | |
35 | /// consists of a list of obligations that must be (eventually) | |
36 | /// satisfied. The job is to track which are satisfied, which yielded | |
37 | /// errors, and which are still pending. At any point, users can call | |
3b2f2976 | 38 | /// `select_where_possible`, and the fulfillment context will try to do |
1a4d82fc JJ |
39 | /// selection, retaining only those obligations that remain |
40 | /// ambiguous. This may be helpful in pushing type inference | |
41 | /// along. Once all type inference constraints have been generated, the | |
42 | /// method `select_all_or_error` can be used to report any remaining | |
43 | /// ambiguous cases as errors. | |
5bcae85e | 44 | |
1a4d82fc | 45 | pub struct FulfillmentContext<'tcx> { |
1a4d82fc JJ |
46 | // A list of all obligations that have been registered with this |
47 | // fulfillment context. | |
a7813a04 | 48 | predicates: ObligationForest<PendingPredicateObligation<'tcx>>, |
1a4d82fc JJ |
49 | } |
50 | ||
7453a54e SL |
51 | #[derive(Clone, Debug)] |
52 | pub struct PendingPredicateObligation<'tcx> { | |
53 | pub obligation: PredicateObligation<'tcx>, | |
54 | pub stalled_on: Vec<Ty<'tcx>>, | |
55 | } | |
56 | ||
a7813a04 | 57 | impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { |
62682a34 | 58 | /// Creates a new fulfillment context. |
7453a54e | 59 | pub fn new() -> FulfillmentContext<'tcx> { |
1a4d82fc | 60 | FulfillmentContext { |
7453a54e | 61 | predicates: ObligationForest::new(), |
1a4d82fc JJ |
62 | } |
63 | } | |
64 | ||
65 | /// "Normalize" a projection type `<SomeType as SomeTrait>::X` by | |
66 | /// creating a fresh type variable `$0` as well as a projection | |
67 | /// predicate `<SomeType as SomeTrait>::X == $0`. When the | |
68 | /// inference engine runs, it will attempt to find an impl of | |
69 | /// `SomeTrait` or a where clause that lets us unify `$0` with | |
70 | /// something concrete. If this fails, we'll unify `$0` with | |
71 | /// `projection_ty` again. | |
a7813a04 XL |
72 | pub fn normalize_projection_type(&mut self, |
73 | infcx: &InferCtxt<'a, 'gcx, 'tcx>, | |
7cac9316 | 74 | param_env: ty::ParamEnv<'tcx>, |
a7813a04 XL |
75 | projection_ty: ty::ProjectionTy<'tcx>, |
76 | cause: ObligationCause<'tcx>) | |
77 | -> Ty<'tcx> | |
1a4d82fc | 78 | { |
7453a54e | 79 | debug!("normalize_projection_type(projection_ty={:?})", |
62682a34 | 80 | projection_ty); |
1a4d82fc JJ |
81 | |
82 | assert!(!projection_ty.has_escaping_regions()); | |
83 | ||
84 | // FIXME(#20304) -- cache | |
85 | ||
c1a9b12d | 86 | let mut selcx = SelectionContext::new(infcx); |
7cac9316 XL |
87 | let normalized = project::normalize_projection_type(&mut selcx, |
88 | param_env, | |
89 | projection_ty, | |
90 | cause, | |
91 | 0); | |
1a4d82fc | 92 | |
85aaf69f | 93 | for obligation in normalized.obligations { |
1a4d82fc JJ |
94 | self.register_predicate_obligation(infcx, obligation); |
95 | } | |
96 | ||
7453a54e | 97 | debug!("normalize_projection_type: result={:?}", normalized.value); |
1a4d82fc JJ |
98 | |
99 | normalized.value | |
100 | } | |
101 | ||
7cac9316 XL |
102 | /// Requires that `ty` must implement the trait with `def_id` in |
103 | /// the given environment. This trait must not have any type | |
104 | /// parameters (except for `Self`). | |
476ff2be SL |
105 | pub fn register_bound(&mut self, |
106 | infcx: &InferCtxt<'a, 'gcx, 'tcx>, | |
7cac9316 | 107 | param_env: ty::ParamEnv<'tcx>, |
476ff2be SL |
108 | ty: Ty<'tcx>, |
109 | def_id: DefId, | |
110 | cause: ObligationCause<'tcx>) | |
1a4d82fc | 111 | { |
476ff2be | 112 | let trait_ref = ty::TraitRef { |
041b39d2 | 113 | def_id, |
476ff2be SL |
114 | substs: infcx.tcx.mk_substs_trait(ty, &[]), |
115 | }; | |
116 | self.register_predicate_obligation(infcx, Obligation { | |
041b39d2 | 117 | cause, |
476ff2be | 118 | recursion_depth: 0, |
7cac9316 | 119 | param_env, |
476ff2be SL |
120 | predicate: trait_ref.to_predicate() |
121 | }); | |
1a4d82fc JJ |
122 | } |
123 | ||
a7813a04 XL |
124 | pub fn register_predicate_obligation(&mut self, |
125 | infcx: &InferCtxt<'a, 'gcx, 'tcx>, | |
126 | obligation: PredicateObligation<'tcx>) | |
1a4d82fc JJ |
127 | { |
128 | // this helps to reduce duplicate errors, as well as making | |
129 | // debug output much nicer to read and so on. | |
130 | let obligation = infcx.resolve_type_vars_if_possible(&obligation); | |
131 | ||
3157f602 XL |
132 | debug!("register_predicate_obligation(obligation={:?})", obligation); |
133 | ||
cc61c64b | 134 | assert!(!infcx.is_in_snapshot()); |
3157f602 | 135 | |
a7813a04 | 136 | self.predicates.register_obligation(PendingPredicateObligation { |
041b39d2 | 137 | obligation, |
7453a54e | 138 | stalled_on: vec![] |
a7813a04 XL |
139 | }); |
140 | } | |
141 | ||
abe05a73 XL |
142 | pub fn register_predicate_obligations<I>(&mut self, |
143 | infcx: &InferCtxt<'a, 'gcx, 'tcx>, | |
144 | obligations: I) | |
145 | where I: IntoIterator<Item = PredicateObligation<'tcx>> | |
cc61c64b XL |
146 | { |
147 | for obligation in obligations { | |
148 | self.register_predicate_obligation(infcx, obligation); | |
149 | } | |
150 | } | |
151 | ||
a7813a04 XL |
152 | pub fn select_all_or_error(&mut self, |
153 | infcx: &InferCtxt<'a, 'gcx, 'tcx>) | |
154 | -> Result<(),Vec<FulfillmentError<'tcx>>> | |
1a4d82fc | 155 | { |
54a0048b | 156 | self.select_where_possible(infcx)?; |
a7813a04 | 157 | |
7453a54e SL |
158 | let errors: Vec<_> = |
159 | self.predicates.to_errors(CodeAmbiguity) | |
160 | .into_iter() | |
161 | .map(|e| to_fulfillment_error(e)) | |
162 | .collect(); | |
1a4d82fc JJ |
163 | if errors.is_empty() { |
164 | Ok(()) | |
165 | } else { | |
166 | Err(errors) | |
167 | } | |
168 | } | |
169 | ||
a7813a04 XL |
170 | pub fn select_where_possible(&mut self, |
171 | infcx: &InferCtxt<'a, 'gcx, 'tcx>) | |
172 | -> Result<(),Vec<FulfillmentError<'tcx>>> | |
1a4d82fc | 173 | { |
c1a9b12d | 174 | let mut selcx = SelectionContext::new(infcx); |
7453a54e | 175 | self.select(&mut selcx) |
1a4d82fc JJ |
176 | } |
177 | ||
7453a54e SL |
178 | pub fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> { |
179 | self.predicates.pending_obligations() | |
1a4d82fc JJ |
180 | } |
181 | ||
182 | /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it | |
183 | /// only attempts to select obligations that haven't been seen before. | |
a7813a04 XL |
184 | fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>) |
185 | -> Result<(),Vec<FulfillmentError<'tcx>>> { | |
7453a54e | 186 | debug!("select(obligation-forest-size={})", self.predicates.len()); |
1a4d82fc JJ |
187 | |
188 | let mut errors = Vec::new(); | |
189 | ||
190 | loop { | |
7453a54e | 191 | debug!("select: starting another iteration"); |
1a4d82fc | 192 | |
7453a54e | 193 | // Process pending obligations. |
abe05a73 | 194 | let outcome = self.predicates.process_obligations(&mut FulfillProcessor { selcx }); |
7453a54e SL |
195 | debug!("select: outcome={:?}", outcome); |
196 | ||
3b2f2976 XL |
197 | // FIXME: if we kept the original cache key, we could mark projection |
198 | // obligations as complete for the projection cache here. | |
1a4d82fc | 199 | |
7453a54e SL |
200 | errors.extend( |
201 | outcome.errors.into_iter() | |
202 | .map(|e| to_fulfillment_error(e))); | |
1a4d82fc | 203 | |
7453a54e SL |
204 | // If nothing new was added, no need to keep looping. |
205 | if outcome.stalled { | |
1a4d82fc JJ |
206 | break; |
207 | } | |
1a4d82fc JJ |
208 | } |
209 | ||
7453a54e SL |
210 | debug!("select({} predicates remaining, {} errors) done", |
211 | self.predicates.len(), errors.len()); | |
1a4d82fc | 212 | |
9346a6ac | 213 | if errors.is_empty() { |
1a4d82fc JJ |
214 | Ok(()) |
215 | } else { | |
216 | Err(errors) | |
217 | } | |
218 | } | |
219 | } | |
220 | ||
a7813a04 XL |
221 | struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> { |
222 | selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>, | |
54a0048b SL |
223 | } |
224 | ||
a7813a04 XL |
225 | impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, 'tcx> { |
226 | type Obligation = PendingPredicateObligation<'tcx>; | |
227 | type Error = FulfillmentErrorCode<'tcx>; | |
7453a54e | 228 | |
a7813a04 XL |
229 | fn process_obligation(&mut self, |
230 | obligation: &mut Self::Obligation) | |
231 | -> Result<Option<Vec<Self::Obligation>>, Self::Error> | |
232 | { | |
abe05a73 | 233 | process_predicate(self.selcx, obligation) |
a7813a04 XL |
234 | .map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation { |
235 | obligation: o, | |
236 | stalled_on: vec![] | |
237 | }).collect())) | |
7453a54e | 238 | } |
7453a54e | 239 | |
a7813a04 XL |
240 | fn process_backedge<'c, I>(&mut self, cycle: I, |
241 | _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>) | |
242 | where I: Clone + Iterator<Item=&'c PendingPredicateObligation<'tcx>>, | |
243 | { | |
3b2f2976 | 244 | if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) { |
a7813a04 XL |
245 | debug!("process_child_obligations: coinductive match"); |
246 | } else { | |
247 | let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect(); | |
248 | self.selcx.infcx().report_overflow_error_cycle(&cycle); | |
54a0048b | 249 | } |
54a0048b SL |
250 | } |
251 | } | |
7453a54e SL |
252 | |
253 | /// Return the set of type variables contained in a trait ref | |
a7813a04 XL |
254 | fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>, |
255 | t: ty::PolyTraitRef<'tcx>) -> Vec<Ty<'tcx>> | |
7453a54e SL |
256 | { |
257 | t.skip_binder() // ok b/c this check doesn't care about regions | |
258 | .input_types() | |
9e0c209e | 259 | .map(|t| selcx.infcx().resolve_type_vars_if_possible(&t)) |
7453a54e SL |
260 | .filter(|t| t.has_infer_types()) |
261 | .flat_map(|t| t.walk()) | |
262 | .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false }) | |
263 | .collect() | |
264 | } | |
265 | ||
266 | /// Processes a predicate obligation and returns either: | |
267 | /// - `Ok(Some(v))` if the predicate is true, presuming that `v` are also true | |
268 | /// - `Ok(None)` if we don't have enough info to be sure | |
269 | /// - `Err` if the predicate does not hold | |
a7813a04 XL |
270 | fn process_predicate<'a, 'gcx, 'tcx>( |
271 | selcx: &mut SelectionContext<'a, 'gcx, 'tcx>, | |
abe05a73 | 272 | pending_obligation: &mut PendingPredicateObligation<'tcx>) |
a7813a04 XL |
273 | -> Result<Option<Vec<PredicateObligation<'tcx>>>, |
274 | FulfillmentErrorCode<'tcx>> | |
7453a54e SL |
275 | { |
276 | // if we were stalled on some unresolved variables, first check | |
277 | // whether any of them have been resolved; if not, don't bother | |
278 | // doing more work yet | |
279 | if !pending_obligation.stalled_on.is_empty() { | |
280 | if pending_obligation.stalled_on.iter().all(|&ty| { | |
281 | let resolved_ty = selcx.infcx().shallow_resolve(&ty); | |
282 | resolved_ty == ty // nothing changed here | |
283 | }) { | |
284 | debug!("process_predicate: pending obligation {:?} still stalled on {:?}", | |
285 | selcx.infcx().resolve_type_vars_if_possible(&pending_obligation.obligation), | |
286 | pending_obligation.stalled_on); | |
287 | return Ok(None); | |
288 | } | |
289 | pending_obligation.stalled_on = vec![]; | |
290 | } | |
291 | ||
292 | let obligation = &mut pending_obligation.obligation; | |
293 | ||
7453a54e SL |
294 | if obligation.predicate.has_infer_types() { |
295 | obligation.predicate = selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate); | |
296 | } | |
1a4d82fc | 297 | |
1a4d82fc JJ |
298 | match obligation.predicate { |
299 | ty::Predicate::Trait(ref data) => { | |
3b2f2976 XL |
300 | let trait_obligation = obligation.with(data.clone()); |
301 | ||
302 | if data.is_global() { | |
303 | // no type variables present, can use evaluation for better caching. | |
304 | // FIXME: consider caching errors too. | |
305 | if | |
306 | // make defaulted unit go through the slow path for better warnings, | |
307 | // please remove this when the warnings are removed. | |
308 | !trait_obligation.predicate.skip_binder().self_ty().is_defaulted_unit() && | |
309 | selcx.evaluate_obligation_conservatively(&obligation) { | |
310 | debug!("selecting trait `{:?}` at depth {} evaluated to holds", | |
311 | data, obligation.recursion_depth); | |
312 | return Ok(Some(vec![])) | |
313 | } | |
7453a54e SL |
314 | } |
315 | ||
1a4d82fc | 316 | match selcx.select(&trait_obligation) { |
7453a54e | 317 | Ok(Some(vtable)) => { |
a7813a04 | 318 | debug!("selecting trait `{:?}` at depth {} yielded Ok(Some)", |
3b2f2976 | 319 | data, obligation.recursion_depth); |
7453a54e | 320 | Ok(Some(vtable.nested_obligations())) |
1a4d82fc | 321 | } |
7453a54e | 322 | Ok(None) => { |
a7813a04 | 323 | debug!("selecting trait `{:?}` at depth {} yielded Ok(None)", |
3b2f2976 | 324 | data, obligation.recursion_depth); |
7453a54e SL |
325 | |
326 | // This is a bit subtle: for the most part, the | |
327 | // only reason we can fail to make progress on | |
328 | // trait selection is because we don't have enough | |
329 | // information about the types in the trait. One | |
330 | // exception is that we sometimes haven't decided | |
331 | // what kind of closure a closure is. *But*, in | |
332 | // that case, it turns out, the type of the | |
333 | // closure will also change, because the closure | |
334 | // also includes references to its upvars as part | |
335 | // of its type, and those types are resolved at | |
336 | // the same time. | |
3157f602 XL |
337 | // |
338 | // FIXME(#32286) logic seems false if no upvars | |
7453a54e SL |
339 | pending_obligation.stalled_on = |
340 | trait_ref_type_vars(selcx, data.to_poly_trait_ref()); | |
341 | ||
342 | debug!("process_predicate: pending obligation {:?} now stalled on {:?}", | |
343 | selcx.infcx().resolve_type_vars_if_possible(obligation), | |
344 | pending_obligation.stalled_on); | |
345 | ||
346 | Ok(None) | |
1a4d82fc JJ |
347 | } |
348 | Err(selection_err) => { | |
7453a54e SL |
349 | info!("selecting trait `{:?}` at depth {} yielded Err", |
350 | data, obligation.recursion_depth); | |
5bcae85e | 351 | |
8bb4bdeb | 352 | Err(CodeSelectionError(selection_err)) |
1a4d82fc JJ |
353 | } |
354 | } | |
355 | } | |
356 | ||
357 | ty::Predicate::Equate(ref binder) => { | |
7cac9316 XL |
358 | match selcx.infcx().equality_predicate(&obligation.cause, |
359 | obligation.param_env, | |
360 | binder) { | |
476ff2be SL |
361 | Ok(InferOk { obligations, value: () }) => { |
362 | Ok(Some(obligations)) | |
54a0048b | 363 | }, |
7453a54e | 364 | Err(_) => Err(CodeSelectionError(Unimplemented)), |
1a4d82fc | 365 | } |
1a4d82fc JJ |
366 | } |
367 | ||
368 | ty::Predicate::RegionOutlives(ref binder) => { | |
c30ab7b3 | 369 | match selcx.infcx().region_outlives_predicate(&obligation.cause, binder) { |
7453a54e SL |
370 | Ok(()) => Ok(Some(Vec::new())), |
371 | Err(_) => Err(CodeSelectionError(Unimplemented)), | |
1a4d82fc | 372 | } |
1a4d82fc JJ |
373 | } |
374 | ||
375 | ty::Predicate::TypeOutlives(ref binder) => { | |
c1a9b12d SL |
376 | // Check if there are higher-ranked regions. |
377 | match selcx.tcx().no_late_bound_regions(binder) { | |
378 | // If there are, inspect the underlying type further. | |
379 | None => { | |
380 | // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`. | |
381 | let binder = binder.map_bound_ref(|pred| pred.0); | |
382 | ||
383 | // Check if the type has any bound regions. | |
384 | match selcx.tcx().no_late_bound_regions(&binder) { | |
385 | // If so, this obligation is an error (for now). Eventually we should be | |
386 | // able to support additional cases here, like `for<'a> &'a str: 'a`. | |
387 | None => { | |
7453a54e | 388 | Err(CodeSelectionError(Unimplemented)) |
c1a9b12d SL |
389 | } |
390 | // Otherwise, we have something of the form | |
391 | // `for<'a> T: 'a where 'a not in T`, which we can treat as `T: 'static`. | |
392 | Some(t_a) => { | |
cc61c64b | 393 | let r_static = selcx.tcx().types.re_static; |
abe05a73 XL |
394 | selcx.infcx().register_region_obligation( |
395 | obligation.cause.body_id, | |
396 | RegionObligation { | |
397 | sup_type: t_a, | |
398 | sub_region: r_static, | |
399 | cause: obligation.cause.clone(), | |
400 | }); | |
7453a54e | 401 | Ok(Some(vec![])) |
c1a9b12d SL |
402 | } |
403 | } | |
404 | } | |
405 | // If there aren't, register the obligation. | |
406 | Some(ty::OutlivesPredicate(t_a, r_b)) => { | |
abe05a73 XL |
407 | selcx.infcx().register_region_obligation( |
408 | obligation.cause.body_id, | |
409 | RegionObligation { | |
410 | sup_type: t_a, | |
411 | sub_region: r_b, | |
412 | cause: obligation.cause.clone() | |
413 | }); | |
7453a54e | 414 | Ok(Some(vec![])) |
c1a9b12d | 415 | } |
1a4d82fc | 416 | } |
1a4d82fc JJ |
417 | } |
418 | ||
419 | ty::Predicate::Projection(ref data) => { | |
420 | let project_obligation = obligation.with(data.clone()); | |
7453a54e | 421 | match project::poly_project_and_unify_type(selcx, &project_obligation) { |
1a4d82fc | 422 | Ok(None) => { |
041b39d2 | 423 | let tcx = selcx.tcx(); |
7453a54e | 424 | pending_obligation.stalled_on = |
041b39d2 | 425 | trait_ref_type_vars(selcx, data.to_poly_trait_ref(tcx)); |
7453a54e | 426 | Ok(None) |
1a4d82fc | 427 | } |
7453a54e SL |
428 | Ok(v) => Ok(v), |
429 | Err(e) => Err(CodeProjectionError(e)) | |
1a4d82fc JJ |
430 | } |
431 | } | |
1a4d82fc | 432 | |
e9174d1e | 433 | ty::Predicate::ObjectSafe(trait_def_id) => { |
a7813a04 | 434 | if !selcx.tcx().is_object_safe(trait_def_id) { |
7453a54e SL |
435 | Err(CodeSelectionError(Unimplemented)) |
436 | } else { | |
437 | Ok(Some(Vec::new())) | |
e9174d1e | 438 | } |
e9174d1e SL |
439 | } |
440 | ||
a7813a04 XL |
441 | ty::Predicate::ClosureKind(closure_def_id, kind) => { |
442 | match selcx.infcx().closure_kind(closure_def_id) { | |
443 | Some(closure_kind) => { | |
444 | if closure_kind.extends(kind) { | |
445 | Ok(Some(vec![])) | |
446 | } else { | |
447 | Err(CodeSelectionError(Unimplemented)) | |
448 | } | |
449 | } | |
450 | None => { | |
451 | Ok(None) | |
452 | } | |
453 | } | |
454 | } | |
455 | ||
e9174d1e | 456 | ty::Predicate::WellFormed(ty) => { |
7cac9316 XL |
457 | match ty::wf::obligations(selcx.infcx(), |
458 | obligation.param_env, | |
459 | obligation.cause.body_id, | |
9cc50fc6 | 460 | ty, obligation.cause.span) { |
e9174d1e | 461 | None => { |
7453a54e SL |
462 | pending_obligation.stalled_on = vec![ty]; |
463 | Ok(None) | |
e9174d1e | 464 | } |
7453a54e | 465 | s => Ok(s) |
e9174d1e SL |
466 | } |
467 | } | |
cc61c64b XL |
468 | |
469 | ty::Predicate::Subtype(ref subtype) => { | |
7cac9316 XL |
470 | match selcx.infcx().subtype_predicate(&obligation.cause, |
471 | obligation.param_env, | |
472 | subtype) { | |
cc61c64b XL |
473 | None => { |
474 | // none means that both are unresolved | |
475 | pending_obligation.stalled_on = vec![subtype.skip_binder().a, | |
476 | subtype.skip_binder().b]; | |
477 | Ok(None) | |
478 | } | |
479 | Some(Ok(ok)) => { | |
480 | Ok(Some(ok.obligations)) | |
481 | } | |
482 | Some(Err(err)) => { | |
483 | let expected_found = ExpectedFound::new(subtype.skip_binder().a_is_expected, | |
484 | subtype.skip_binder().a, | |
485 | subtype.skip_binder().b); | |
486 | Err(FulfillmentErrorCode::CodeSubtypeError(expected_found, err)) | |
487 | } | |
488 | } | |
489 | } | |
ea8adc8c XL |
490 | |
491 | ty::Predicate::ConstEvaluatable(def_id, substs) => { | |
492 | match selcx.tcx().lift_to_global(&obligation.param_env) { | |
493 | None => { | |
494 | Ok(None) | |
495 | } | |
496 | Some(param_env) => { | |
497 | match selcx.tcx().lift_to_global(&substs) { | |
498 | None => { | |
499 | pending_obligation.stalled_on = substs.types().collect(); | |
500 | Ok(None) | |
501 | } | |
502 | Some(substs) => { | |
503 | match selcx.tcx().at(obligation.cause.span) | |
504 | .const_eval(param_env.and((def_id, substs))) { | |
505 | Ok(_) => Ok(Some(vec![])), | |
506 | Err(e) => Err(CodeSelectionError(ConstEvalFailure(e))) | |
507 | } | |
508 | } | |
509 | } | |
510 | } | |
511 | } | |
512 | } | |
1a4d82fc JJ |
513 | } |
514 | } | |
515 | ||
7453a54e SL |
516 | fn to_fulfillment_error<'tcx>( |
517 | error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>) | |
518 | -> FulfillmentError<'tcx> | |
519 | { | |
520 | let obligation = error.backtrace.into_iter().next().unwrap().obligation; | |
521 | FulfillmentError::new(obligation, error.error) | |
522 | } |