]> git.lizzy.rs Git - rust.git/blob - src/librustc/traits/fulfill.rs
Auto merge of #50710 - Zoxc:value_to_constvalue, r=oli-obk
[rust.git] / src / librustc / traits / fulfill.rs
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
11 use infer::{RegionObligation, InferCtxt};
12 use mir::interpret::GlobalId;
13 use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate};
14 use ty::error::ExpectedFound;
15 use rustc_data_structures::obligation_forest::{ObligationForest, Error};
16 use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor};
17 use std::marker::PhantomData;
18 use hir::def_id::DefId;
19 use middle::const_val::{ConstEvalErr, ErrKind};
20
21 use super::CodeAmbiguity;
22 use super::CodeProjectionError;
23 use super::CodeSelectionError;
24 use super::engine::TraitEngine;
25 use super::{FulfillmentError, FulfillmentErrorCode};
26 use super::{ObligationCause, PredicateObligation, Obligation};
27 use super::project;
28 use super::select::SelectionContext;
29 use super::{Unimplemented, ConstEvalFailure};
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 }
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
41 /// `select_where_possible`, and the fulfillment context will try to do
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.
47
48 pub struct FulfillmentContext<'tcx> {
49     // A list of all obligations that have been registered with this
50     // fulfillment context.
51     predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
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,
65 }
66
67 #[derive(Clone, Debug)]
68 pub struct PendingPredicateObligation<'tcx> {
69     pub obligation: PredicateObligation<'tcx>,
70     pub stalled_on: Vec<Ty<'tcx>>,
71 }
72
73 impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> {
74     /// Creates a new fulfillment context.
75     pub fn new() -> FulfillmentContext<'tcx> {
76         FulfillmentContext {
77             predicates: ObligationForest::new(),
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
86         }
87     }
88
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> {
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.
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>
155     {
156         debug!("normalize_projection_type(projection_ty={:?})",
157                projection_ty);
158
159         assert!(!projection_ty.has_escaping_regions());
160
161         // FIXME(#20304) -- cache
162
163         let mut selcx = SelectionContext::new(infcx);
164         let normalized = project::normalize_projection_type(&mut selcx,
165                                                             param_env,
166                                                             projection_ty,
167                                                             cause,
168                                                             0);
169
170         for obligation in normalized.obligations {
171             self.register_predicate_obligation(infcx, obligation);
172         }
173
174         debug!("normalize_projection_type: result={:?}", normalized.value);
175
176         normalized.value
177     }
178
179     /// Requires that `ty` must implement the trait with `def_id` in
180     /// the given environment. This trait must not have any type
181     /// parameters (except for `Self`).
182     fn register_bound<'a, 'gcx>(&mut self,
183                       infcx: &InferCtxt<'a, 'gcx, 'tcx>,
184                       param_env: ty::ParamEnv<'tcx>,
185                       ty: Ty<'tcx>,
186                       def_id: DefId,
187                       cause: ObligationCause<'tcx>)
188     {
189         let trait_ref = ty::TraitRef {
190             def_id,
191             substs: infcx.tcx.mk_substs_trait(ty, &[]),
192         };
193         self.register_predicate_obligation(infcx, Obligation {
194             cause,
195             recursion_depth: 0,
196             param_env,
197             predicate: trait_ref.to_predicate()
198         });
199     }
200
201     fn register_predicate_obligation<'a, 'gcx>(&mut self,
202                                      infcx: &InferCtxt<'a, 'gcx, 'tcx>,
203                                      obligation: PredicateObligation<'tcx>)
204     {
205         // this helps to reduce duplicate errors, as well as making
206         // debug output much nicer to read and so on.
207         let obligation = infcx.resolve_type_vars_if_possible(&obligation);
208
209         debug!("register_predicate_obligation(obligation={:?})", obligation);
210
211         assert!(!infcx.is_in_snapshot());
212
213         self.predicates.register_obligation(PendingPredicateObligation {
214             obligation,
215             stalled_on: vec![]
216         });
217     }
218
219     fn select_all_or_error<'a, 'gcx>(&mut self,
220                                      infcx: &InferCtxt<'a, 'gcx, 'tcx>)
221                                      -> Result<(),Vec<FulfillmentError<'tcx>>>
222     {
223         self.select_where_possible(infcx)?;
224
225         let errors: Vec<_> =
226             self.predicates.to_errors(CodeAmbiguity)
227                            .into_iter()
228                            .map(|e| to_fulfillment_error(e))
229                            .collect();
230         if errors.is_empty() {
231             Ok(())
232         } else {
233             Err(errors)
234         }
235     }
236
237     fn select_where_possible<'a, 'gcx>(&mut self,
238                              infcx: &InferCtxt<'a, 'gcx, 'tcx>)
239                              -> Result<(),Vec<FulfillmentError<'tcx>>>
240     {
241         let mut selcx = SelectionContext::new(infcx);
242         self.select(&mut selcx)
243     }
244
245     fn pending_obligations(&self) -> Vec<PendingPredicateObligation<'tcx>> {
246         self.predicates.pending_obligations()
247     }
248 }
249
250 struct FulfillProcessor<'a, 'b: 'a, 'gcx: 'tcx, 'tcx: 'b> {
251     selcx: &'a mut SelectionContext<'b, 'gcx, 'tcx>,
252     register_region_obligations: bool
253 }
254
255 impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx, 'tcx> {
256     type Obligation = PendingPredicateObligation<'tcx>;
257     type Error = FulfillmentErrorCode<'tcx>;
258
259     fn process_obligation(&mut self,
260                           obligation: &mut Self::Obligation)
261                           -> Result<Option<Vec<Self::Obligation>>, Self::Error>
262     {
263         process_predicate(self.selcx, obligation, self.register_region_obligations)
264             .map(|os| os.map(|os| os.into_iter().map(|o| PendingPredicateObligation {
265                 obligation: o,
266                 stalled_on: vec![]
267             }).collect()))
268     }
269
270     fn process_backedge<'c, I>(&mut self, cycle: I,
271                                _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>)
272         where I: Clone + Iterator<Item=&'c PendingPredicateObligation<'tcx>>,
273     {
274         if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
275             debug!("process_child_obligations: coinductive match");
276         } else {
277             let cycle : Vec<_> = cycle.map(|c| c.obligation.clone()).collect();
278             self.selcx.infcx().report_overflow_error_cycle(&cycle);
279         }
280     }
281 }
282
283 /// Return the set of type variables contained in a trait ref
284 fn trait_ref_type_vars<'a, 'gcx, 'tcx>(selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
285                                        t: ty::PolyTraitRef<'tcx>) -> Vec<Ty<'tcx>>
286 {
287     t.skip_binder() // ok b/c this check doesn't care about regions
288      .input_types()
289      .map(|t| selcx.infcx().resolve_type_vars_if_possible(&t))
290      .filter(|t| t.has_infer_types())
291      .flat_map(|t| t.walk())
292      .filter(|t| match t.sty { ty::TyInfer(_) => true, _ => false })
293      .collect()
294 }
295
296 /// Processes a predicate obligation and returns either:
297 /// - `Ok(Some(v))` if the predicate is true, presuming that `v` are also true
298 /// - `Ok(None)` if we don't have enough info to be sure
299 /// - `Err` if the predicate does not hold
300 fn process_predicate<'a, 'gcx, 'tcx>(
301     selcx: &mut SelectionContext<'a, 'gcx, 'tcx>,
302     pending_obligation: &mut PendingPredicateObligation<'tcx>,
303     register_region_obligations: bool)
304     -> Result<Option<Vec<PredicateObligation<'tcx>>>,
305               FulfillmentErrorCode<'tcx>>
306 {
307     // if we were stalled on some unresolved variables, first check
308     // whether any of them have been resolved; if not, don't bother
309     // doing more work yet
310     if !pending_obligation.stalled_on.is_empty() {
311         if pending_obligation.stalled_on.iter().all(|&ty| {
312             let resolved_ty = selcx.infcx().shallow_resolve(&ty);
313             resolved_ty == ty // nothing changed here
314         }) {
315             debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
316                    selcx.infcx().resolve_type_vars_if_possible(&pending_obligation.obligation),
317                    pending_obligation.stalled_on);
318             return Ok(None);
319         }
320         pending_obligation.stalled_on = vec![];
321     }
322
323     let obligation = &mut pending_obligation.obligation;
324
325     if obligation.predicate.has_infer_types() {
326         obligation.predicate = selcx.infcx().resolve_type_vars_if_possible(&obligation.predicate);
327     }
328
329     match obligation.predicate {
330         ty::Predicate::Trait(ref data) => {
331             let trait_obligation = obligation.with(data.clone());
332
333             if data.is_global() && !data.has_late_bound_regions() {
334                 // no type variables present, can use evaluation for better caching.
335                 // FIXME: consider caching errors too.
336                 if selcx.infcx().predicate_must_hold(&obligation) {
337                     debug!("selecting trait `{:?}` at depth {} evaluated to holds",
338                            data, obligation.recursion_depth);
339                     return Ok(Some(vec![]))
340                 }
341             }
342
343             match selcx.select(&trait_obligation) {
344                 Ok(Some(vtable)) => {
345                     debug!("selecting trait `{:?}` at depth {} yielded Ok(Some)",
346                            data, obligation.recursion_depth);
347                     Ok(Some(vtable.nested_obligations()))
348                 }
349                 Ok(None) => {
350                     debug!("selecting trait `{:?}` at depth {} yielded Ok(None)",
351                            data, obligation.recursion_depth);
352
353                     // This is a bit subtle: for the most part, the
354                     // only reason we can fail to make progress on
355                     // trait selection is because we don't have enough
356                     // information about the types in the trait. One
357                     // exception is that we sometimes haven't decided
358                     // what kind of closure a closure is. *But*, in
359                     // that case, it turns out, the type of the
360                     // closure will also change, because the closure
361                     // also includes references to its upvars as part
362                     // of its type, and those types are resolved at
363                     // the same time.
364                     //
365                     // FIXME(#32286) logic seems false if no upvars
366                     pending_obligation.stalled_on =
367                         trait_ref_type_vars(selcx, data.to_poly_trait_ref());
368
369                     debug!("process_predicate: pending obligation {:?} now stalled on {:?}",
370                            selcx.infcx().resolve_type_vars_if_possible(obligation),
371                            pending_obligation.stalled_on);
372
373                     Ok(None)
374                 }
375                 Err(selection_err) => {
376                     info!("selecting trait `{:?}` at depth {} yielded Err",
377                           data, obligation.recursion_depth);
378
379                     Err(CodeSelectionError(selection_err))
380                 }
381             }
382         }
383
384         ty::Predicate::RegionOutlives(ref binder) => {
385             match selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
386                 Ok(()) => Ok(Some(Vec::new())),
387                 Err(_) => Err(CodeSelectionError(Unimplemented)),
388             }
389         }
390
391         ty::Predicate::TypeOutlives(ref binder) => {
392             // Check if there are higher-ranked regions.
393             match binder.no_late_bound_regions() {
394                 // If there are, inspect the underlying type further.
395                 None => {
396                     // Convert from `Binder<OutlivesPredicate<Ty, Region>>` to `Binder<Ty>`.
397                     let binder = binder.map_bound_ref(|pred| pred.0);
398
399                     // Check if the type has any bound regions.
400                     match binder.no_late_bound_regions() {
401                         // If so, this obligation is an error (for now). Eventually we should be
402                         // able to support additional cases here, like `for<'a> &'a str: 'a`.
403                         None => {
404                             Err(CodeSelectionError(Unimplemented))
405                         }
406                         // Otherwise, we have something of the form
407                         // `for<'a> T: 'a where 'a not in T`, which we can treat as `T: 'static`.
408                         Some(t_a) => {
409                             let r_static = selcx.tcx().types.re_static;
410                             if register_region_obligations {
411                                 selcx.infcx().register_region_obligation(
412                                     obligation.cause.body_id,
413                                     RegionObligation {
414                                         sup_type: t_a,
415                                         sub_region: r_static,
416                                         cause: obligation.cause.clone(),
417                                     });
418                             }
419                             Ok(Some(vec![]))
420                         }
421                     }
422                 }
423                 // If there aren't, register the obligation.
424                 Some(ty::OutlivesPredicate(t_a, r_b)) => {
425                     if register_region_obligations {
426                         selcx.infcx().register_region_obligation(
427                             obligation.cause.body_id,
428                             RegionObligation {
429                                 sup_type: t_a,
430                                 sub_region: r_b,
431                                 cause: obligation.cause.clone()
432                             });
433                     }
434                     Ok(Some(vec![]))
435                 }
436             }
437         }
438
439         ty::Predicate::Projection(ref data) => {
440             let project_obligation = obligation.with(data.clone());
441             match project::poly_project_and_unify_type(selcx, &project_obligation) {
442                 Ok(None) => {
443                     let tcx = selcx.tcx();
444                     pending_obligation.stalled_on =
445                         trait_ref_type_vars(selcx, data.to_poly_trait_ref(tcx));
446                     Ok(None)
447                 }
448                 Ok(v) => Ok(v),
449                 Err(e) => Err(CodeProjectionError(e))
450             }
451         }
452
453         ty::Predicate::ObjectSafe(trait_def_id) => {
454             if !selcx.tcx().is_object_safe(trait_def_id) {
455                 Err(CodeSelectionError(Unimplemented))
456             } else {
457                 Ok(Some(Vec::new()))
458             }
459         }
460
461         ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => {
462             match selcx.infcx().closure_kind(closure_def_id, closure_substs) {
463                 Some(closure_kind) => {
464                     if closure_kind.extends(kind) {
465                         Ok(Some(vec![]))
466                     } else {
467                         Err(CodeSelectionError(Unimplemented))
468                     }
469                 }
470                 None => {
471                     Ok(None)
472                 }
473             }
474         }
475
476         ty::Predicate::WellFormed(ty) => {
477             match ty::wf::obligations(selcx.infcx(),
478                                       obligation.param_env,
479                                       obligation.cause.body_id,
480                                       ty, obligation.cause.span) {
481                 None => {
482                     pending_obligation.stalled_on = vec![ty];
483                     Ok(None)
484                 }
485                 s => Ok(s)
486             }
487         }
488
489         ty::Predicate::Subtype(ref subtype) => {
490             match selcx.infcx().subtype_predicate(&obligation.cause,
491                                                   obligation.param_env,
492                                                   subtype) {
493                 None => {
494                     // none means that both are unresolved
495                     pending_obligation.stalled_on = vec![subtype.skip_binder().a,
496                                                          subtype.skip_binder().b];
497                     Ok(None)
498                 }
499                 Some(Ok(ok)) => {
500                     Ok(Some(ok.obligations))
501                 }
502                 Some(Err(err)) => {
503                     let expected_found = ExpectedFound::new(subtype.skip_binder().a_is_expected,
504                                                             subtype.skip_binder().a,
505                                                             subtype.skip_binder().b);
506                     Err(FulfillmentErrorCode::CodeSubtypeError(expected_found, err))
507                 }
508             }
509         }
510
511         ty::Predicate::ConstEvaluatable(def_id, substs) => {
512             match selcx.tcx().lift_to_global(&obligation.param_env) {
513                 None => {
514                     Ok(None)
515                 }
516                 Some(param_env) => {
517                     match selcx.tcx().lift_to_global(&substs) {
518                         Some(substs) => {
519                             let instance = ty::Instance::resolve(
520                                 selcx.tcx().global_tcx(),
521                                 param_env,
522                                 def_id,
523                                 substs,
524                             );
525                             if let Some(instance) = instance {
526                                 let cid = GlobalId {
527                                     instance,
528                                     promoted: None,
529                                 };
530                                 match selcx.tcx().at(obligation.cause.span)
531                                                  .const_eval(param_env.and(cid)) {
532                                     Ok(_) => Ok(Some(vec![])),
533                                     Err(err) => Err(CodeSelectionError(ConstEvalFailure(err)))
534                                 }
535                             } else {
536                                 Err(CodeSelectionError(ConstEvalFailure(ConstEvalErr {
537                                     span: obligation.cause.span,
538                                     kind: ErrKind::UnimplementedConstVal("could not resolve")
539                                         .into(),
540                                 })))
541                             }
542                         },
543                         None => {
544                             pending_obligation.stalled_on = substs.types().collect();
545                             Ok(None)
546                         }
547                     }
548                 }
549             }
550         }
551     }
552 }
553
554 fn to_fulfillment_error<'tcx>(
555     error: Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>)
556     -> FulfillmentError<'tcx>
557 {
558     let obligation = error.backtrace.into_iter().next().unwrap().obligation;
559     FulfillmentError::new(obligation, error.error)
560 }