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