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