提交 8403b82d 编写于 作者: N Niko Matsakis

Port over type inference to using the new type relation stuff

上级 e301d7ca
......@@ -122,6 +122,7 @@ pub mod middle {
pub mod traits;
pub mod ty;
pub mod ty_fold;
pub mod ty_relate;
pub mod ty_walk;
pub mod weak_lang_items;
}
......
......@@ -25,66 +25,54 @@
//! In particular, it might be enough to say (A,B) are bivariant for
//! all (A,B).
use middle::ty::BuiltinBounds;
use super::combine::{self, CombineFields};
use super::type_variable::{BiTo};
use middle::ty::{self, Ty};
use middle::ty::TyVar;
use middle::infer::combine::*;
use middle::infer::CombineResult;
use middle::infer::type_variable::BiTo;
use util::ppaux::Repr;
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use util::ppaux::{Repr};
pub struct Bivariate<'f, 'tcx: 'f> {
fields: CombineFields<'f, 'tcx>
pub struct Bivariate<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
}
#[allow(non_snake_case)]
pub fn Bivariate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Bivariate<'f, 'tcx> {
Bivariate { fields: cf }
impl<'a, 'tcx> Bivariate<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Bivariate<'a, 'tcx> {
Bivariate { fields: fields }
}
}
impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> {
fn tag(&self) -> String { "Bivariate".to_string() }
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
fn tag(&self) -> &'static str { "Bivariate" }
fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-> CombineResult<'tcx, Ty<'tcx>>
{
match v {
ty::Invariant => self.equate().tys(a, b),
ty::Covariant => self.tys(a, b),
ty::Contravariant => self.tys(a, b),
ty::Bivariant => self.tys(a, b),
}
}
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-> CombineResult<'tcx, ty::Region>
{
match v {
ty::Invariant => self.equate().regions(a, b),
ty::Covariant => self.regions(a, b),
ty::Contravariant => self.regions(a, b),
ty::Bivariant => self.regions(a, b),
}
}
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
fn regions(&self, a: ty::Region, _: ty::Region) -> CombineResult<'tcx, ty::Region> {
Ok(a)
}
fn builtin_bounds(&self,
a: BuiltinBounds,
b: BuiltinBounds)
-> CombineResult<'tcx, BuiltinBounds>
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
{
if a != b {
Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
} else {
Ok(a)
match variance {
// If we have Foo<A> and Foo is invariant w/r/t A,
// and we want to assert that
//
// Foo<A> <: Foo<B> ||
// Foo<B> <: Foo<A>
//
// then still A must equal B.
ty::Invariant => self.relate(a, b),
ty::Covariant => self.relate(a, b),
ty::Bivariant => self.relate(a, b),
ty::Contravariant => self.relate(a, b),
}
}
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug!("{}.tys({}, {})", self.tag(),
a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
if a == b { return Ok(a); }
......@@ -109,17 +97,22 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
}
_ => {
super_tys(self, a, b)
combine::super_combine_tys(self.fields.infcx, self, a, b)
}
}
}
fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> CombineResult<'tcx, ty::Binder<T>>
where T : Combineable<'tcx>
fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> {
Ok(a)
}
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'a,'tcx>
{
let a1 = ty::erase_late_bound_regions(self.tcx(), a);
let b1 = ty::erase_late_bound_regions(self.tcx(), b);
let c = try!(Combineable::combine(self, &a1, &b1));
let c = try!(self.relate(&a1, &b1));
Ok(ty::Binder(c))
}
}
......@@ -8,51 +8,43 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::combine::{self, CombineFields};
use super::higher_ranked::HigherRankedRelations;
use super::{Subtype};
use super::type_variable::{EqTo};
use middle::ty::{self, Ty};
use middle::ty::TyVar;
use middle::infer::combine::*;
use middle::infer::CombineResult;
use middle::infer::Subtype;
use middle::infer::type_variable::EqTo;
use util::ppaux::Repr;
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use util::ppaux::{Repr};
pub struct Equate<'f, 'tcx: 'f> {
fields: CombineFields<'f, 'tcx>
pub struct Equate<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
}
#[allow(non_snake_case)]
pub fn Equate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Equate<'f, 'tcx> {
Equate { fields: cf }
impl<'a, 'tcx> Equate<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Equate<'a, 'tcx> {
Equate { fields: fields }
}
}
impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> {
fn tag(&self) -> String { "Equate".to_string() }
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
fn tag(&self) -> &'static str { "Equate" }
fn tys_with_variance(&self, _: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-> CombineResult<'tcx, Ty<'tcx>>
{
// Once we're equating, it doesn't matter what the variance is.
self.tys(a, b)
}
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
fn regions_with_variance(&self, _: ty::Variance, a: ty::Region, b: ty::Region)
-> CombineResult<'tcx, ty::Region>
{
// Once we're equating, it doesn't matter what the variance is.
self.regions(a, b)
}
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
fn regions(&self, a: ty::Region, b: ty::Region) -> CombineResult<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
a.repr(self.fields.infcx.tcx),
b.repr(self.fields.infcx.tcx));
self.infcx().region_vars.make_eqregion(Subtype(self.trace()), a, b);
Ok(a)
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
_: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
{
self.relate(a, b)
}
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug!("{}.tys({}, {})", self.tag(),
a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
if a == b { return Ok(a); }
......@@ -77,15 +69,26 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
}
_ => {
super_tys(self, a, b)
combine::super_combine_tys(self.fields.infcx, self, a, b)
}
}
}
fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> CombineResult<'tcx, ty::Binder<T>>
where T : Combineable<'tcx>
fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
a.repr(self.fields.infcx.tcx),
b.repr(self.fields.infcx.tcx));
let origin = Subtype(self.fields.trace.clone());
self.fields.infcx.region_vars.make_eqregion(origin, a, b);
Ok(a)
}
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'a, 'tcx>
{
try!(self.sub().binders(a, b));
self.sub().binders(b, a)
try!(self.fields.higher_ranked_sub(a, b));
self.fields.higher_ranked_sub(b, a)
}
}
......@@ -8,67 +8,79 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::combine::*;
use super::lattice::*;
use super::combine::CombineFields;
use super::higher_ranked::HigherRankedRelations;
use super::CombineResult;
use super::InferCtxt;
use super::lattice::{self, LatticeDir};
use super::Subtype;
use middle::ty::{self, Ty};
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use util::ppaux::Repr;
/// "Greatest lower bound" (common subtype)
pub struct Glb<'f, 'tcx: 'f> {
fields: CombineFields<'f, 'tcx>
pub struct Glb<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
}
#[allow(non_snake_case)]
pub fn Glb<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Glb<'f, 'tcx> {
Glb { fields: cf }
impl<'a, 'tcx> Glb<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Glb<'a, 'tcx> {
Glb { fields: fields }
}
}
impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
fn tag(&self) -> String { "Glb".to_string() }
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
fn tag(&self) -> &'static str { "Glb" }
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-> CombineResult<'tcx, Ty<'tcx>>
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
{
match v {
ty::Invariant => self.equate().tys(a, b),
ty::Covariant => self.tys(a, b),
ty::Bivariant => self.bivariate().tys(a, b),
ty::Contravariant => self.lub().tys(a, b),
match variance {
ty::Invariant => self.fields.equate().relate(a, b),
ty::Covariant => self.relate(a, b),
ty::Bivariant => self.fields.bivariate().relate(a, b),
ty::Contravariant => self.fields.lub().relate(a, b),
}
}
fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-> CombineResult<'tcx, ty::Region>
{
match v {
ty::Invariant => self.equate().regions(a, b),
ty::Covariant => self.regions(a, b),
ty::Bivariant => self.bivariate().regions(a, b),
ty::Contravariant => self.lub().regions(a, b),
}
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
lattice::super_lattice_tys(self, a, b)
}
fn regions(&self, a: ty::Region, b: ty::Region) -> CombineResult<'tcx, ty::Region> {
fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
a.repr(self.fields.infcx.tcx),
b.repr(self.fields.infcx.tcx));
Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
let origin = Subtype(self.fields.trace.clone());
Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b))
}
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
super_lattice_tys(self, a, b)
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'a, 'tcx>
{
self.fields.higher_ranked_glb(a, b)
}
}
fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> CombineResult<'tcx, ty::Binder<T>>
where T : Combineable<'tcx>
{
self.higher_ranked_glb(a, b)
impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> {
fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
self.fields.infcx
}
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
let mut sub = self.fields.sub();
try!(sub.relate(&v, &a));
try!(sub.relate(&v, &b));
Ok(())
}
}
......@@ -11,25 +11,26 @@
//! Helper routines for higher-ranked things. See the `doc` module at
//! the end of the file for details.
use super::{CombinedSnapshot, CombineResult, InferCtxt, HigherRankedType, SkolemizationMap};
use super::combine::{Combine, Combineable};
use super::{CombinedSnapshot, InferCtxt, HigherRankedType, SkolemizationMap};
use super::combine::CombineFields;
use middle::subst;
use middle::ty::{self, Binder};
use middle::ty_fold::{self, TypeFoldable};
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use syntax::codemap::Span;
use util::nodemap::{FnvHashMap, FnvHashSet};
use util::ppaux::Repr;
pub trait HigherRankedRelations<'tcx> {
fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> CombineResult<'tcx, Binder<T>>
where T : Combineable<'tcx>;
pub trait HigherRankedRelations<'a,'tcx> {
fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>;
fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> CombineResult<'tcx, Binder<T>>
where T : Combineable<'tcx>;
fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>;
fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> CombineResult<'tcx, Binder<T>>
where T : Combineable<'tcx>;
fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>;
}
trait InferCtxtExt {
......@@ -40,15 +41,15 @@ fn region_vars_confined_to_snapshot(&self,
-> Vec<ty::RegionVid>;
}
impl<'tcx,C> HigherRankedRelations<'tcx> for C
where C : Combine<'tcx>
{
impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
-> CombineResult<'tcx, Binder<T>>
where T : Combineable<'tcx>
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>
{
let tcx = self.infcx.tcx;
debug!("higher_ranked_sub(a={}, b={})",
a.repr(self.tcx()), b.repr(self.tcx()));
a.repr(tcx), b.repr(tcx));
// Rather than checking the subtype relationship between `a` and `b`
// as-is, we need to do some extra work here in order to make sure
......@@ -60,32 +61,32 @@ fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
// Start a snapshot so we can examine "all bindings that were
// created as part of this type comparison".
return self.infcx().commit_if_ok(|snapshot| {
return self.infcx.commit_if_ok(|snapshot| {
// First, we instantiate each bound region in the subtype with a fresh
// region variable.
let (a_prime, _) =
self.infcx().replace_late_bound_regions_with_fresh_var(
self.trace().origin.span(),
self.infcx.replace_late_bound_regions_with_fresh_var(
self.trace.origin.span(),
HigherRankedType,
a);
// Second, we instantiate each bound region in the supertype with a
// fresh concrete region.
let (b_prime, skol_map) =
self.infcx().skolemize_late_bound_regions(b, snapshot);
self.infcx.skolemize_late_bound_regions(b, snapshot);
debug!("a_prime={}", a_prime.repr(self.tcx()));
debug!("b_prime={}", b_prime.repr(self.tcx()));
debug!("a_prime={}", a_prime.repr(tcx));
debug!("b_prime={}", b_prime.repr(tcx));
// Compare types now that bound regions have been replaced.
let result = try!(Combineable::combine(self, &a_prime, &b_prime));
let result = try!(self.sub().relate(&a_prime, &b_prime));
// Presuming type comparison succeeds, we need to check
// that the skolemized regions do not "leak".
match leak_check(self.infcx(), &skol_map, snapshot) {
match leak_check(self.infcx, &skol_map, snapshot) {
Ok(()) => { }
Err((skol_br, tainted_region)) => {
if self.a_is_expected() {
if self.a_is_expected {
debug!("Not as polymorphic!");
return Err(ty::terr_regions_insufficiently_polymorphic(skol_br,
tainted_region));
......@@ -98,42 +99,42 @@ fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
}
debug!("higher_ranked_sub: OK result={}",
result.repr(self.tcx()));
result.repr(tcx));
Ok(ty::Binder(result))
});
}
fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> CombineResult<'tcx, Binder<T>>
where T : Combineable<'tcx>
fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>
{
// Start a snapshot so we can examine "all bindings that were
// created as part of this type comparison".
return self.infcx().commit_if_ok(|snapshot| {
return self.infcx.commit_if_ok(|snapshot| {
// Instantiate each bound region with a fresh region variable.
let span = self.trace().origin.span();
let span = self.trace.origin.span();
let (a_with_fresh, a_map) =
self.infcx().replace_late_bound_regions_with_fresh_var(
self.infcx.replace_late_bound_regions_with_fresh_var(
span, HigherRankedType, a);
let (b_with_fresh, _) =
self.infcx().replace_late_bound_regions_with_fresh_var(
self.infcx.replace_late_bound_regions_with_fresh_var(
span, HigherRankedType, b);
// Collect constraints.
let result0 =
try!(Combineable::combine(self, &a_with_fresh, &b_with_fresh));
try!(self.lub().relate(&a_with_fresh, &b_with_fresh));
let result0 =
self.infcx().resolve_type_vars_if_possible(&result0);
self.infcx.resolve_type_vars_if_possible(&result0);
debug!("lub result0 = {}", result0.repr(self.tcx()));
// Generalize the regions appearing in result0 if possible
let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot);
let span = self.trace().origin.span();
let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
let span = self.trace.origin.span();
let result1 =
fold_regions_in(
self.tcx(),
&result0,
|r, debruijn| generalize_region(self.infcx(), span, snapshot, debruijn,
|r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
&new_vars, &a_map, r));
debug!("lub({},{}) = {}",
......@@ -194,40 +195,40 @@ fn generalize_region(infcx: &InferCtxt,
}
}
fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> CombineResult<'tcx, Binder<T>>
where T : Combineable<'tcx>
fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>
{
debug!("{}.higher_ranked_glb({}, {})",
self.tag(), a.repr(self.tcx()), b.repr(self.tcx()));
debug!("higher_ranked_glb({}, {})",
a.repr(self.tcx()), b.repr(self.tcx()));
// Make a snapshot so we can examine "all bindings that were
// created as part of this type comparison".
return self.infcx().commit_if_ok(|snapshot| {
return self.infcx.commit_if_ok(|snapshot| {
// Instantiate each bound region with a fresh region variable.
let (a_with_fresh, a_map) =
self.infcx().replace_late_bound_regions_with_fresh_var(
self.trace().origin.span(), HigherRankedType, a);
self.infcx.replace_late_bound_regions_with_fresh_var(
self.trace.origin.span(), HigherRankedType, a);
let (b_with_fresh, b_map) =
self.infcx().replace_late_bound_regions_with_fresh_var(
self.trace().origin.span(), HigherRankedType, b);
self.infcx.replace_late_bound_regions_with_fresh_var(
self.trace.origin.span(), HigherRankedType, b);
let a_vars = var_ids(self, &a_map);
let b_vars = var_ids(self, &b_map);
// Collect constraints.
let result0 =
try!(Combineable::combine(self, &a_with_fresh, &b_with_fresh));
try!(self.glb().relate(&a_with_fresh, &b_with_fresh));
let result0 =
self.infcx().resolve_type_vars_if_possible(&result0);
self.infcx.resolve_type_vars_if_possible(&result0);
debug!("glb result0 = {}", result0.repr(self.tcx()));
// Generalize the regions appearing in result0 if possible
let new_vars = self.infcx().region_vars_confined_to_snapshot(snapshot);
let span = self.trace().origin.span();
let new_vars = self.infcx.region_vars_confined_to_snapshot(snapshot);
let span = self.trace.origin.span();
let result1 =
fold_regions_in(
self.tcx(),
&result0,
|r, debruijn| generalize_region(self.infcx(), span, snapshot, debruijn,
|r, debruijn| generalize_region(self.infcx, span, snapshot, debruijn,
&new_vars,
&a_map, &a_vars, &b_vars,
r));
......@@ -332,17 +333,19 @@ fn fresh_bound_variable(infcx: &InferCtxt, debruijn: ty::DebruijnIndex) -> ty::R
}
}
fn var_ids<'tcx, T: Combine<'tcx>>(combiner: &T,
map: &FnvHashMap<ty::BoundRegion, ty::Region>)
-> Vec<ty::RegionVid> {
map.iter().map(|(_, r)| match *r {
ty::ReInfer(ty::ReVar(r)) => { r }
r => {
combiner.infcx().tcx.sess.span_bug(
combiner.trace().origin.span(),
&format!("found non-region-vid: {:?}", r));
}
}).collect()
fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx>,
map: &FnvHashMap<ty::BoundRegion, ty::Region>)
-> Vec<ty::RegionVid> {
map.iter()
.map(|(_, r)| match *r {
ty::ReInfer(ty::ReVar(r)) => { r }
r => {
fields.tcx().sess.span_bug(
fields.trace.origin.span(),
&format!("found non-region-vid: {:?}", r));
}
})
.collect()
}
fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region) -> bool {
......@@ -356,8 +359,8 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>,
unbound_value: &T,
mut fldr: F)
-> T
where T : Combineable<'tcx>,
F : FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
where T: TypeFoldable<'tcx>,
F: FnMut(ty::Region, ty::DebruijnIndex) -> ty::Region,
{
unbound_value.fold_with(&mut ty_fold::RegionFolder::new(tcx, &mut |region, current_depth| {
// we should only be encountering "escaping" late-bound regions here,
......
......@@ -29,48 +29,32 @@
//! over a `LatticeValue`, which is a value defined with respect to
//! a lattice.
use super::*;
use super::combine::*;
use super::glb::Glb;
use super::lub::Lub;
use super::combine;
use super::InferCtxt;
use middle::ty::TyVar;
use middle::ty::{self, Ty};
use middle::ty_relate::{RelateResult, TypeRelation};
use util::ppaux::Repr;
pub trait LatticeDir<'tcx> {
pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> {
fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
// Relates the type `v` to `a` and `b` such that `v` represents
// the LUB/GLB of `a` and `b` as appropriate.
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, ()>;
}
impl<'a, 'tcx> LatticeDir<'tcx> for Lub<'a, 'tcx> {
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, ()> {
let sub = self.sub();
try!(sub.tys(a, v));
try!(sub.tys(b, v));
Ok(())
}
}
impl<'a, 'tcx> LatticeDir<'tcx> for Glb<'a, 'tcx> {
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, ()> {
let sub = self.sub();
try!(sub.tys(v, a));
try!(sub.tys(v, b));
Ok(())
}
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
}
pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> CombineResult<'tcx, Ty<'tcx>>
pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> RelateResult<'tcx, Ty<'tcx>>
where 'tcx: 'a
{
debug!("{}.lattice_tys({}, {})",
this.tag(),
a.repr(this.infcx().tcx),
b.repr(this.infcx().tcx));
a.repr(this.tcx()),
b.repr(this.tcx()));
if a == b {
return Ok(a);
......@@ -95,7 +79,7 @@ pub fn super_lattice_tys<'tcx, L:LatticeDir<'tcx>+Combine<'tcx>>(this: &L,
}
_ => {
super_tys(this, a, b)
combine::super_combine_tys(this.infcx(), this, a, b)
}
}
}
......@@ -8,67 +8,80 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::combine::*;
use super::combine::CombineFields;
use super::higher_ranked::HigherRankedRelations;
use super::lattice::*;
use super::CombineResult;
use super::InferCtxt;
use super::lattice::{self, LatticeDir};
use super::Subtype;
use middle::ty::{self, Ty};
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use util::ppaux::Repr;
/// "Least upper bound" (common supertype)
pub struct Lub<'f, 'tcx: 'f> {
fields: CombineFields<'f, 'tcx>
pub struct Lub<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
}
#[allow(non_snake_case)]
pub fn Lub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Lub<'f, 'tcx> {
Lub { fields: cf }
impl<'a, 'tcx> Lub<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Lub<'a, 'tcx> {
Lub { fields: fields }
}
}
impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> {
fn tag(&self) -> String { "Lub".to_string() }
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
fn tag(&self) -> &'static str { "Lub" }
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-> CombineResult<'tcx, Ty<'tcx>>
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
{
match v {
ty::Invariant => self.equate().tys(a, b),
ty::Covariant => self.tys(a, b),
ty::Bivariant => self.bivariate().tys(a, b),
ty::Contravariant => self.glb().tys(a, b),
match variance {
ty::Invariant => self.fields.equate().relate(a, b),
ty::Covariant => self.relate(a, b),
ty::Bivariant => self.fields.bivariate().relate(a, b),
ty::Contravariant => self.fields.glb().relate(a, b),
}
}
fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-> CombineResult<'tcx, ty::Region>
{
match v {
ty::Invariant => self.equate().regions(a, b),
ty::Covariant => self.regions(a, b),
ty::Bivariant => self.bivariate().regions(a, b),
ty::Contravariant => self.glb().regions(a, b),
}
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
lattice::super_lattice_tys(self, a, b)
}
fn regions(&self, a: ty::Region, b: ty::Region) -> CombineResult<'tcx, ty::Region> {
fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
a.repr(self.tcx()),
b.repr(self.tcx()));
Ok(self.infcx().region_vars.lub_regions(Subtype(self.trace()), a, b))
let origin = Subtype(self.fields.trace.clone());
Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b))
}
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
super_lattice_tys(self, a, b)
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'a, 'tcx>
{
self.fields.higher_ranked_lub(a, b)
}
}
fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> CombineResult<'tcx, ty::Binder<T>>
where T : Combineable<'tcx>
{
self.higher_ranked_lub(a, b)
impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> {
fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
self.fields.infcx
}
fn relate_bound(&self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()> {
let mut sub = self.fields.sub();
try!(sub.relate(&a, &v));
try!(sub.relate(&b, &v));
Ok(())
}
}
......@@ -28,7 +28,8 @@
use middle::ty::replace_late_bound_regions;
use middle::ty::{self, Ty};
use middle::ty_fold::{TypeFolder, TypeFoldable};
use std::cell::RefCell;
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use std::cell::{RefCell};
use std::fmt;
use std::rc::Rc;
use syntax::ast;
......@@ -38,11 +39,8 @@
use util::ppaux::ty_to_string;
use util::ppaux::{Repr, UserString};
use self::combine::{Combine, Combineable, CombineFields};
use self::combine::CombineFields;
use self::region_inference::{RegionVarBindings, RegionSnapshot};
use self::equate::Equate;
use self::sub::Sub;
use self::lub::Lub;
use self::unify::{ToType, UnificationTable};
use self::error_reporting::ErrorReporting;
......@@ -62,9 +60,7 @@
pub mod unify;
pub type Bound<T> = Option<T>;
pub type CombineResult<'tcx, T> = Result<T,ty::type_err<'tcx>>; // "combine result"
pub type UnitResult<'tcx> = CombineResult<'tcx, ()>; // "unify result"
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
pub type fres<T> = Result<T, fixup_err>; // "fixup result"
pub struct InferCtxt<'a, 'tcx: 'a> {
......@@ -343,7 +339,7 @@ pub fn common_supertype<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
values: Types(expected_found(a_is_expected, a, b))
};
let result = cx.commit_if_ok(|_| cx.lub(a_is_expected, trace.clone()).tys(a, b));
let result = cx.commit_if_ok(|_| cx.lub(a_is_expected, trace.clone()).relate(&a, &b));
match result {
Ok(t) => t,
Err(ref err) => {
......@@ -374,11 +370,12 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
origin: Misc(codemap::DUMMY_SP),
values: Types(expected_found(true, a, b))
};
cx.sub(true, trace).tys(a, b).map(|_| ())
cx.sub(true, trace).relate(&a, &b).map(|_| ())
})
}
pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> UnitResult<'tcx>
pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
-> UnitResult<'tcx>
{
cx.can_equate(&a, &b)
}
......@@ -473,26 +470,39 @@ pub fn type_is_unconstrained_numeric(&'a self, ty: Ty) -> UnconstrainedNumeric {
}
}
fn combine_fields<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> CombineFields<'b, 'tcx> {
fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> CombineFields<'a, 'tcx> {
CombineFields {infcx: self,
a_is_expected: a_is_expected,
trace: trace}
}
fn equate<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> Equate<'b, 'tcx> {
Equate(self.combine_fields(a_is_expected, trace))
// public so that it can be used from the rustc_driver unit tests
pub fn equate(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> equate::Equate<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).equate()
}
fn sub<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> Sub<'b, 'tcx> {
Sub(self.combine_fields(a_is_expected, trace))
// public so that it can be used from the rustc_driver unit tests
pub fn sub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> sub::Sub<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).sub()
}
fn lub<'b>(&'b self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> Lub<'b, 'tcx> {
Lub(self.combine_fields(a_is_expected, trace))
// public so that it can be used from the rustc_driver unit tests
pub fn lub(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> lub::Lub<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).lub()
}
// public so that it can be used from the rustc_driver unit tests
pub fn glb(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-> glb::Glb<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).glb()
}
fn start_snapshot(&self) -> CombinedSnapshot {
......@@ -631,7 +641,7 @@ pub fn sub_types(&self,
debug!("sub_types({} <: {})", a.repr(self.tcx), b.repr(self.tcx));
self.commit_if_ok(|_| {
let trace = TypeTrace::types(origin, a_is_expected, a, b);
self.sub(a_is_expected, trace).tys(a, b).map(|_| ())
self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ())
})
}
......@@ -644,7 +654,7 @@ pub fn eq_types(&self,
{
self.commit_if_ok(|_| {
let trace = TypeTrace::types(origin, a_is_expected, a, b);
self.equate(a_is_expected, trace).tys(a, b).map(|_| ())
self.equate(a_is_expected, trace).relate(&a, &b).map(|_| ())
})
}
......@@ -663,7 +673,7 @@ pub fn sub_trait_refs(&self,
origin: origin,
values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
};
self.sub(a_is_expected, trace).trait_refs(&*a, &*b).map(|_| ())
self.sub(a_is_expected, trace).relate(&*a, &*b).map(|_| ())
})
}
......@@ -682,7 +692,7 @@ pub fn sub_poly_trait_refs(&self,
origin: origin,
values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
};
self.sub(a_is_expected, trace).binders(&a, &b).map(|_| ())
self.sub(a_is_expected, trace).relate(&a, &b).map(|_| ())
})
}
......@@ -1045,8 +1055,8 @@ pub fn verify_generic_bound(&self,
self.region_vars.verify_generic_bound(origin, kind, a, bs);
}
pub fn can_equate<T>(&self, a: &T, b: &T) -> UnitResult<'tcx>
where T : Combineable<'tcx> + Repr<'tcx>
pub fn can_equate<'b,T>(&'b self, a: &T, b: &T) -> UnitResult<'tcx>
where T: Relate<'b,'tcx> + Repr<'tcx>
{
debug!("can_equate({}, {})", a.repr(self.tcx), b.repr(self.tcx));
self.probe(|_| {
......@@ -1057,8 +1067,7 @@ pub fn can_equate<T>(&self, a: &T, b: &T) -> UnitResult<'tcx>
let e = self.tcx.types.err;
let trace = TypeTrace { origin: Misc(codemap::DUMMY_SP),
values: Types(expected_found(true, e, e)) };
let eq = self.equate(true, trace);
Combineable::combine(&eq, a, b)
self.equate(true, trace).relate(a, b)
}).map(|_| ())
}
}
......
......@@ -18,7 +18,6 @@
pub use self::VarValue::*;
use self::Classification::*;
use super::CombineResult;
use super::{RegionVariableOrigin, SubregionOrigin, TypeTrace, MiscVariable};
use middle::region;
......@@ -26,6 +25,7 @@
use middle::ty::{BoundRegion, FreeRegion, Region, RegionVid};
use middle::ty::{ReEmpty, ReStatic, ReInfer, ReFree, ReEarlyBound};
use middle::ty::{ReLateBound, ReScope, ReVar, ReSkolemized, BrFresh};
use middle::ty_relate::RelateResult;
use middle::graph;
use middle::graph::{Direction, NodeIndex};
use util::common::indenter;
......@@ -825,7 +825,7 @@ fn helper(this: &RegionVarBindings,
fn glb_concrete_regions(&self,
a: Region,
b: Region)
-> CombineResult<'tcx, Region>
-> RelateResult<'tcx, Region>
{
debug!("glb_concrete_regions({:?}, {:?})", a, b);
match (a, b) {
......@@ -901,7 +901,7 @@ fn glb_concrete_regions(&self,
fn glb_free_regions(&self,
a: &FreeRegion,
b: &FreeRegion)
-> CombineResult<'tcx, ty::Region>
-> RelateResult<'tcx, ty::Region>
{
return match a.cmp(b) {
Less => helper(self, a, b),
......@@ -911,7 +911,7 @@ fn glb_free_regions(&self,
fn helper<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
a: &FreeRegion,
b: &FreeRegion) -> CombineResult<'tcx, ty::Region>
b: &FreeRegion) -> RelateResult<'tcx, ty::Region>
{
if this.tcx.region_maps.sub_free_region(*a, *b) {
Ok(ty::ReFree(*a))
......@@ -930,7 +930,7 @@ fn intersect_scopes(&self,
region_b: ty::Region,
scope_a: region::CodeExtent,
scope_b: region::CodeExtent)
-> CombineResult<'tcx, Region>
-> RelateResult<'tcx, Region>
{
// We want to generate the intersection of two
// scopes or two free regions. So, if one of
......
......@@ -8,64 +8,49 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use super::combine::*;
use super::CombineResult;
use super::combine::{self, CombineFields};
use super::higher_ranked::HigherRankedRelations;
use super::Subtype;
use super::type_variable::{SubtypeOf, SupertypeOf};
use middle::ty::{self, Ty};
use middle::ty::TyVar;
use util::ppaux::Repr;
use middle::ty_relate::{Relate, RelateResult, TypeRelation};
use util::ppaux::{Repr};
/// "Greatest lower bound" (common subtype)
pub struct Sub<'f, 'tcx: 'f> {
fields: CombineFields<'f, 'tcx>
pub struct Sub<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
}
#[allow(non_snake_case)]
pub fn Sub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Sub<'f, 'tcx> {
Sub { fields: cf }
impl<'a, 'tcx> Sub<'a, 'tcx> {
pub fn new(f: CombineFields<'a, 'tcx>) -> Sub<'a, 'tcx> {
Sub { fields: f }
}
}
impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
fn tag(&self) -> String { "Sub".to_string() }
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
-> CombineResult<'tcx, Ty<'tcx>>
{
match v {
ty::Invariant => self.equate().tys(a, b),
ty::Covariant => self.tys(a, b),
ty::Bivariant => self.bivariate().tys(a, b),
ty::Contravariant => Sub(self.fields.switch_expected()).tys(b, a),
}
}
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
fn tag(&self) -> &'static str { "Sub" }
fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.infcx.tcx }
fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
-> CombineResult<'tcx, ty::Region>
fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
variance: ty::Variance,
a: &T,
b: &T)
-> RelateResult<'tcx, T>
{
match v {
ty::Invariant => self.equate().regions(a, b),
ty::Covariant => self.regions(a, b),
ty::Bivariant => self.bivariate().regions(a, b),
ty::Contravariant => Sub(self.fields.switch_expected()).regions(b, a),
match variance {
ty::Invariant => self.fields.equate().relate(a, b),
ty::Covariant => self.relate(a, b),
ty::Bivariant => self.fields.bivariate().relate(a, b),
ty::Contravariant => self.fields.switch_expected().sub().relate(b, a),
}
}
fn regions(&self, a: ty::Region, b: ty::Region) -> CombineResult<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
a.repr(self.tcx()),
b.repr(self.tcx()));
self.infcx().region_vars.make_subregion(Subtype(self.trace()), a, b);
Ok(a)
}
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug!("{}.tys({}, {})", self.tag(), a.repr(self.tcx()), b.repr(self.tcx()));
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
debug!("{}.tys({}, {})", self.tag(),
a.repr(self.tcx()), b.repr(self.tcx()));
if a == b { return Ok(a); }
let infcx = self.fields.infcx;
......@@ -80,8 +65,8 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
}
(&ty::ty_infer(TyVar(a_id)), _) => {
try!(self.fields
.switch_expected()
.instantiate(b, SupertypeOf, a_id));
.switch_expected()
.instantiate(b, SupertypeOf, a_id));
Ok(a)
}
(_, &ty::ty_infer(TyVar(b_id))) => {
......@@ -94,14 +79,25 @@ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CombineResult<'tcx, Ty<'tcx>> {
}
_ => {
super_tys(self, a, b)
combine::super_combine_tys(self.fields.infcx, self, a, b)
}
}
}
fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> CombineResult<'tcx, ty::Binder<T>>
where T : Combineable<'tcx>
fn regions(&mut self, a: ty::Region, b: ty::Region) -> RelateResult<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
a.repr(self.tcx()),
b.repr(self.tcx()));
let origin = Subtype(self.fields.trace.clone());
self.fields.infcx.region_vars.make_subregion(origin, a, b);
Ok(a)
}
fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
-> RelateResult<'tcx, ty::Binder<T>>
where T: Relate<'a,'tcx>
{
self.higher_ranked_sub(a, b)
self.fields.higher_ranked_sub(a, b)
}
}
......@@ -291,6 +291,7 @@ fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
}
}
#[derive(Clone)]
pub struct Normalized<'tcx,T> {
pub value: T,
pub obligations: Vec<PredicateObligation<'tcx>>,
......
......@@ -39,6 +39,8 @@
use middle::ty::{self, Ty};
use middle::traits;
use std::rc::Rc;
use syntax::abi;
use syntax::ast;
use syntax::owned_slice::OwnedSlice;
use util::ppaux::Repr;
......@@ -47,7 +49,7 @@
/// The TypeFoldable trait is implemented for every type that can be folded.
/// Basically, every type that has a corresponding method in TypeFolder.
pub trait TypeFoldable<'tcx> {
pub trait TypeFoldable<'tcx>: Repr<'tcx> + Clone {
fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
}
......@@ -149,12 +151,20 @@ fn fold_item_substs(&mut self, i: ty::ItemSubsts<'tcx>) -> ty::ItemSubsts<'tcx>
// can easily refactor the folding into the TypeFolder trait as
// needed.
impl<'tcx> TypeFoldable<'tcx> for () {
fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> () {
()
macro_rules! CopyImpls {
($($ty:ty),+) => {
$(
impl<'tcx> TypeFoldable<'tcx> for $ty {
fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> $ty {
*self
}
}
)+
}
}
CopyImpls! { (), ast::Unsafety, abi::Abi }
impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
(self.0.fold_with(folder), self.1.fold_with(folder))
......
此差异已折叠。
......@@ -1532,3 +1532,9 @@ fn user_string(&self, tcx: &ctxt<'tcx>) -> String {
}
}
}
impl<'tcx> Repr<'tcx> for ast::Unsafety {
fn repr(&self, _: &ctxt<'tcx>) -> String {
format!("{:?}", *self)
}
}
......@@ -22,7 +22,7 @@
use rustc_typeck::middle::subst;
use rustc_typeck::middle::subst::Subst;
use rustc_typeck::middle::ty::{self, Ty};
use rustc_typeck::middle::infer::combine::Combine;
use rustc_typeck::middle::ty_relate::TypeRelation;
use rustc_typeck::middle::infer;
use rustc_typeck::middle::infer::lub::Lub;
use rustc_typeck::middle::infer::glb::Glb;
......@@ -350,21 +350,21 @@ pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> {
pub fn sub(&self) -> Sub<'a, 'tcx> {
let trace = self.dummy_type_trace();
Sub(self.infcx.combine_fields(true, trace))
self.infcx.sub(true, trace)
}
pub fn lub(&self) -> Lub<'a, 'tcx> {
let trace = self.dummy_type_trace();
Lub(self.infcx.combine_fields(true, trace))
self.infcx.lub(true, trace)
}
pub fn glb(&self) -> Glb<'a, 'tcx> {
let trace = self.dummy_type_trace();
Glb(self.infcx.combine_fields(true, trace))
self.infcx.glb(true, trace)
}
pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> {
match self.lub().tys(t1, t2) {
match self.lub().relate(&t1, &t2) {
Ok(t) => t,
Err(ref e) => panic!("unexpected error computing LUB: {}",
ty::type_err_to_str(self.infcx.tcx, e))
......@@ -374,7 +374,7 @@ pub fn make_lub_ty(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> Ty<'tcx> {
/// Checks that `t1 <: t2` is true (this may register additional
/// region checks).
pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
match self.sub().tys(t1, t2) {
match self.sub().relate(&t1, &t2) {
Ok(_) => { }
Err(ref e) => {
panic!("unexpected error computing sub({},{}): {}",
......@@ -388,7 +388,7 @@ pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
/// Checks that `t1 <: t2` is false (this may register additional
/// region checks).
pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
match self.sub().tys(t1, t2) {
match self.sub().relate(&t1, &t2) {
Err(_) => { }
Ok(_) => {
panic!("unexpected success computing sub({},{})",
......@@ -400,7 +400,7 @@ pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
/// Checks that `LUB(t1,t2) == t_lub`
pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) {
match self.lub().tys(t1, t2) {
match self.lub().relate(&t1, &t2) {
Ok(t) => {
self.assert_eq(t, t_lub);
}
......@@ -417,7 +417,7 @@ pub fn check_glb(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_glb: Ty<'tcx>) {
self.ty_to_string(t1),
self.ty_to_string(t2),
self.ty_to_string(t_glb));
match self.glb().tys(t1, t2) {
match self.glb().relate(&t1, &t2) {
Err(e) => {
panic!("unexpected error computing LUB: {:?}", e)
}
......
......@@ -62,11 +62,11 @@
use check::{autoderef, FnCtxt, NoPreference, PreferMutLvalue, UnresolvedTypeAction};
use middle::infer::{self, CombineResult, Coercion};
use middle::infer::combine::Combine;
use middle::infer::{self, Coercion};
use middle::subst;
use middle::ty::{AutoPtr, AutoDerefRef, AdjustDerefRef, AutoUnsize, AutoUnsafe};
use middle::ty::{self, mt, Ty};
use middle::ty_relate::RelateResult;
use util::common::indent;
use util::ppaux;
use util::ppaux::Repr;
......@@ -78,7 +78,7 @@ struct Coerce<'a, 'tcx: 'a> {
origin: infer::TypeOrigin,
}
type CoerceResult<'tcx> = CombineResult<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
type CoerceResult<'tcx> = RelateResult<'tcx, Option<ty::AutoAdjustment<'tcx>>>;
impl<'f, 'tcx> Coerce<'f, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> {
......@@ -536,7 +536,7 @@ pub fn mk_assignty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
expr: &ast::Expr,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> CombineResult<'tcx, ()> {
-> RelateResult<'tcx, ()> {
debug!("mk_assignty({} -> {})", a.repr(fcx.tcx()), b.repr(fcx.tcx()));
let adjustment = try!(indent(|| {
fcx.infcx().commit_if_ok(|_| {
......
......@@ -30,7 +30,6 @@
use middle::ty::ty_projection;
use middle::ty;
use CrateCtxt;
use middle::infer::combine::Combine;
use middle::infer::InferCtxt;
use middle::infer::new_infer_ctxt;
use std::collections::HashSet;
......
......@@ -23,10 +23,6 @@ pub fn main() {
let f2: &Fat<[isize; 3]> = &f1;
let f3: &Fat<[usize]> = f2;
//~^ ERROR mismatched types
//~| expected `&Fat<[usize]>`
//~| found `&Fat<[isize; 3]>`
//~| expected usize
//~| found isize
// With a trait.
let f1 = Fat { ptr: Foo };
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册