mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-04 04:39:16 +00:00
Make all predicates higher-ranked, not just trait references.
This commit is contained in:
parent
4f34524fcb
commit
c2ca1a4b62
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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 {
|
||||
|
@ -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>,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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 ®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
|
||||
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 =
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user