Make all predicates higher-ranked, not just trait references.

This commit is contained in:
Niko Matsakis 2014-12-13 05:34:34 -05:00
parent 4f34524fcb
commit c2ca1a4b62
12 changed files with 338 additions and 135 deletions

View File

@ -21,7 +21,7 @@ pub use self::DefIdSource::*;
use middle::region;
use middle::subst;
use middle::subst::VecPerParamSpace;
use middle::ty::{mod, Ty};
use middle::ty::{mod, AsPredicate, Ty};
use std::rc::Rc;
use std::str;
@ -669,13 +669,13 @@ pub fn parse_predicate<'a,'tcx>(st: &mut PState<'a, 'tcx>,
-> ty::Predicate<'tcx>
{
match next(st) {
't' => ty::Predicate::Trait(Rc::new(ty::Binder(parse_trait_ref(st, conv)))),
'e' => ty::Predicate::Equate(parse_ty(st, |x,y| conv(x,y)),
parse_ty(st, |x,y| conv(x,y))),
'r' => ty::Predicate::RegionOutlives(parse_region(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y))),
'o' => ty::Predicate::TypeOutlives(parse_ty(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y))),
't' => Rc::new(ty::Binder(parse_trait_ref(st, conv))).as_predicate(),
'e' => ty::Binder(ty::EquatePredicate(parse_ty(st, |x,y| conv(x,y)),
parse_ty(st, |x,y| conv(x,y)))).as_predicate(),
'r' => ty::Binder(ty::OutlivesPredicate(parse_region(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
'o' => ty::Binder(ty::OutlivesPredicate(parse_ty(st, |x,y| conv(x,y)),
parse_region(st, |x,y| conv(x,y)))).as_predicate(),
c => panic!("Encountered invalid character in metadata: {}", c)
}
}

View File

@ -427,17 +427,17 @@ pub fn enc_predicate<'a, 'tcx>(w: &mut SeekableMemWriter,
mywrite!(w, "t");
enc_trait_ref(w, cx, &trait_ref.0);
}
ty::Predicate::Equate(a, b) => {
ty::Predicate::Equate(ty::Binder(ty::EquatePredicate(a, b))) => {
mywrite!(w, "e");
enc_ty(w, cx, a);
enc_ty(w, cx, b);
}
ty::Predicate::RegionOutlives(a, b) => {
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
mywrite!(w, "r");
enc_region(w, cx, a);
enc_region(w, cx, b);
}
ty::Predicate::TypeOutlives(a, b) => {
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(a, b))) => {
mywrite!(w, "o");
enc_ty(w, cx, a);
enc_region(w, cx, b);

View File

@ -81,7 +81,7 @@ impl<'tcx,C> HigherRankedRelations<'tcx> for C
// Presuming type comparison succeeds, we need to check
// that the skolemized regions do not "leak".
match self.infcx().leak_check(&skol_map, snapshot) {
match leak_check(self.infcx(), &skol_map, snapshot) {
Ok(()) => { }
Err((skol_br, tainted_region)) => {
if self.a_is_expected() {

View File

@ -717,11 +717,40 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn leak_check(&self,
skol_map: &SkolemizationMap,
snapshot: &CombinedSnapshot)
-> Result<(),(ty::BoundRegion,ty::Region)>
-> ures<'tcx>
{
/*! See `higher_ranked::leak_check` */
higher_ranked::leak_check(self, skol_map, snapshot)
match higher_ranked::leak_check(self, skol_map, snapshot) {
Ok(()) => Ok(()),
Err((br, r)) => Err(ty::terr_regions_insufficiently_polymorphic(br, r))
}
}
pub fn equality_predicate(&self,
span: Span,
predicate: &ty::PolyEquatePredicate<'tcx>)
-> ures<'tcx> {
self.try(|snapshot| {
let (ty::EquatePredicate(a, b), skol_map) =
self.skolemize_late_bound_regions(predicate, snapshot);
let origin = EquatePredicate(span);
let () = try!(mk_eqty(self, false, origin, a, b));
self.leak_check(&skol_map, snapshot)
})
}
pub fn region_outlives_predicate(&self,
span: Span,
predicate: &ty::PolyRegionOutlivesPredicate)
-> ures<'tcx> {
self.try(|snapshot| {
let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
self.skolemize_late_bound_regions(predicate, snapshot);
let origin = RelateRegionParamBound(span);
let () = mk_subr(self, origin, r_b, r_a); // `b : a` ==> `a <= b`
self.leak_check(&skol_map, snapshot)
})
}
pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {

View File

@ -8,9 +8,9 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use middle::infer::InferCtxt;
use middle::mem_categorization::Typer;
use middle::ty::{mod, Ty};
use middle::infer::{mod, InferCtxt};
use std::collections::HashSet;
use std::collections::hash_map::{Occupied, Vacant};
use std::default::Default;
@ -329,30 +329,50 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
}
}
ty::Predicate::Equate(a, b) => {
let origin = infer::EquatePredicate(predicate.cause.span);
match infer::mk_eqty(selcx.infcx(), false, origin, a, b) {
Ok(()) => {
true
}
ty::Predicate::Equate(ref binder) => {
match selcx.infcx().equality_predicate(predicate.cause.span, binder) {
Ok(()) => { }
Err(_) => {
errors.push(
FulfillmentError::new(
predicate.clone(),
CodeSelectionError(Unimplemented)));
true
}
}
}
ty::Predicate::RegionOutlives(r_a, r_b) => {
let origin = infer::RelateRegionParamBound(predicate.cause.span);
let () = infer::mk_subr(selcx.infcx(), origin, r_b, r_a); // `b : a` ==> `a <= b`
true
}
ty::Predicate::TypeOutlives(t_a, r_b) => {
register_region_obligation(tcx, t_a, r_b, predicate.cause, region_obligations);
ty::Predicate::RegionOutlives(ref binder) => {
match selcx.infcx().region_outlives_predicate(predicate.cause.span, binder) {
Ok(()) => { }
Err(_) => {
errors.push(
FulfillmentError::new(
predicate.clone(),
CodeSelectionError(Unimplemented)));
}
}
true
}
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
// cases here, I imagine (e.g., `for<'a> &'a int : 'a`).
//
// TODO This is overly conservative, but good enough for
// now.
if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
errors.push(
FulfillmentError::new(
predicate.clone(),
CodeSelectionError(Unimplemented)));
} else {
let ty::OutlivesPredicate(t_a, r_b) = binder.0;
register_region_obligation(tcx, t_a, r_b, predicate.cause, region_obligations);
}
true
}
}
@ -385,3 +405,4 @@ fn register_region_obligation<'tcx>(tcx: &ty::ctxt<'tcx>,
}
}

View File

@ -28,7 +28,7 @@ use super::{util};
use middle::fast_reject;
use middle::mem_categorization::Typer;
use middle::subst::{Subst, Substs, VecPerParamSpace};
use middle::ty::{mod, Ty, RegionEscape};
use middle::ty::{mod, AsPredicate, RegionEscape, Ty};
use middle::infer;
use middle::infer::{InferCtxt, TypeFreshener};
use middle::ty_fold::TypeFoldable;
@ -288,8 +288,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
self.evaluate_obligation_recursively(previous_stack, &obligation)
}
ty::Predicate::Equate(a, b) => {
match infer::can_mk_eqty(self.infcx, a, b) {
ty::Predicate::Equate(ref p) => {
let result = self.infcx.probe(|| {
self.infcx.equality_predicate(obligation.cause.span, p)
});
match result {
Ok(()) => EvaluatedToOk,
Err(_) => EvaluatedToErr(Unimplemented),
}
@ -1447,8 +1450,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligations.push(Obligation {
cause: obligation.cause,
recursion_depth: obligation.recursion_depth+1,
trait_ref: ty::Predicate::TypeOutlives(obligation.self_ty(),
ty::ReStatic)
trait_ref: ty::Binder(ty::OutlivesPredicate(obligation.self_ty(),
ty::ReStatic)).as_predicate(),
});
}

View File

@ -1689,23 +1689,60 @@ pub enum Predicate<'tcx> {
Trait(Rc<PolyTraitRef<'tcx>>),
/// where `T1 == T2`.
Equate(/* T1 */ Ty<'tcx>, /* T2 */ Ty<'tcx>),
Equate(PolyEquatePredicate<'tcx>),
/// where 'a : 'b
RegionOutlives(/* 'a */ Region, /* 'b */ Region),
RegionOutlives(PolyRegionOutlivesPredicate),
/// where T : 'a
TypeOutlives(Ty<'tcx>, Region),
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
}
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1`
pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>;
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B`
pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>;
pub type PolyRegionOutlivesPredicate = PolyOutlivesPredicate<ty::Region, ty::Region>;
pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region>;
pub trait AsPredicate<'tcx> {
fn as_predicate(&self) -> Predicate<'tcx>;
}
impl<'tcx> AsPredicate<'tcx> for Rc<PolyTraitRef<'tcx>> {
fn as_predicate(&self) -> Predicate<'tcx> {
Predicate::Trait(self.clone())
}
}
impl<'tcx> AsPredicate<'tcx> for PolyEquatePredicate<'tcx> {
fn as_predicate(&self) -> Predicate<'tcx> {
Predicate::Equate(self.clone())
}
}
impl<'tcx> AsPredicate<'tcx> for PolyRegionOutlivesPredicate {
fn as_predicate(&self) -> Predicate<'tcx> {
Predicate::RegionOutlives(self.clone())
}
}
impl<'tcx> AsPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> {
fn as_predicate(&self) -> Predicate<'tcx> {
Predicate::TypeOutlives(self.clone())
}
}
impl<'tcx> Predicate<'tcx> {
pub fn has_escaping_regions(&self) -> bool {
match *self {
Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(),
Predicate::Equate(a, b) => (ty::type_has_escaping_regions(a) ||
ty::type_has_escaping_regions(b)),
Predicate::RegionOutlives(a, b) => a.escapes_depth(0) || b.escapes_depth(0),
Predicate::TypeOutlives(a, b) => ty::type_has_escaping_regions(a) || b.escapes_depth(0),
Predicate::Equate(ref p) => p.has_escaping_regions(),
Predicate::RegionOutlives(ref p) => p.has_escaping_regions(),
Predicate::TypeOutlives(ref p) => p.has_escaping_regions(),
}
}
@ -5208,17 +5245,20 @@ pub fn predicates<'tcx>(
for builtin_bound in bounds.builtin_bounds.iter() {
match traits::poly_trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
Ok(trait_ref) => { vec.push(Predicate::Trait(trait_ref)); }
Ok(trait_ref) => { vec.push(trait_ref.as_predicate()); }
Err(ErrorReported) => { }
}
}
for &region_bound in bounds.region_bounds.iter() {
vec.push(Predicate::TypeOutlives(param_ty, region_bound));
// account for the binder being introduced below; no need to shift `param_ty`
// because, at present at least, it can only refer to early-bound regions
let region_bound = ty_fold::shift_region(region_bound, 1);
vec.push(ty::Binder(ty::OutlivesPredicate(param_ty, region_bound)).as_predicate());
}
for bound_trait_ref in bounds.trait_bounds.iter() {
vec.push(Predicate::Trait((*bound_trait_ref).clone()));
vec.push(bound_trait_ref.as_predicate());
}
vec
@ -5595,19 +5635,27 @@ pub fn object_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
ty::required_region_bounds(tcx, open_ty, predicates)
}
/// Given a type which must meet the builtin bounds and trait bounds, returns a set of lifetimes
/// which the type must outlive.
/// Given a set of predicates that apply to an object type, returns
/// the region bounds that the (erased) `Self` type must
/// outlive. Precisely *because* the `Self` type is erased, the
/// parameter `erased_self_ty` must be supplied to indicate what type
/// has been used to represent `Self` in the predicates
/// themselves. This should really be a unique type; `FreshTy(0)` is a
/// popular choice (see `object_region_bounds` above).
///
/// Requires that trait definitions have been processed.
/// Requires that trait definitions have been processed so that we can
/// elaborate predicates and walk supertraits.
pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
param_ty: Ty<'tcx>,
erased_self_ty: Ty<'tcx>,
predicates: Vec<ty::Predicate<'tcx>>)
-> Vec<ty::Region>
{
debug!("required_region_bounds(param_ty={}, predicates={})",
param_ty.repr(tcx),
debug!("required_region_bounds(erased_self_ty={}, predicates={})",
erased_self_ty.repr(tcx),
predicates.repr(tcx));
assert!(!erased_self_ty.has_escaping_regions());
traits::elaborate_predicates(tcx, predicates)
.filter_map(|predicate| {
match predicate {
@ -5616,9 +5664,22 @@ pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
ty::Predicate::RegionOutlives(..) => {
None
}
ty::Predicate::TypeOutlives(t, r) => {
if t == param_ty {
Some(r)
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => {
// Search for a bound of the form `erased_self_ty
// : 'a`, but be wary of something like `for<'a>
// erased_self_ty : 'a` (we interpret a
// higher-ranked bound like that as 'static,
// though at present the code in `fulfill.rs`
// considers such bounds to be unsatisfiable, so
// it's kind of a moot point since you could never
// construct such an object, but this seems
// correct even if that code changes).
if t == erased_self_ty && !r.has_escaping_regions() {
if r.has_escaping_regions() {
Some(ty::ReStatic)
} else {
Some(r)
}
} else {
None
}
@ -6100,16 +6161,20 @@ pub fn construct_parameter_environment<'tcx>(
Predicate::Trait(..) | Predicate::Equate(..) | Predicate::TypeOutlives(..) => {
// No region bounds here
}
Predicate::RegionOutlives(ty::ReFree(fr_a), ty::ReFree(fr_b)) => {
// Record that `'a:'b`. Or, put another way, `'b <= 'a`.
tcx.region_maps.relate_free_regions(fr_b, fr_a);
}
Predicate::RegionOutlives(r_a, r_b) => {
// All named regions are instantiated with free regions.
tcx.sess.bug(
format!("record_region_bounds: non free region: {} / {}",
r_a.repr(tcx),
r_b.repr(tcx)).as_slice());
Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r_a, r_b))) => {
match (r_a, r_b) {
(ty::ReFree(fr_a), ty::ReFree(fr_b)) => {
// Record that `'a:'b`. Or, put another way, `'b <= 'a`.
tcx.region_maps.relate_free_regions(fr_b, fr_a);
}
_ => {
// All named regions are instantiated with free regions.
tcx.sess.bug(
format!("record_region_bounds: non free region: {} / {}",
r_a.repr(tcx),
r_b.repr(tcx)).as_slice());
}
}
}
}
}
@ -6313,6 +6378,16 @@ pub fn liberate_late_bound_regions<'tcx, T>(
|br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0
}
pub fn count_late_bound_regions<'tcx, T>(
tcx: &ty::ctxt<'tcx>,
value: &Binder<T>)
-> uint
where T : TypeFoldable<'tcx> + Repr<'tcx>
{
let (_, skol_map) = replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic);
skol_map.len()
}
/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
/// method lookup and a few other places where precise region relationships are not required.
pub fn erase_late_bound_regions<'tcx, T>(
@ -6454,9 +6529,9 @@ impl<'tcx> Repr<'tcx> for ty::Predicate<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
match *self {
Predicate::Trait(ref a) => a.repr(tcx),
Predicate::Equate(a, b) => format!("Equate({},{})", a.repr(tcx), b.repr(tcx)),
Predicate::RegionOutlives(a, b) => format!("Outlives({}:{})", a.repr(tcx), b.repr(tcx)),
Predicate::TypeOutlives(a, b) => format!("Outlives({}:{})", a.repr(tcx), b.repr(tcx)),
Predicate::Equate(ref pair) => format!("Equate({})", pair.repr(tcx)),
Predicate::RegionOutlives(ref pair) => format!("Outlives({})", pair.repr(tcx)),
Predicate::TypeOutlives(ref pair) => format!("Outlives({})", pair.repr(tcx)),
}
}
}
@ -6586,9 +6661,15 @@ impl<'tcx,T:RegionEscape> RegionEscape for Binder<T> {
}
}
impl<T:RegionEscape> Binder<T> {
pub fn has_bound_regions(&self) -> bool {
self.0.has_regions_escaping_depth(0)
impl<'tcx> RegionEscape for EquatePredicate<'tcx> {
fn has_regions_escaping_depth(&self, depth: uint) -> bool {
self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
}
}
impl<T:RegionEscape,U:RegionEscape> RegionEscape for OutlivesPredicate<T,U> {
fn has_regions_escaping_depth(&self, depth: uint) -> bool {
self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth)
}
}

View File

@ -409,15 +409,12 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
match *self {
ty::Predicate::Trait(ref a) =>
ty::Predicate::Trait(a.fold_with(folder)),
ty::Predicate::Equate(ref a, ref b) =>
ty::Predicate::Equate(a.fold_with(folder),
b.fold_with(folder)),
ty::Predicate::RegionOutlives(ref a, ref b) =>
ty::Predicate::RegionOutlives(a.fold_with(folder),
b.fold_with(folder)),
ty::Predicate::TypeOutlives(ref a, ref b) =>
ty::Predicate::TypeOutlives(a.fold_with(folder),
b.fold_with(folder)),
ty::Predicate::Equate(ref binder) =>
ty::Predicate::Equate(binder.fold_with(folder)),
ty::Predicate::RegionOutlives(ref binder) =>
ty::Predicate::RegionOutlives(binder.fold_with(folder)),
ty::Predicate::TypeOutlives(ref binder) =>
ty::Predicate::TypeOutlives(binder.fold_with(folder)),
}
}
}
@ -501,6 +498,23 @@ impl<'tcx> TypeFoldable<'tcx> for traits::VtableParamData<'tcx> {
}
}
impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::EquatePredicate<'tcx> {
ty::EquatePredicate(self.0.fold_with(folder),
self.1.fold_with(folder))
}
}
impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
where T : TypeFoldable<'tcx>,
U : TypeFoldable<'tcx>,
{
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::OutlivesPredicate<T,U> {
ty::OutlivesPredicate(self.0.fold_with(folder),
self.1.fold_with(folder))
}
}
///////////////////////////////////////////////////////////////////////////
// "super" routines: these are the default implementations for TypeFolder.
//

View File

@ -1350,3 +1350,56 @@ impl<'tcx, S, H, K, V> Repr<'tcx> for HashMap<K,V,H>
.connect(", "))
}
}
impl<'tcx, T, U> Repr<'tcx> for ty::OutlivesPredicate<T,U>
where T : Repr<'tcx> + TypeFoldable<'tcx>,
U : Repr<'tcx> + TypeFoldable<'tcx>,
{
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("OutlivesPredicate({}, {})",
self.0.repr(tcx),
self.1.repr(tcx))
}
}
impl<'tcx, T, U> UserString<'tcx> for ty::OutlivesPredicate<T,U>
where T : UserString<'tcx> + TypeFoldable<'tcx>,
U : UserString<'tcx> + TypeFoldable<'tcx>,
{
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
format!("{} : {}",
self.0.user_string(tcx),
self.1.user_string(tcx))
}
}
impl<'tcx> Repr<'tcx> for ty::EquatePredicate<'tcx> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
format!("EquatePredicate({}, {})",
self.0.repr(tcx),
self.1.repr(tcx))
}
}
impl<'tcx> UserString<'tcx> for ty::EquatePredicate<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
format!("{} == {}",
self.0.user_string(tcx),
self.1.user_string(tcx))
}
}
impl<'tcx> UserString<'tcx> for ty::Predicate<'tcx> {
fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
match *self {
ty::Predicate::Trait(ref trait_ref) => {
format!("{} : {}",
trait_ref.self_ty().user_string(tcx),
trait_ref.user_string(tcx))
}
ty::Predicate::Equate(ref predicate) => predicate.user_string(tcx),
ty::Predicate::RegionOutlives(ref predicate) => predicate.user_string(tcx),
ty::Predicate::TypeOutlives(ref predicate) => predicate.user_string(tcx),
}
}
}

View File

@ -315,36 +315,13 @@ pub fn report_selection_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
match *error {
Overflow => {
// We could track the stack here more precisely if we wanted, I imagine.
match obligation.trait_ref {
ty::Predicate::Trait(ref trait_ref) => {
let trait_ref =
fcx.infcx().resolve_type_vars_if_possible(&**trait_ref);
fcx.tcx().sess.span_err(
obligation.cause.span,
format!(
"overflow evaluating the trait `{}` for the type `{}`",
trait_ref.user_string(fcx.tcx()),
trait_ref.self_ty().user_string(fcx.tcx())).as_slice());
}
ty::Predicate::Equate(a, b) => {
let a = fcx.infcx().resolve_type_vars_if_possible(&a);
let b = fcx.infcx().resolve_type_vars_if_possible(&b);
fcx.tcx().sess.span_err(
obligation.cause.span,
format!(
"overflow checking whether the types `{}` and `{}` are equal",
a.user_string(fcx.tcx()),
b.user_string(fcx.tcx())).as_slice());
}
ty::Predicate::TypeOutlives(..) |
ty::Predicate::RegionOutlives(..) => {
fcx.tcx().sess.span_err(
obligation.cause.span,
format!("overflow evaluating lifetime predicate").as_slice());
}
}
let predicate =
fcx.infcx().resolve_type_vars_if_possible(&obligation.trait_ref);
fcx.tcx().sess.span_err(
obligation.cause.span,
format!(
"overflow evaluating the requirement `{}`",
predicate.user_string(fcx.tcx())).as_slice());
let current_limit = fcx.tcx().sess.recursion_limit.get();
let suggested_limit = current_limit * 2;
@ -359,8 +336,7 @@ pub fn report_selection_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Unimplemented => {
match obligation.trait_ref {
ty::Predicate::Trait(ref trait_ref) => {
let trait_ref =
fcx.infcx().resolve_type_vars_if_possible(&**trait_ref);
let trait_ref = fcx.infcx().resolve_type_vars_if_possible(&**trait_ref);
if !ty::type_is_error(trait_ref.self_ty()) {
fcx.tcx().sess.span_err(
obligation.cause.span,
@ -368,34 +344,44 @@ pub fn report_selection_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
"the trait `{}` is not implemented for the type `{}`",
trait_ref.user_string(fcx.tcx()),
trait_ref.self_ty().user_string(fcx.tcx())).as_slice());
note_obligation_cause(fcx, obligation);
}
}
ty::Predicate::Equate(a, b) => {
let a = fcx.infcx().resolve_type_vars_if_possible(&a);
let b = fcx.infcx().resolve_type_vars_if_possible(&b);
let err = infer::can_mk_eqty(fcx.infcx(), a, b).unwrap_err();
ty::Predicate::Equate(ref predicate) => {
let predicate = fcx.infcx().resolve_type_vars_if_possible(predicate);
let err = fcx.infcx().equality_predicate(obligation.cause.span,
&predicate).unwrap_err();
fcx.tcx().sess.span_err(
obligation.cause.span,
format!(
"mismatched types: the types `{}` and `{}` are not equal ({})",
a.user_string(fcx.tcx()),
b.user_string(fcx.tcx()),
"the requirement `{}` is not satisfied (`{}`)",
predicate.user_string(fcx.tcx()),
ty::type_err_to_str(fcx.tcx(), &err)).as_slice());
}
ty::Predicate::TypeOutlives(..) |
ty::Predicate::RegionOutlives(..) => {
// these kinds of predicates turn into
// constraints, and hence errors show up in region
// inference.
fcx.tcx().sess.span_bug(
ty::Predicate::RegionOutlives(ref predicate) => {
let predicate = fcx.infcx().resolve_type_vars_if_possible(predicate);
let err = fcx.infcx().region_outlives_predicate(obligation.cause.span,
&predicate).unwrap_err();
fcx.tcx().sess.span_err(
obligation.cause.span,
format!("region predicate error {}",
obligation.repr(fcx.tcx())).as_slice());
format!(
"the requirement `{}` is not satisfied (`{}`)",
predicate.user_string(fcx.tcx()),
ty::type_err_to_str(fcx.tcx(), &err)).as_slice());
}
ty::Predicate::TypeOutlives(ref predicate) => {
let predicate = fcx.infcx().resolve_type_vars_if_possible(predicate);
fcx.tcx().sess.span_err(
obligation.cause.span,
format!(
"the requirement `{}` is not satisfied",
predicate.user_string(fcx.tcx())).as_slice());
}
}
note_obligation_cause(fcx, obligation);
}
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
let expected_trait_ref =

View File

@ -42,10 +42,9 @@ use middle::region;
use middle::resolve_lifetime;
use middle::subst;
use middle::subst::{Substs};
use middle::ty::{ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use middle::ty::{Polytype};
use middle::ty::{mod, Ty};
use middle::ty_fold::TypeFolder;
use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
use middle::ty::{mod, Ty, Polytype};
use middle::ty_fold::{mod, TypeFolder};
use middle::infer;
use rscope::*;
use {CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
@ -1920,8 +1919,12 @@ fn ty_generics<'tcx,AC>(this: &AC,
for region_param_def in result.regions.get_slice(space).iter() {
let region = region_param_def.to_early_bound_region();
for &bound_region in region_param_def.bounds.iter() {
result.predicates.push(space, ty::Predicate::RegionOutlives(region,
bound_region));
// account for new binder introduced in the predicate below; no need
// to shift `region` because it is never a late-bound region
let bound_region = ty_fold::shift_region(bound_region, 1);
result.predicates.push(
space,
ty::Binder(ty::OutlivesPredicate(region, bound_region)).as_predicate());
}
}
}

View File

@ -105,8 +105,11 @@ pub trait Visitor<'v> {
None => ()
}
}
fn visit_lifetime_bound(&mut self, lifetime: &'v Lifetime) {
walk_lifetime_bound(self, lifetime)
}
fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
self.visit_name(lifetime.span, lifetime.name)
walk_lifetime_ref(self, lifetime)
}
fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
walk_lifetime_def(self, lifetime)
@ -214,10 +217,20 @@ pub fn walk_lifetime_def<'v, V: Visitor<'v>>(visitor: &mut V,
lifetime_def: &'v LifetimeDef) {
visitor.visit_name(lifetime_def.lifetime.span, lifetime_def.lifetime.name);
for bound in lifetime_def.bounds.iter() {
visitor.visit_lifetime_ref(bound);
visitor.visit_lifetime_bound(bound);
}
}
pub fn walk_lifetime_bound<'v, V: Visitor<'v>>(visitor: &mut V,
lifetime_ref: &'v Lifetime) {
visitor.visit_lifetime_ref(lifetime_ref)
}
pub fn walk_lifetime_ref<'v, V: Visitor<'v>>(visitor: &mut V,
lifetime_ref: &'v Lifetime) {
visitor.visit_name(lifetime_ref.span, lifetime_ref.name)
}
pub fn walk_explicit_self<'v, V: Visitor<'v>>(visitor: &mut V,
explicit_self: &'v ExplicitSelf) {
match explicit_self.node {
@ -550,7 +563,7 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V,
visitor.visit_poly_trait_ref(typ);
}
RegionTyParamBound(ref lifetime) => {
visitor.visit_lifetime_ref(lifetime);
visitor.visit_lifetime_bound(lifetime);
}
}
}