2014-09-12 10:53:35 -04:00
|
|
|
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-12-17 14:16:28 -05:00
|
|
|
use middle::infer::{mod, InferCtxt};
|
2014-09-18 11:08:04 -04:00
|
|
|
use middle::mem_categorization::Typer;
|
2014-12-17 14:16:28 -05:00
|
|
|
use middle::ty::{mod, AsPredicate, RegionEscape, Ty, ToPolyTraitRef};
|
2014-11-07 16:14:32 -05:00
|
|
|
use std::collections::HashSet;
|
2014-12-13 11:15:18 -05:00
|
|
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
2014-12-05 02:57:17 -05:00
|
|
|
use std::default::Default;
|
2014-11-07 16:14:32 -05:00
|
|
|
use std::rc::Rc;
|
2014-12-05 02:57:17 -05:00
|
|
|
use syntax::ast;
|
2014-12-07 11:10:48 -05:00
|
|
|
use util::common::ErrorReported;
|
2014-09-12 10:53:35 -04:00
|
|
|
use util::ppaux::Repr;
|
2014-12-05 02:57:17 -05:00
|
|
|
use util::nodemap::NodeMap;
|
2014-09-12 10:53:35 -04:00
|
|
|
|
2014-09-11 17:07:49 +12:00
|
|
|
use super::CodeAmbiguity;
|
2014-12-17 14:16:28 -05:00
|
|
|
use super::CodeProjectionError;
|
2014-12-07 11:10:48 -05:00
|
|
|
use super::CodeSelectionError;
|
|
|
|
use super::FulfillmentError;
|
2014-12-06 01:30:41 -05:00
|
|
|
use super::Obligation;
|
|
|
|
use super::ObligationCause;
|
2014-12-07 11:10:48 -05:00
|
|
|
use super::PredicateObligation;
|
2014-12-17 14:16:28 -05:00
|
|
|
use super::project;
|
2014-09-12 10:53:35 -04:00
|
|
|
use super::select::SelectionContext;
|
2014-12-07 11:10:48 -05:00
|
|
|
use super::Unimplemented;
|
2014-12-17 14:16:28 -05:00
|
|
|
use super::util::predicate_for_builtin_bound;
|
2014-09-12 10:53:35 -04:00
|
|
|
|
2014-11-24 20:06:06 -05:00
|
|
|
/// The fulfillment context is used to drive trait resolution. It
|
|
|
|
/// consists of a list of obligations that must be (eventually)
|
|
|
|
/// satisfied. The job is to track which are satisfied, which yielded
|
|
|
|
/// errors, and which are still pending. At any point, users can call
|
|
|
|
/// `select_where_possible`, and the fulfilment context will try to do
|
|
|
|
/// selection, retaining only those obligations that remain
|
|
|
|
/// ambiguous. This may be helpful in pushing type inference
|
|
|
|
/// along. Once all type inference constraints have been generated, the
|
|
|
|
/// method `select_all_or_error` can be used to report any remaining
|
|
|
|
/// ambiguous cases as errors.
|
2014-09-29 22:11:30 +03:00
|
|
|
pub struct FulfillmentContext<'tcx> {
|
2014-11-07 16:14:32 -05:00
|
|
|
// a simple cache that aims to cache *exact duplicate obligations*
|
|
|
|
// and avoid adding them twice. This serves a different purpose
|
|
|
|
// than the `SelectionCache`: it avoids duplicate errors and
|
|
|
|
// permits recursive obligations, which are often generated from
|
|
|
|
// traits like `Send` et al.
|
2014-12-07 11:10:48 -05:00
|
|
|
duplicate_set: HashSet<ty::Predicate<'tcx>>,
|
2014-11-07 16:14:32 -05:00
|
|
|
|
2014-09-12 10:53:35 -04:00
|
|
|
// A list of all obligations that have been registered with this
|
|
|
|
// fulfillment context.
|
2014-12-07 11:10:48 -05:00
|
|
|
predicates: Vec<PredicateObligation<'tcx>>,
|
2014-10-28 07:13:15 -04:00
|
|
|
|
|
|
|
// Remembers the count of trait obligations that we have already
|
|
|
|
// attempted to select. This is used to avoid repeating work
|
|
|
|
// when `select_new_obligations` is called.
|
|
|
|
attempted_mark: uint,
|
2014-12-05 02:57:17 -05:00
|
|
|
|
|
|
|
// A set of constraints that regionck must validate. Each
|
|
|
|
// constraint has the form `T:'a`, meaning "some type `T` must
|
|
|
|
// outlive the lifetime 'a". These constraints derive from
|
|
|
|
// instantiated type parameters. So if you had a struct defined
|
|
|
|
// like
|
|
|
|
//
|
|
|
|
// struct Foo<T:'static> { ... }
|
|
|
|
//
|
|
|
|
// then in some expression `let x = Foo { ... }` it will
|
|
|
|
// instantiate the type parameter `T` with a fresh type `$0`. At
|
|
|
|
// the same time, it will record a region obligation of
|
|
|
|
// `$0:'static`. This will get checked later by regionck. (We
|
|
|
|
// can't generally check these things right away because we have
|
|
|
|
// to wait until types are resolved.)
|
|
|
|
//
|
|
|
|
// These are stored in a map keyed to the id of the innermost
|
|
|
|
// enclosing fn body / static initializer expression. This is
|
|
|
|
// because the location where the obligation was incurred can be
|
|
|
|
// relevant with respect to which sublifetime assumptions are in
|
|
|
|
// place. The reason that we store under the fn-id, and not
|
|
|
|
// something more fine-grained, is so that it is easier for
|
|
|
|
// regionck to be sure that it has found *all* the region
|
|
|
|
// obligations (otherwise, it's easy to fail to walk to a
|
|
|
|
// particular node-id).
|
|
|
|
region_obligations: NodeMap<Vec<RegionObligation<'tcx>>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct RegionObligation<'tcx> {
|
|
|
|
pub sub_region: ty::Region,
|
|
|
|
pub sup_type: Ty<'tcx>,
|
2014-12-06 01:30:41 -05:00
|
|
|
pub cause: ObligationCause<'tcx>,
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
impl<'tcx> FulfillmentContext<'tcx> {
|
|
|
|
pub fn new() -> FulfillmentContext<'tcx> {
|
2014-09-12 10:53:35 -04:00
|
|
|
FulfillmentContext {
|
2014-11-07 16:14:32 -05:00
|
|
|
duplicate_set: HashSet::new(),
|
2014-12-07 11:10:48 -05:00
|
|
|
predicates: Vec::new(),
|
2014-10-28 07:13:15 -04:00
|
|
|
attempted_mark: 0,
|
2014-12-05 02:57:17 -05:00
|
|
|
region_obligations: NodeMap::new(),
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-17 14:16:28 -05:00
|
|
|
pub fn normalize_associated_type<'a>(&mut self,
|
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
|
|
|
trait_ref: Rc<ty::TraitRef<'tcx>>,
|
|
|
|
item_name: ast::Name,
|
|
|
|
cause: ObligationCause<'tcx>)
|
|
|
|
-> Ty<'tcx>
|
|
|
|
{
|
|
|
|
assert!(!trait_ref.has_escaping_regions());
|
|
|
|
|
|
|
|
let ty_var = infcx.next_ty_var();
|
|
|
|
let projection =
|
|
|
|
ty::Binder(ty::ProjectionPredicate {
|
|
|
|
projection_ty: ty::ProjectionTy { trait_ref: trait_ref,
|
|
|
|
item_name: item_name },
|
|
|
|
ty: ty_var
|
|
|
|
});
|
|
|
|
let obligation = Obligation::new(cause, projection.as_predicate());
|
2014-12-27 04:22:29 -05:00
|
|
|
self.register_predicate(infcx, obligation);
|
2014-12-17 14:16:28 -05:00
|
|
|
ty_var
|
|
|
|
}
|
|
|
|
|
2014-12-27 04:22:29 -05:00
|
|
|
pub fn register_builtin_bound<'a>(&mut self,
|
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
|
|
|
ty: Ty<'tcx>,
|
|
|
|
builtin_bound: ty::BuiltinBound,
|
|
|
|
cause: ObligationCause<'tcx>)
|
2014-12-06 01:30:41 -05:00
|
|
|
{
|
2014-12-27 04:22:29 -05:00
|
|
|
match predicate_for_builtin_bound(infcx.tcx, cause, builtin_bound, 0, ty) {
|
2014-12-17 14:16:28 -05:00
|
|
|
Ok(predicate) => {
|
2014-12-27 04:22:29 -05:00
|
|
|
self.register_predicate(infcx, predicate);
|
2014-12-06 01:30:41 -05:00
|
|
|
}
|
2014-12-07 11:10:48 -05:00
|
|
|
Err(ErrorReported) => { }
|
2014-12-06 01:30:41 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-27 04:22:29 -05:00
|
|
|
pub fn register_region_obligation<'a>(&mut self,
|
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
|
|
|
t_a: Ty<'tcx>,
|
|
|
|
r_b: ty::Region,
|
|
|
|
cause: ObligationCause<'tcx>)
|
2014-12-05 02:57:17 -05:00
|
|
|
{
|
2014-12-27 04:22:29 -05:00
|
|
|
register_region_obligation(infcx.tcx, t_a, r_b, cause, &mut self.region_obligations);
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn register_predicate<'a>(&mut self,
|
2014-12-27 04:22:29 -05:00
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation: PredicateObligation<'tcx>)
|
2014-12-07 11:10:48 -05:00
|
|
|
{
|
2014-12-17 16:00:34 -05:00
|
|
|
if !self.duplicate_set.insert(obligation.predicate.clone()) {
|
2014-12-27 04:22:29 -05:00
|
|
|
debug!("register_predicate({}) -- already seen, skip", obligation.repr(infcx.tcx));
|
2014-12-07 11:10:48 -05:00
|
|
|
return;
|
2014-12-05 02:57:17 -05:00
|
|
|
}
|
2014-12-07 11:10:48 -05:00
|
|
|
|
2014-12-27 04:22:29 -05:00
|
|
|
debug!("register_predicate({})", obligation.repr(infcx.tcx));
|
2014-12-17 16:00:34 -05:00
|
|
|
self.predicates.push(obligation);
|
2014-12-05 02:57:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn region_obligations(&self,
|
|
|
|
body_id: ast::NodeId)
|
|
|
|
-> &[RegionObligation<'tcx>]
|
|
|
|
{
|
|
|
|
match self.region_obligations.get(&body_id) {
|
|
|
|
None => Default::default(),
|
|
|
|
Some(vec) => vec.as_slice(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn select_all_or_error<'a>(&mut self,
|
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
|
|
|
param_env: &ty::ParameterEnvironment<'tcx>,
|
|
|
|
typer: &Typer<'tcx>)
|
|
|
|
-> Result<(),Vec<FulfillmentError<'tcx>>>
|
2014-09-12 10:53:35 -04:00
|
|
|
{
|
2014-09-18 11:08:04 -04:00
|
|
|
try!(self.select_where_possible(infcx, param_env, typer));
|
2014-09-12 10:53:35 -04:00
|
|
|
|
|
|
|
// Anything left is ambiguous.
|
|
|
|
let errors: Vec<FulfillmentError> =
|
2014-12-07 11:10:48 -05:00
|
|
|
self.predicates
|
2014-09-12 10:53:35 -04:00
|
|
|
.iter()
|
2014-09-11 17:07:49 +12:00
|
|
|
.map(|o| FulfillmentError::new((*o).clone(), CodeAmbiguity))
|
2014-09-12 10:53:35 -04:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
if errors.is_empty() {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(errors)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-25 21:17:11 -05:00
|
|
|
/// Attempts to select obligations that were registered since the call to a selection routine.
|
|
|
|
/// This is used by the type checker to eagerly attempt to resolve obligations in hopes of
|
|
|
|
/// gaining type information. It'd be equally valid to use `select_where_possible` but it
|
|
|
|
/// results in `O(n^2)` performance (#18208).
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn select_new_obligations<'a>(&mut self,
|
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
|
|
|
param_env: &ty::ParameterEnvironment<'tcx>,
|
|
|
|
typer: &Typer<'tcx>)
|
|
|
|
-> Result<(),Vec<FulfillmentError<'tcx>>>
|
2014-10-28 07:13:15 -04:00
|
|
|
{
|
|
|
|
let mut selcx = SelectionContext::new(infcx, param_env, typer);
|
|
|
|
self.select(&mut selcx, true)
|
|
|
|
}
|
|
|
|
|
2014-09-29 22:11:30 +03:00
|
|
|
pub fn select_where_possible<'a>(&mut self,
|
|
|
|
infcx: &InferCtxt<'a,'tcx>,
|
|
|
|
param_env: &ty::ParameterEnvironment<'tcx>,
|
|
|
|
typer: &Typer<'tcx>)
|
|
|
|
-> Result<(),Vec<FulfillmentError<'tcx>>>
|
2014-09-12 10:53:35 -04:00
|
|
|
{
|
2014-09-18 11:08:04 -04:00
|
|
|
let mut selcx = SelectionContext::new(infcx, param_env, typer);
|
2014-10-28 07:13:15 -04:00
|
|
|
self.select(&mut selcx, false)
|
|
|
|
}
|
2014-09-12 10:53:35 -04:00
|
|
|
|
2014-12-07 11:10:48 -05:00
|
|
|
pub fn pending_obligations(&self) -> &[PredicateObligation<'tcx>] {
|
|
|
|
self.predicates[]
|
2014-11-18 16:13:24 -05:00
|
|
|
}
|
|
|
|
|
2014-11-25 21:17:11 -05:00
|
|
|
/// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
|
|
|
|
/// only attempts to select obligations that haven't been seen before.
|
2014-09-29 22:11:30 +03:00
|
|
|
fn select<'a>(&mut self,
|
|
|
|
selcx: &mut SelectionContext<'a, 'tcx>,
|
|
|
|
only_new_obligations: bool)
|
|
|
|
-> Result<(),Vec<FulfillmentError<'tcx>>>
|
2014-10-28 07:13:15 -04:00
|
|
|
{
|
|
|
|
debug!("select({} obligations, only_new_obligations={}) start",
|
2014-12-07 11:10:48 -05:00
|
|
|
self.predicates.len(),
|
2014-10-28 07:13:15 -04:00
|
|
|
only_new_obligations);
|
2014-09-12 10:53:35 -04:00
|
|
|
|
|
|
|
let mut errors = Vec::new();
|
|
|
|
|
|
|
|
loop {
|
2014-12-07 11:10:48 -05:00
|
|
|
let count = self.predicates.len();
|
2014-09-12 10:53:35 -04:00
|
|
|
|
|
|
|
debug!("select_where_possible({} obligations) iteration",
|
|
|
|
count);
|
|
|
|
|
2014-12-17 14:16:28 -05:00
|
|
|
let mut new_obligations = Vec::new();
|
2014-09-12 10:53:35 -04:00
|
|
|
|
2014-10-28 07:13:15 -04:00
|
|
|
// If we are only attempting obligations we haven't seen yet,
|
|
|
|
// then set `skip` to the number of obligations we've already
|
|
|
|
// seen.
|
|
|
|
let mut skip = if only_new_obligations {
|
|
|
|
self.attempted_mark
|
|
|
|
} else {
|
|
|
|
0
|
|
|
|
};
|
|
|
|
|
2014-09-12 10:53:35 -04:00
|
|
|
// First pass: walk each obligation, retaining
|
|
|
|
// only those that we cannot yet process.
|
2014-12-07 11:10:48 -05:00
|
|
|
{
|
|
|
|
let region_obligations = &mut self.region_obligations;
|
|
|
|
self.predicates.retain(|predicate| {
|
|
|
|
// Hack: Retain does not pass in the index, but we want
|
|
|
|
// to avoid processing the first `start_count` entries.
|
2014-12-11 04:35:51 -05:00
|
|
|
let processed =
|
|
|
|
if skip == 0 {
|
|
|
|
process_predicate(selcx, predicate,
|
2014-12-17 14:16:28 -05:00
|
|
|
&mut new_obligations, &mut errors, region_obligations)
|
2014-12-11 04:35:51 -05:00
|
|
|
} else {
|
|
|
|
skip -= 1;
|
|
|
|
false
|
|
|
|
};
|
|
|
|
!processed
|
2014-12-07 11:10:48 -05:00
|
|
|
});
|
|
|
|
}
|
2014-09-12 10:53:35 -04:00
|
|
|
|
2014-12-07 11:10:48 -05:00
|
|
|
self.attempted_mark = self.predicates.len();
|
2014-10-28 07:13:15 -04:00
|
|
|
|
2014-12-07 11:10:48 -05:00
|
|
|
if self.predicates.len() == count {
|
2014-09-12 10:53:35 -04:00
|
|
|
// Nothing changed.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now go through all the successful ones,
|
|
|
|
// registering any nested obligations for the future.
|
2014-12-17 14:16:28 -05:00
|
|
|
for new_obligation in new_obligations.into_iter() {
|
2014-12-27 04:22:29 -05:00
|
|
|
self.register_predicate(selcx.infcx(), new_obligation);
|
2014-09-12 10:53:35 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-28 07:13:15 -04:00
|
|
|
debug!("select({} obligations, {} errors) done",
|
2014-12-07 11:10:48 -05:00
|
|
|
self.predicates.len(),
|
2014-09-12 10:53:35 -04:00
|
|
|
errors.len());
|
|
|
|
|
|
|
|
if errors.len() == 0 {
|
|
|
|
Ok(())
|
|
|
|
} else {
|
|
|
|
Err(errors)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-05 02:57:17 -05:00
|
|
|
|
2014-12-11 04:35:51 -05:00
|
|
|
fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation: &PredicateObligation<'tcx>,
|
2014-12-17 14:16:28 -05:00
|
|
|
new_obligations: &mut Vec<PredicateObligation<'tcx>>,
|
2014-12-11 04:35:51 -05:00
|
|
|
errors: &mut Vec<FulfillmentError<'tcx>>,
|
|
|
|
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
|
|
|
|
-> bool
|
2014-12-07 11:10:48 -05:00
|
|
|
{
|
|
|
|
/*!
|
2014-12-11 04:35:51 -05:00
|
|
|
* Processes a predicate obligation and modifies the appropriate
|
|
|
|
* output array with the successful/error result. Returns `false`
|
|
|
|
* if the predicate could not be processed due to insufficient
|
2014-12-07 11:10:48 -05:00
|
|
|
* type inference.
|
|
|
|
*/
|
|
|
|
|
|
|
|
let tcx = selcx.tcx();
|
2014-12-17 16:00:34 -05:00
|
|
|
match obligation.predicate {
|
2014-12-17 14:16:28 -05:00
|
|
|
ty::Predicate::Trait(ref data) => {
|
|
|
|
let trait_obligation = obligation.with(data.clone());
|
2014-12-07 11:10:48 -05:00
|
|
|
match selcx.select(&trait_obligation) {
|
|
|
|
Ok(None) => {
|
2014-12-11 04:35:51 -05:00
|
|
|
false
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
Ok(Some(s)) => {
|
2014-12-17 14:16:28 -05:00
|
|
|
s.map_move_nested(|p| new_obligations.push(p));
|
2014-12-11 04:35:51 -05:00
|
|
|
true
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
Err(selection_err) => {
|
|
|
|
debug!("predicate: {} error: {}",
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation.repr(tcx),
|
2014-12-07 11:10:48 -05:00
|
|
|
selection_err.repr(tcx));
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation.clone(),
|
2014-12-07 11:10:48 -05:00
|
|
|
CodeSelectionError(selection_err)));
|
2014-12-11 04:35:51 -05:00
|
|
|
true
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-13 05:34:34 -05:00
|
|
|
ty::Predicate::Equate(ref binder) => {
|
2014-12-17 16:00:34 -05:00
|
|
|
match selcx.infcx().equality_predicate(obligation.cause.span, binder) {
|
2014-12-13 05:34:34 -05:00
|
|
|
Ok(()) => { }
|
2014-12-07 11:10:48 -05:00
|
|
|
Err(_) => {
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation.clone(),
|
2014-12-07 11:10:48 -05:00
|
|
|
CodeSelectionError(Unimplemented)));
|
|
|
|
}
|
|
|
|
}
|
2014-12-13 05:34:34 -05:00
|
|
|
true
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
|
2014-12-13 05:34:34 -05:00
|
|
|
ty::Predicate::RegionOutlives(ref binder) => {
|
2014-12-17 16:00:34 -05:00
|
|
|
match selcx.infcx().region_outlives_predicate(obligation.cause.span, binder) {
|
2014-12-13 05:34:34 -05:00
|
|
|
Ok(()) => { }
|
|
|
|
Err(_) => {
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation.clone(),
|
2014-12-13 05:34:34 -05:00
|
|
|
CodeSelectionError(Unimplemented)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-11 04:35:51 -05:00
|
|
|
true
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
|
2014-12-13 05:34:34 -05:00
|
|
|
ty::Predicate::TypeOutlives(ref binder) => {
|
|
|
|
// For now, we just check that there are no higher-ranked
|
|
|
|
// regions. If there are, we will call this obligation an
|
|
|
|
// error. Eventually we should be able to support some
|
2014-12-14 07:17:23 -05:00
|
|
|
// cases here, I imagine (e.g., `for<'a> int : 'a`).
|
2014-12-13 05:34:34 -05:00
|
|
|
if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation.clone(),
|
2014-12-13 05:34:34 -05:00
|
|
|
CodeSelectionError(Unimplemented)));
|
|
|
|
} else {
|
|
|
|
let ty::OutlivesPredicate(t_a, r_b) = binder.0;
|
2014-12-06 11:39:25 -05:00
|
|
|
register_region_obligation(tcx, t_a, r_b,
|
2014-12-17 16:00:34 -05:00
|
|
|
obligation.cause.clone(),
|
2014-12-06 11:39:25 -05:00
|
|
|
region_obligations);
|
2014-12-13 05:34:34 -05:00
|
|
|
}
|
2014-12-11 04:35:51 -05:00
|
|
|
true
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
2014-12-17 14:16:28 -05:00
|
|
|
|
|
|
|
ty::Predicate::Projection(ref data) => {
|
|
|
|
let project_obligation = obligation.with(data.clone());
|
|
|
|
let result = project::poly_project_and_unify_type(selcx, &project_obligation);
|
|
|
|
debug!("poly_project_and_unify_type({}) = {}",
|
|
|
|
project_obligation.repr(tcx),
|
|
|
|
result.repr(tcx));
|
|
|
|
match result {
|
|
|
|
Ok(()) => {
|
|
|
|
true
|
|
|
|
}
|
|
|
|
Err(project::ProjectionError::TooManyCandidates) => {
|
|
|
|
// Without more type information, we can't say much.
|
|
|
|
false
|
|
|
|
}
|
|
|
|
Err(project::ProjectionError::NoCandidate) => {
|
|
|
|
// This means that we have a type like `<T as
|
|
|
|
// Trait>::name = U` but we couldn't find any more
|
|
|
|
// information. This could just be that we're in a
|
|
|
|
// function like:
|
|
|
|
//
|
|
|
|
// fn foo<T:Trait>(...)
|
|
|
|
//
|
|
|
|
// in which case this is not an error. But it
|
|
|
|
// might also mean we're in a situation where we
|
|
|
|
// don't actually know that `T : Trait` holds,
|
|
|
|
// which would be weird (e.g., if `T` was not a
|
|
|
|
// parameter type but a normal type, like `int`).
|
|
|
|
//
|
|
|
|
// So what we do is to (1) add a requirement that
|
|
|
|
// `T : Trait` (just in case) and (2) try to unify
|
|
|
|
// `U` with `<T as Trait>::name`.
|
|
|
|
|
|
|
|
if !ty::binds_late_bound_regions(selcx.tcx(), data) {
|
|
|
|
// Check that `T : Trait` holds.
|
|
|
|
let trait_ref = data.to_poly_trait_ref();
|
|
|
|
new_obligations.push(obligation.with(trait_ref.as_predicate()));
|
|
|
|
|
|
|
|
// Fallback to `<T as Trait>::name`. If this
|
|
|
|
// fails, then the output must be at least
|
|
|
|
// somewhat constrained, and we cannot verify
|
|
|
|
// that constraint, so yield an error.
|
|
|
|
let ty_projection = ty::mk_projection(tcx,
|
2014-12-26 03:31:58 -05:00
|
|
|
trait_ref.0.clone(),
|
|
|
|
data.0.projection_ty.item_name);
|
2014-12-17 14:16:28 -05:00
|
|
|
|
|
|
|
debug!("process_predicate: falling back to projection {}",
|
|
|
|
ty_projection.repr(selcx.tcx()));
|
|
|
|
|
|
|
|
match infer::mk_eqty(selcx.infcx(),
|
|
|
|
true,
|
|
|
|
infer::EquatePredicate(obligation.cause.span),
|
|
|
|
ty_projection,
|
|
|
|
data.0.ty) {
|
|
|
|
Ok(()) => { }
|
|
|
|
Err(_) => {
|
|
|
|
debug!("process_predicate: fallback failed to unify; error");
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
|
|
|
obligation.clone(),
|
|
|
|
CodeSelectionError(Unimplemented)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
true
|
|
|
|
} else {
|
|
|
|
// If we have something like
|
|
|
|
//
|
|
|
|
// for<'a> <T<'a> as Trait>::name == &'a int
|
|
|
|
//
|
|
|
|
// there is no "canonical form" for us to
|
|
|
|
// make, so just report the lack of candidates
|
|
|
|
// as an error.
|
|
|
|
|
|
|
|
debug!("process_predicate: can't fallback, higher-ranked");
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
|
|
|
obligation.clone(),
|
|
|
|
CodeSelectionError(Unimplemented)));
|
|
|
|
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(project::ProjectionError::MismatchedTypes(e)) => {
|
|
|
|
errors.push(
|
|
|
|
FulfillmentError::new(
|
|
|
|
obligation.clone(),
|
|
|
|
CodeProjectionError(e)));
|
|
|
|
true
|
|
|
|
}
|
2014-12-27 04:22:29 -05:00
|
|
|
Err(project::ProjectionError::TraitSelectionError(_)) => {
|
|
|
|
// There was an error matching `T : Trait` (which
|
|
|
|
// is a pre-requisite for `<T as Trait>::Name`
|
|
|
|
// being valid). We could just report the error
|
|
|
|
// now, but that tends to lead to double error
|
|
|
|
// reports for the user (one for the obligation `T
|
|
|
|
// : Trait`, typically incurred somewhere else,
|
|
|
|
// and one from here). Instead, we'll create the
|
|
|
|
// `T : Trait` obligation and add THAT as a
|
|
|
|
// requirement. This will (eventually) trigger the
|
|
|
|
// same error, but it will also wind up flagged as
|
|
|
|
// a duplicate if another requirement that `T :
|
|
|
|
// Trait` arises from somewhere else.
|
2014-12-17 14:16:28 -05:00
|
|
|
let trait_predicate = data.to_poly_trait_ref();
|
|
|
|
let trait_obligation = obligation.with(trait_predicate.as_predicate());
|
2014-12-27 04:22:29 -05:00
|
|
|
new_obligations.push(trait_obligation);
|
2014-12-17 14:16:28 -05:00
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-12-07 11:10:48 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-05 02:57:17 -05:00
|
|
|
impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
|
|
|
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
2014-12-06 01:30:41 -05:00
|
|
|
format!("RegionObligation(sub_region={}, sup_type={})",
|
2014-12-05 02:57:17 -05:00
|
|
|
self.sub_region.repr(tcx),
|
2014-12-06 01:30:41 -05:00
|
|
|
self.sup_type.repr(tcx))
|
2014-12-05 02:57:17 -05:00
|
|
|
}
|
|
|
|
}
|
2014-12-07 11:10:48 -05:00
|
|
|
|
|
|
|
fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|
|
|
t_a: Ty<'tcx>,
|
|
|
|
r_b: ty::Region,
|
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>)
|
|
|
|
{
|
|
|
|
let region_obligation = RegionObligation { sup_type: t_a,
|
|
|
|
sub_region: r_b,
|
|
|
|
cause: cause };
|
|
|
|
|
|
|
|
debug!("register_region_obligation({})",
|
|
|
|
region_obligation.repr(tcx));
|
|
|
|
|
|
|
|
match region_obligations.entry(region_obligation.cause.body_id) {
|
|
|
|
Vacant(entry) => { entry.set(vec![region_obligation]); },
|
|
|
|
Occupied(mut entry) => { entry.get_mut().push(region_obligation); },
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2014-12-13 05:34:34 -05:00
|
|
|
|