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;
-> 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)
}
}
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);
// 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() {
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 {
// 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;
}
}
- 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
}
}
+ 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`
+ 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(t_a, r_b) => {
- register_region_obligation(tcx, t_a, r_b, predicate.cause, region_obligations);
+ 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
}
}
}
}
+
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;
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),
}
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(),
});
}
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(),
}
}
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 ®ion_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
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 {
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
}
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());
+ }
+ }
}
}
}
|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>(
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)),
}
}
}
}
}
-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)
}
}
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)),
}
}
}
}
}
+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.
//
.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),
+ }
+ }
+}
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;
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,
"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!(
+ "the requirement `{}` is not satisfied (`{}`)",
+ predicate.user_string(fcx.tcx()),
+ ty::type_err_to_str(fcx.tcx(), &err)).as_slice());
+ }
+
+ 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!(
- "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::TypeOutlives(ref predicate) => {
+ let predicate = fcx.infcx().resolve_type_vars_if_possible(predicate);
+ 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())).as_slice());
}
}
+
+ note_obligation_cause(fcx, obligation);
}
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
let expected_trait_ref =
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};
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());
}
}
}
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)
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 {
visitor.visit_poly_trait_ref(typ);
}
RegionTyParamBound(ref lifetime) => {
- visitor.visit_lifetime_ref(lifetime);
+ visitor.visit_lifetime_bound(lifetime);
}
}
}