Skip to content

Plumb inference obligations through librustc/middle and librustc_typeck #31759

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 7 additions & 10 deletions src/librustc/middle/infer/bivariate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use super::type_variable::{BiTo};

use middle::ty::{self, Ty};
use middle::ty::TyVar;
use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation};

pub struct Bivariate<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
Expand Down Expand Up @@ -74,25 +74,23 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug!("{}.tys({:?}, {:?})", self.tag(),
a, b);
if a == b { return Ok(a); }
if a == b { return Ok(RelateOk::from(a)); }

let infcx = self.fields.infcx;
let a = infcx.type_variables.borrow().replace_if_possible(a);
let b = infcx.type_variables.borrow().replace_if_possible(b);
match (&a.sty, &b.sty) {
(&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id);
Ok(a)
Ok(RelateOk::from(a))
}

(&ty::TyInfer(TyVar(a_id)), _) => {
try!(self.fields.instantiate(b, BiTo, a_id));
Ok(a)
self.fields.instantiate(b, BiTo, a_id).map_value(|_| a)
}

(_, &ty::TyInfer(TyVar(b_id))) => {
try!(self.fields.instantiate(a, BiTo, b_id));
Ok(a)
self.fields.instantiate(a, BiTo, b_id).map_value(|_| a)
}

_ => {
Expand All @@ -102,7 +100,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
}

fn regions(&mut self, a: ty::Region, _: ty::Region) -> RelateResult<'tcx, ty::Region> {
Ok(a)
Ok(RelateOk::from(a))
}

fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
Expand All @@ -111,7 +109,6 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
{
let a1 = self.tcx().erase_late_bound_regions(a);
let b1 = self.tcx().erase_late_bound_regions(b);
let c = try!(self.relate(&a1, &b1));
Ok(ty::Binder(c))
self.relate(&a1, &b1).map_value(|c| ty::Binder(c))
}
}
32 changes: 18 additions & 14 deletions src/librustc/middle/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use middle::ty::{IntType, UintType};
use middle::ty::{self, Ty};
use middle::ty::error::TypeError;
use middle::ty::fold::{TypeFolder, TypeFoldable};
use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use middle::ty::relate::{Relate, RelateOk, RelateResult, TypeRelation};

use syntax::ast;
use syntax::codemap::Span;
Expand Down Expand Up @@ -74,7 +74,7 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
.borrow_mut()
.unify_var_var(a_id, b_id)
.map_err(|e| int_unification_error(a_is_expected, e)));
Ok(a)
Ok(RelateOk::from(a))
}
(&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => {
unify_integral_variable(infcx, a_is_expected, v_id, IntType(v))
Expand All @@ -95,7 +95,7 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
.borrow_mut()
.unify_var_var(a_id, b_id)
.map_err(|e| float_unification_error(relation.a_is_expected(), e)));
Ok(a)
Ok(RelateOk::from(a))
}
(&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => {
unify_float_variable(infcx, a_is_expected, v_id, v)
Expand Down Expand Up @@ -129,8 +129,8 @@ fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
.unify_var_value(vid, val)
.map_err(|e| int_unification_error(vid_is_expected, e)));
match val {
IntType(v) => Ok(infcx.tcx.mk_mach_int(v)),
UintType(v) => Ok(infcx.tcx.mk_mach_uint(v)),
IntType(v) => Ok(RelateOk::from(infcx.tcx.mk_mach_int(v))),
UintType(v) => Ok(RelateOk::from(infcx.tcx.mk_mach_uint(v))),
}
}

Expand All @@ -145,7 +145,7 @@ fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
.borrow_mut()
.unify_var_value(vid, val)
.map_err(|e| float_unification_error(vid_is_expected, e)));
Ok(infcx.tcx.mk_mach_float(val))
Ok(RelateOk::from(infcx.tcx.mk_mach_float(val)))
}

impl<'a, 'tcx> CombineFields<'a, 'tcx> {
Expand Down Expand Up @@ -187,6 +187,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
-> RelateResult<'tcx, ()>
{
let mut stack = Vec::new();
let mut obligations = Vec::new();
stack.push((a_ty, dir, b_vid));
loop {
// For each turn of the loop, we extract a tuple
Expand Down Expand Up @@ -224,10 +225,11 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
Some(t) => t, // ...already instantiated.
None => { // ...not yet instantiated:
// Generalize type if necessary.
let generalized_ty = try!(match dir {
EqTo => self.generalize(a_ty, b_vid, false),
BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
});
let RelateOk { value: generalized_ty, obligations: new_obligations } =
try!(match dir {
EqTo => self.generalize(a_ty, b_vid, false),
BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
});
debug!("instantiate(a_ty={:?}, dir={:?}, \
b_vid={:?}, generalized_ty={:?})",
a_ty, dir, b_vid,
Expand All @@ -236,6 +238,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
.borrow_mut()
.instantiate_and_push(
b_vid, generalized_ty, &mut stack);
obligations.extend(new_obligations);
generalized_ty
}
};
Expand All @@ -247,15 +250,16 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
// relations wind up attributed to the same spans. We need
// to associate causes/spans with each of the relations in
// the stack to get this right.
try!(match dir {
let RelateOk { obligations: new_obligations, .. } = try!(match dir {
BiTo => self.bivariate().relate(&a_ty, &b_ty),
EqTo => self.equate().relate(&a_ty, &b_ty),
SubtypeOf => self.sub().relate(&a_ty, &b_ty),
SupertypeOf => self.sub().relate_with_variance(ty::Contravariant, &a_ty, &b_ty),
});
obligations.extend(new_obligations);
}

Ok(())
Ok(RelateOk { value: (), obligations: obligations })
}

/// Attempts to generalize `ty` for the type variable `for_vid`. This checks for cycle -- that
Expand All @@ -279,7 +283,7 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
if generalize.cycle_detected {
Err(TypeError::CyclicTy)
} else {
Ok(u)
Ok(RelateOk::from(u))
}
}
}
Expand Down Expand Up @@ -370,7 +374,7 @@ impl<'tcx, T:Clone + PartialEq> RelateResultCompare<'tcx, T> for RelateResult<'t
F: FnOnce() -> TypeError<'tcx>,
{
self.clone().and_then(|s| {
if s == t {
if s.value == t {
self.clone()
} else {
Err(f())
Expand Down
21 changes: 9 additions & 12 deletions src/librustc/middle/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use super::type_variable::{EqTo};

use middle::ty::{self, Ty};
use middle::ty::TyVar;
use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation};

/// Ensures `a` is made equal to `b`. Returns `a` on success.
pub struct Equate<'a, 'tcx: 'a> {
Expand Down Expand Up @@ -47,30 +47,27 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
debug!("{}.tys({:?}, {:?})", self.tag(),
a, b);
if a == b { return Ok(a); }
if a == b { return Ok(RelateOk::from(a)); }

let infcx = self.fields.infcx;
let a = infcx.type_variables.borrow().replace_if_possible(a);
let b = infcx.type_variables.borrow().replace_if_possible(b);
match (&a.sty, &b.sty) {
(&ty::TyInfer(TyVar(a_id)), &ty::TyInfer(TyVar(b_id))) => {
infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id);
Ok(a)
Ok(RelateOk::from(a))
}

(&ty::TyInfer(TyVar(a_id)), _) => {
try!(self.fields.instantiate(b, EqTo, a_id));
Ok(a)
self.fields.instantiate(b, EqTo, a_id).map_value(|_| a)
}

(_, &ty::TyInfer(TyVar(b_id))) => {
try!(self.fields.instantiate(a, EqTo, b_id));
Ok(a)
self.fields.instantiate(a, EqTo, b_id).map_value(|_| a)
}

_ => {
try!(combine::super_combine_tys(self.fields.infcx, self, a, b));
Ok(a)
combine::super_combine_tys(self.fields.infcx, self, a, b).map_value(|_| a)
}
}
}
Expand All @@ -82,14 +79,14 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
b);
let origin = Subtype(self.fields.trace.clone());
self.fields.infcx.region_vars.make_eqregion(origin, a, b);
Ok(a)
Ok(RelateOk::from(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.fields.higher_ranked_sub(a, b));
self.fields.higher_ranked_sub(b, a)
self.fields.higher_ranked_sub(a, b)
.and_then_with(|_| self.fields.higher_ranked_sub(b, a))
}
}
10 changes: 5 additions & 5 deletions src/librustc/middle/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use super::lattice::{self, LatticeDir};
use super::Subtype;

use middle::ty::{self, Ty};
use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation};

/// "Greatest lower bound" (common subtype)
pub struct Glb<'a, 'tcx: 'a> {
Expand Down Expand Up @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
b);

let origin = Subtype(self.fields.trace.clone());
Ok(self.fields.infcx.region_vars.glb_regions(origin, a, b))
Ok(RelateOk::from(self.fields.infcx.region_vars.glb_regions(origin, a, b)))
}

fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
Expand All @@ -78,8 +78,8 @@ impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> {

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(())
sub.relate(&v, &a)
.and_then_with(|_| sub.relate(&v, &b))
.and_then_with(|_| Ok(RelateOk::from(())))
}
}
12 changes: 6 additions & 6 deletions src/librustc/middle/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use super::combine::CombineFields;

use middle::ty::{self, Binder, TypeFoldable};
use middle::ty::error::TypeError;
use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation};
use syntax::codemap::Span;
use util::nodemap::{FnvHashMap, FnvHashSet};

Expand Down Expand Up @@ -97,7 +97,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
debug!("higher_ranked_sub: OK result={:?}",
result);

Ok(ty::Binder(result))
Ok(result).map_value(|r| ty::Binder(r))
});
}

Expand All @@ -117,7 +117,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
span, HigherRankedType, b);

// Collect constraints.
let result0 =
let RelateOk { value: result0, obligations } =
try!(self.lub().relate(&a_with_fresh, &b_with_fresh));
let result0 =
self.infcx.resolve_type_vars_if_possible(&result0);
Expand All @@ -138,7 +138,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
b,
result1);

Ok(ty::Binder(result1))
Ok(RelateOk { value: ty::Binder(result1), obligations: obligations })
});

fn generalize_region(infcx: &InferCtxt,
Expand Down Expand Up @@ -211,7 +211,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
let b_vars = var_ids(self, &b_map);

// Collect constraints.
let result0 =
let RelateOk { value: result0, obligations } =
try!(self.glb().relate(&a_with_fresh, &b_with_fresh));
let result0 =
self.infcx.resolve_type_vars_if_possible(&result0);
Expand All @@ -234,7 +234,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
b,
result1);

Ok(ty::Binder(result1))
Ok(RelateOk { value: ty::Binder(result1), obligations: obligations })
});

fn generalize_region(infcx: &InferCtxt,
Expand Down
10 changes: 4 additions & 6 deletions src/librustc/middle/infer/lattice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ use super::InferCtxt;

use middle::ty::TyVar;
use middle::ty::{self, Ty};
use middle::ty::relate::{RelateResult, TypeRelation};
use middle::ty::relate::{RelateOk, RelateResult, RelateResultTrait, TypeRelation};

pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> {
fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
Expand All @@ -56,7 +56,7 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
b);

if a == b {
return Ok(a);
return Ok(RelateOk::from(a));
}

let infcx = this.infcx();
Expand All @@ -66,15 +66,13 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
(&ty::TyInfer(TyVar(..)), &ty::TyInfer(TyVar(..)))
if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => {
let v = infcx.next_diverging_ty_var();
try!(this.relate_bound(v, a, b));
Ok(v)
this.relate_bound(v, a, b).map_value(|_| v)
}

(&ty::TyInfer(TyVar(..)), _) |
(_, &ty::TyInfer(TyVar(..))) => {
let v = infcx.next_ty_var();
try!(this.relate_bound(v, a, b));
Ok(v)
this.relate_bound(v, a, b).map_value(|_| v)
}

_ => {
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/middle/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use super::lattice::{self, LatticeDir};
use super::Subtype;

use middle::ty::{self, Ty};
use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use middle::ty::relate::{Relate, RelateOk, RelateResult, RelateResultTrait, TypeRelation};

/// "Least upper bound" (common supertype)
pub struct Lub<'a, 'tcx: 'a> {
Expand Down Expand Up @@ -60,7 +60,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
b);

let origin = Subtype(self.fields.trace.clone());
Ok(self.fields.infcx.region_vars.lub_regions(origin, a, b))
Ok(RelateOk::from(self.fields.infcx.region_vars.lub_regions(origin, a, b)))
}

fn binders<T>(&mut self, a: &ty::Binder<T>, b: &ty::Binder<T>)
Expand All @@ -78,8 +78,8 @@ impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> {

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(())
sub.relate(&a, &v)
.and_then_with(|_| sub.relate(&b, &v))
.and_then_with(|_| Ok(RelateOk::from(())))
}
}
Loading