Skip to content

Plumb inference obligations through librustc/middle and librustc_typeck, take 2 #31867

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 11 commits into from
13 changes: 8 additions & 5 deletions src/librustc/middle/infer/bivariate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,25 +28,28 @@
use super::combine::{self, CombineFields};
use super::type_variable::{BiTo};

use middle::traits::PredicateObligation;
use middle::ty::{self, Ty};
use middle::ty::TyVar;
use middle::ty::relate::{Relate, RelateResult, TypeRelation};

pub struct Bivariate<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
pub struct Bivariate<'a, 'o, 'tcx: 'a + 'o> {
fields: CombineFields<'a, 'o, 'tcx>
}

impl<'a, 'tcx> Bivariate<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Bivariate<'a, 'tcx> {
impl<'a, 'o, 'tcx> Bivariate<'a, 'o, 'tcx> {
pub fn new(fields: CombineFields<'a, 'o, 'tcx>) -> Bivariate<'a, 'o, 'tcx> {
Bivariate { fields: fields }
}
}

impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
impl<'a, 'o, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'o, 'tcx> {
fn tag(&self) -> &'static str { "Bivariate" }

fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }

fn obligations(&self) -> &Vec<PredicateObligation<'tcx>> { self.fields.obligations }

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
Expand Down
43 changes: 27 additions & 16 deletions src/librustc/middle/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use super::{InferCtxt};
use super::{MiscVariable, TypeTrace};
use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf};

use middle::traits::PredicateObligation;
use middle::ty::{IntType, UintType};
use middle::ty::{self, Ty};
use middle::ty::error::TypeError;
Expand All @@ -50,12 +51,12 @@ use middle::ty::relate::{Relate, RelateResult, TypeRelation};
use syntax::ast;
use syntax::codemap::Span;

#[derive(Clone)]
pub struct CombineFields<'a, 'tcx: 'a> {
pub struct CombineFields<'a, 'o, 'tcx: 'a + 'o> {
pub infcx: &'a InferCtxt<'a, 'tcx>,
pub a_is_expected: bool,
pub trace: TypeTrace<'tcx>,
pub cause: Option<ty::relate::Cause>,
pub obligations: &'o mut Vec<PredicateObligation<'tcx>>,
}

pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
Expand Down Expand Up @@ -148,39 +149,49 @@ fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
Ok(infcx.tcx.mk_mach_float(val))
}

impl<'a, 'tcx> CombineFields<'a, 'tcx> {
impl<'a, 'o, 'tcx> CombineFields<'a, 'o, 'tcx> {
pub fn tcx(&self) -> &'a ty::ctxt<'tcx> {
self.infcx.tcx
}

pub fn switch_expected(&self) -> CombineFields<'a, 'tcx> {
pub fn switch_expected<'s>(&'s mut self) -> CombineFields<'a, 's, 'tcx> {
CombineFields {
a_is_expected: !self.a_is_expected,
..(*self).clone()
..(*self).clone_and_reborrow()
}
}

pub fn equate(&self) -> Equate<'a, 'tcx> {
Equate::new(self.clone())
pub fn clone_and_reborrow<'s>(&'s mut self) -> CombineFields<'a, 's, 'tcx> {
CombineFields {
infcx: self.infcx,
a_is_expected: self.a_is_expected,
trace: self.trace.clone(),
cause: self.cause.clone(),
obligations: self.obligations,
}
}

pub fn equate<'s>(&'s mut self) -> Equate<'a, 's, 'tcx> {
Equate::new(self.clone_and_reborrow())
}

pub fn bivariate(&self) -> Bivariate<'a, 'tcx> {
Bivariate::new(self.clone())
pub fn bivariate<'s>(&'s mut self) -> Bivariate<'a, 's, 'tcx> {
Bivariate::new(self.clone_and_reborrow())
}

pub fn sub(&self) -> Sub<'a, 'tcx> {
Sub::new(self.clone())
pub fn sub<'s>(&'s mut self) -> Sub<'a, 's, 'tcx> {
Sub::new(self.clone_and_reborrow())
}

pub fn lub(&self) -> Lub<'a, 'tcx> {
Lub::new(self.clone())
pub fn lub<'s>(&'s mut self) -> Lub<'a, 's, 'tcx> {
Lub::new(self.clone_and_reborrow())
}

pub fn glb(&self) -> Glb<'a, 'tcx> {
Glb::new(self.clone())
pub fn glb<'s>(&'s mut self) -> Glb<'a, 's, 'tcx> {
Glb::new(self.clone_and_reborrow())
}

pub fn instantiate(&self,
pub fn instantiate(&mut self,
a_ty: Ty<'tcx>,
dir: RelationDir,
b_vid: ty::TyVid)
Expand Down
13 changes: 8 additions & 5 deletions src/librustc/middle/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,29 @@ use super::higher_ranked::HigherRankedRelations;
use super::{Subtype};
use super::type_variable::{EqTo};

use middle::traits::PredicateObligation;
use middle::ty::{self, Ty};
use middle::ty::TyVar;
use middle::ty::relate::{Relate, RelateResult, TypeRelation};

/// Ensures `a` is made equal to `b`. Returns `a` on success.
pub struct Equate<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
pub struct Equate<'a, 'o, 'tcx: 'a + 'o> {
fields: CombineFields<'a, 'o, 'tcx>
}

impl<'a, 'tcx> Equate<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Equate<'a, 'tcx> {
impl<'a, 'o, 'tcx> Equate<'a, 'o, 'tcx> {
pub fn new(fields: CombineFields<'a, 'o, 'tcx>) -> Equate<'a, 'o, 'tcx> {
Equate { fields: fields }
}
}

impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
impl<'a, 'o, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'o, 'tcx> {
fn tag(&self) -> &'static str { "Equate" }

fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }

fn obligations(&self) -> &Vec<PredicateObligation<'tcx>> { self.fields.obligations }

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
Expand Down
17 changes: 10 additions & 7 deletions src/librustc/middle/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,28 @@ use super::InferCtxt;
use super::lattice::{self, LatticeDir};
use super::Subtype;

use middle::traits::PredicateObligation;
use middle::ty::{self, Ty};
use middle::ty::relate::{Relate, RelateResult, TypeRelation};

/// "Greatest lower bound" (common subtype)
pub struct Glb<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
pub struct Glb<'a, 'o, 'tcx: 'a + 'o> {
fields: CombineFields<'a, 'o, 'tcx>
}

impl<'a, 'tcx> Glb<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Glb<'a, 'tcx> {
impl<'a, 'o, 'tcx> Glb<'a, 'o, 'tcx> {
pub fn new(fields: CombineFields<'a, 'o, 'tcx>) -> Glb<'a, 'o, 'tcx> {
Glb { fields: fields }
}
}

impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
impl<'a, 'o, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'o, 'tcx> {
fn tag(&self) -> &'static str { "Glb" }

fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }

fn obligations(&self) -> &Vec<PredicateObligation<'tcx>> { self.fields.obligations }

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
Expand Down Expand Up @@ -71,12 +74,12 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
}
}

impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> {
impl<'a, 'o, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'o, '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, ()> {
fn relate_bound(&mut 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));
Expand Down
30 changes: 18 additions & 12 deletions src/librustc/middle/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,16 @@ use syntax::codemap::Span;
use util::nodemap::{FnvHashMap, FnvHashSet};

pub trait HigherRankedRelations<'a,'tcx> {
fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
fn higher_ranked_sub<T>(&mut 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>) -> RelateResult<'tcx, Binder<T>>
fn higher_ranked_lub<T>(&mut 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>) -> RelateResult<'tcx, Binder<T>>
fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>)
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>;
}

Expand All @@ -39,8 +42,8 @@ trait InferCtxtExt {
-> Vec<ty::RegionVid>;
}

impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
impl<'a,'o,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'o,'tcx> {
fn higher_ranked_sub<T>(&mut self, a: &Binder<T>, b: &Binder<T>)
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>
{
Expand Down Expand Up @@ -101,7 +104,8 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
});
}

fn higher_ranked_lub<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
fn higher_ranked_lub<T>(&mut 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
Expand Down Expand Up @@ -191,7 +195,8 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
}
}

fn higher_ranked_glb<T>(&self, a: &Binder<T>, b: &Binder<T>) -> RelateResult<'tcx, Binder<T>>
fn higher_ranked_glb<T>(&mut self, a: &Binder<T>, b: &Binder<T>)
-> RelateResult<'tcx, Binder<T>>
where T: Relate<'a,'tcx>
{
debug!("higher_ranked_glb({:?}, {:?})",
Expand Down Expand Up @@ -329,9 +334,10 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
}
}

fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx>,
map: &FnvHashMap<ty::BoundRegion, ty::Region>)
-> Vec<ty::RegionVid> {
fn var_ids<'a, 'o, 'tcx>(fields: &CombineFields<'a, 'o, 'tcx>,
map: &FnvHashMap<ty::BoundRegion, ty::Region>)
-> Vec<ty::RegionVid>
{
map.iter()
.map(|(_, r)| match *r {
ty::ReVar(r) => { r }
Expand Down Expand Up @@ -486,7 +492,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-> Result<(),(ty::BoundRegion,ty::Region)>
{
/*!
* Searches the region constriants created since `snapshot` was started
* Searches the region constraints created since `snapshot` was started
* and checks to determine whether any of the skolemized regions created
* in `skol_map` would "escape" -- meaning that they are related to
* other regions in some way. If so, the higher-ranked subtyping doesn't
Expand Down Expand Up @@ -531,7 +537,7 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
///
/// This routine is only intended to be used when the leak-check has
/// passed; currently, it's used in the trait matching code to create
/// a set of nested obligations frmo an impl that matches against
/// a set of nested obligations from an impl that matches against
/// something higher-ranked. More details can be found in
/// `librustc/middle/traits/README.md`.
///
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/infer/lattice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub trait LatticeDir<'f,'tcx> : TypeRelation<'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>) -> RelateResult<'tcx, ()>;
fn relate_bound(&mut self, v: Ty<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, ()>;
}

pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
Expand Down
17 changes: 10 additions & 7 deletions src/librustc/middle/infer/lub.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,28 @@ use super::InferCtxt;
use super::lattice::{self, LatticeDir};
use super::Subtype;

use middle::traits::PredicateObligation;
use middle::ty::{self, Ty};
use middle::ty::relate::{Relate, RelateResult, TypeRelation};

/// "Least upper bound" (common supertype)
pub struct Lub<'a, 'tcx: 'a> {
fields: CombineFields<'a, 'tcx>
pub struct Lub<'a, 'o, 'tcx: 'a + 'o> {
fields: CombineFields<'a, 'o, 'tcx>
}

impl<'a, 'tcx> Lub<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Lub<'a, 'tcx> {
impl<'a, 'o, 'tcx> Lub<'a, 'o, 'tcx> {
pub fn new(fields: CombineFields<'a, 'o, 'tcx>) -> Lub<'a, 'o, 'tcx> {
Lub { fields: fields }
}
}

impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
impl<'a, 'o, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'o, 'tcx> {
fn tag(&self) -> &'static str { "Lub" }

fn tcx(&self) -> &'a ty::ctxt<'tcx> { self.fields.tcx() }

fn obligations(&self) -> &Vec<PredicateObligation<'tcx>> { self.fields.obligations }

fn a_is_expected(&self) -> bool { self.fields.a_is_expected }

fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
Expand Down Expand Up @@ -71,12 +74,12 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
}
}

impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> {
impl<'a, 'o, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'o, '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, ()> {
fn relate_bound(&mut 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));
Expand Down
Loading