Rollup merge of #32596 - soltanmm:lazy, r=nikomatsakis

Plumb obligations through librustc/infer

Like #32542, but more like #31867.

TODO before merge: make an issue for the propagation of obligations through... uh, everywhere... then replace the `#????`s with the actual issue number.

cc @jroesch
r? @nikomatsakis
This commit is contained in:
Manish Goregaokar 2016-04-05 16:43:21 +05:30
commit f6019760f9
18 changed files with 276 additions and 108 deletions

View File

@ -37,7 +37,7 @@ use super::equate::Equate;
use super::glb::Glb;
use super::lub::Lub;
use super::sub::Sub;
use super::{InferCtxt};
use super::InferCtxt;
use super::{MiscVariable, TypeTrace};
use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf};
@ -46,6 +46,7 @@ use ty::{self, Ty, TyCtxt};
use ty::error::TypeError;
use ty::fold::{TypeFolder, TypeFoldable};
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
use syntax::ast;
use syntax::codemap::Span;
@ -56,6 +57,7 @@ pub struct CombineFields<'a, 'tcx: 'a> {
pub a_is_expected: bool,
pub trace: TypeTrace<'tcx>,
pub cause: Option<ty::relate::Cause>,
pub obligations: PredicateObligations<'tcx>,
}
pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,

View File

@ -16,6 +16,7 @@ use super::type_variable::{EqTo};
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
/// Ensures `a` is made equal to `b`. Returns `a` on success.
pub struct Equate<'a, 'tcx: 'a> {
@ -26,6 +27,10 @@ impl<'a, 'tcx> Equate<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Equate<'a, 'tcx> {
Equate { fields: fields }
}
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
}
}
impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {

View File

@ -16,6 +16,7 @@ use super::Subtype;
use ty::{self, Ty, TyCtxt};
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
/// "Greatest lower bound" (common subtype)
pub struct Glb<'a, 'tcx: 'a> {
@ -26,6 +27,10 @@ impl<'a, 'tcx> Glb<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Glb<'a, 'tcx> {
Glb { fields: fields }
}
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
}
}
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {

View File

@ -16,6 +16,7 @@ use super::Subtype;
use ty::{self, Ty, TyCtxt};
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
/// "Least upper bound" (common supertype)
pub struct Lub<'a, 'tcx: 'a> {
@ -26,6 +27,10 @@ impl<'a, 'tcx> Lub<'a, 'tcx> {
pub fn new(fields: CombineFields<'a, 'tcx>) -> Lub<'a, 'tcx> {
Lub { fields: fields }
}
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
}
}
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {

View File

@ -27,13 +27,13 @@ use middle::region::CodeExtent;
use ty::subst;
use ty::subst::Substs;
use ty::subst::Subst;
use traits::{self, ProjectionMode};
use ty::adjustment;
use ty::{TyVid, IntVid, FloatVid};
use ty::{self, Ty, TyCtxt};
use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
use ty::fold::{TypeFolder, TypeFoldable};
use ty::relate::{Relate, RelateResult, TypeRelation};
use traits::{self, PredicateObligations, ProjectionMode};
use rustc_data_structures::unify::{self, UnificationTable};
use std::cell::{RefCell, Ref};
use std::fmt;
@ -63,6 +63,12 @@ pub mod sub;
pub mod type_variable;
pub mod unify_key;
pub struct InferOk<'tcx, T> {
pub value: T,
pub obligations: PredicateObligations<'tcx>,
}
pub type InferResult<'tcx, T> = Result<InferOk<'tcx, T>, TypeError<'tcx>>;
pub type Bound<T> = Option<T>;
pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
@ -391,16 +397,15 @@ pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
origin: TypeOrigin,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("mk_subty({:?} <: {:?})", a, b);
cx.sub_types(a_is_expected, origin, a, b)
}
pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> UnitResult<'tcx> {
pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
-> UnitResult<'tcx>
{
debug!("can_mk_subty({:?} <: {:?})", a, b);
cx.probe(|_| {
let trace = TypeTrace {
@ -412,7 +417,7 @@ pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
}
pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
-> UnitResult<'tcx>
-> UnitResult<'tcx>
{
cx.can_equate(&a, &b)
}
@ -432,7 +437,7 @@ pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
origin: TypeOrigin,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("mk_eqty({:?} <: {:?})", a, b);
cx.eq_types(a_is_expected, origin, a, b)
@ -443,7 +448,7 @@ pub fn mk_eq_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
origin: TypeOrigin,
a: ty::TraitRef<'tcx>,
b: ty::TraitRef<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("mk_eq_trait_refs({:?} = {:?})", a, b);
cx.eq_trait_refs(a_is_expected, origin, a, b)
@ -454,7 +459,7 @@ pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
origin: TypeOrigin,
a: ty::PolyTraitRef<'tcx>,
b: ty::PolyTraitRef<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("mk_sub_poly_trait_refs({:?} <: {:?})", a, b);
cx.sub_poly_trait_refs(a_is_expected, origin, a, b)
@ -465,7 +470,7 @@ pub fn mk_eq_impl_headers<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
origin: TypeOrigin,
a: &ty::ImplHeader<'tcx>,
b: &ty::ImplHeader<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("mk_eq_impl_header({:?} = {:?})", a, b);
match (a.trait_ref, b.trait_ref) {
@ -574,6 +579,12 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
Ok(infcx.tcx.erase_regions(&result))
}
impl<'tcx, T> InferOk<'tcx, T> {
fn unit(self) -> InferOk<'tcx, ()> {
InferOk { value: (), obligations: self.obligations }
}
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn projection_mode(&self) -> ProjectionMode {
self.projection_mode
@ -661,39 +672,51 @@ impl<'a, 'tcx> InferCtxt<'a, '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,
cause: None}
-> CombineFields<'a, 'tcx>
{
CombineFields {
infcx: self,
a_is_expected: a_is_expected,
trace: trace,
cause: None,
obligations: PredicateObligations::new(),
}
}
pub fn equate<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> RelateResult<'tcx, T>
-> InferResult<'tcx, T>
where T: Relate<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).equate().relate(a, b)
let mut equate = self.combine_fields(a_is_expected, trace).equate();
let result = equate.relate(a, b);
result.map(|t| InferOk { value: t, obligations: equate.obligations() })
}
pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> RelateResult<'tcx, T>
-> InferResult<'tcx, T>
where T: Relate<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).sub().relate(a, b)
let mut sub = self.combine_fields(a_is_expected, trace).sub();
let result = sub.relate(a, b);
result.map(|t| InferOk { value: t, obligations: sub.obligations() })
}
pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> RelateResult<'tcx, T>
-> InferResult<'tcx, T>
where T: Relate<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).lub().relate(a, b)
let mut lub = self.combine_fields(a_is_expected, trace).lub();
let result = lub.relate(a, b);
result.map(|t| InferOk { value: t, obligations: lub.obligations() })
}
pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-> RelateResult<'tcx, T>
-> InferResult<'tcx, T>
where T: Relate<'a, 'tcx>
{
self.combine_fields(a_is_expected, trace).glb().relate(a, b)
let mut glb = self.combine_fields(a_is_expected, trace).glb();
let result = glb.relate(a, b);
result.map(|t| InferOk { value: t, obligations: glb.obligations() })
}
fn start_snapshot(&self) -> CombinedSnapshot {
@ -829,12 +852,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: TypeOrigin,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("sub_types({:?} <: {:?})", a, b);
self.commit_if_ok(|_| {
let trace = TypeTrace::types(origin, a_is_expected, a, b);
self.sub(a_is_expected, trace, &a, &b).map(|_| ())
self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
})
}
@ -843,11 +866,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: TypeOrigin,
a: Ty<'tcx>,
b: Ty<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
self.commit_if_ok(|_| {
let trace = TypeTrace::types(origin, a_is_expected, a, b);
self.equate(a_is_expected, trace, &a, &b).map(|_| ())
self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
})
}
@ -856,7 +879,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: TypeOrigin,
a: ty::TraitRef<'tcx>,
b: ty::TraitRef<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("eq_trait_refs({:?} <: {:?})",
a,
@ -866,7 +889,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: origin,
values: TraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
};
self.equate(a_is_expected, trace, &a, &b).map(|_| ())
self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
})
}
@ -875,7 +898,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: TypeOrigin,
a: ty::PolyTraitRef<'tcx>,
b: ty::PolyTraitRef<'tcx>)
-> UnitResult<'tcx>
-> InferResult<'tcx, ()>
{
debug!("sub_poly_trait_refs({:?} <: {:?})",
a,
@ -885,7 +908,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
origin: origin,
values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
};
self.sub(a_is_expected, trace, &a, &b).map(|_| ())
self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
})
}
@ -928,20 +951,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn equality_predicate(&self,
span: Span,
predicate: &ty::PolyEquatePredicate<'tcx>)
-> UnitResult<'tcx> {
-> InferResult<'tcx, ()>
{
self.commit_if_ok(|snapshot| {
let (ty::EquatePredicate(a, b), skol_map) =
self.skolemize_late_bound_regions(predicate, snapshot);
let origin = TypeOrigin::EquatePredicate(span);
let () = mk_eqty(self, false, origin, a, b)?;
self.leak_check(&skol_map, snapshot)
let eqty_ok = mk_eqty(self, false, origin, a, b)?;
self.leak_check(&skol_map, snapshot).map(|_| eqty_ok.unit())
})
}
pub fn region_outlives_predicate(&self,
span: Span,
predicate: &ty::PolyRegionOutlivesPredicate)
-> UnitResult<'tcx> {
-> UnitResult<'tcx>
{
self.commit_if_ok(|snapshot| {
let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
self.skolemize_late_bound_regions(predicate, snapshot);

View File

@ -16,6 +16,7 @@ use super::type_variable::{SubtypeOf, SupertypeOf};
use ty::{self, Ty, TyCtxt};
use ty::TyVar;
use ty::relate::{Cause, Relate, RelateResult, TypeRelation};
use traits::PredicateObligations;
use std::mem;
/// Ensures `a` is made a subtype of `b`. Returns `a` on success.
@ -27,6 +28,10 @@ impl<'a, 'tcx> Sub<'a, 'tcx> {
pub fn new(f: CombineFields<'a, 'tcx>) -> Sub<'a, 'tcx> {
Sub { fields: f }
}
pub fn obligations(self) -> PredicateObligations<'tcx> {
self.fields.obligations
}
}
impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {

View File

@ -9,7 +9,7 @@
// except according to those terms.
use dep_graph::DepGraph;
use infer::InferCtxt;
use infer::{InferCtxt, InferOk};
use ty::{self, Ty, TyCtxt, TypeFoldable, ToPolyTraitRef};
use rustc_data_structures::obligation_forest::{Backtrace, ObligationForest, Error};
use std::iter;
@ -580,7 +580,11 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
ty::Predicate::Equate(ref binder) => {
match selcx.infcx().equality_predicate(obligation.cause.span, binder) {
Ok(()) => Ok(Some(Vec::new())),
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
Ok(Some(Vec::new()))
},
Err(_) => Err(CodeSelectionError(Unimplemented)),
}
}

View File

@ -24,7 +24,7 @@ use super::VtableImplData;
use super::util;
use middle::def_id::DefId;
use infer::{self, TypeOrigin};
use infer::{self, InferOk, TypeOrigin};
use ty::subst::Subst;
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt};
use ty::fold::{TypeFoldable, TypeFolder};
@ -232,7 +232,11 @@ fn project_and_unify_type<'cx,'tcx>(
let infcx = selcx.infcx();
let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span);
match infer::mk_eqty(infcx, true, origin, normalized_ty, obligation.predicate.ty) {
Ok(()) => Ok(Some(obligations)),
Ok(InferOk { obligations: inferred_obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(inferred_obligations.is_empty());
Ok(Some(obligations))
},
Err(err) => Err(MismatchedProjectionTypes { err: err }),
}
}
@ -278,7 +282,10 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span);
let obligation_ty = obligation.predicate.ty;
match infer::mk_eqty(infcx, true, origin, obligation_ty, ret_type) {
Ok(()) => { }
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
Err(_) => { /* ignore errors */ }
}
}
@ -829,7 +836,10 @@ fn assemble_candidates_from_predicates<'cx,'tcx,I>(
infcx.sub_poly_trait_refs(false,
origin,
data_poly_trait_ref,
obligation_poly_trait_ref).is_ok()
obligation_poly_trait_ref)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
.is_ok()
});
debug!("assemble_candidates_from_predicates: candidate={:?} \
@ -1082,7 +1092,10 @@ fn confirm_param_env_candidate<'cx,'tcx>(
origin,
obligation.predicate.trait_ref.clone(),
projection.projection_ty.trait_ref.clone()) {
Ok(()) => { }
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
Err(e) => {
span_bug!(
obligation.cause.span,

View File

@ -38,7 +38,7 @@ use super::util;
use middle::def_id::DefId;
use infer;
use infer::{InferCtxt, TypeFreshener, TypeOrigin};
use infer::{InferCtxt, InferOk, TypeFreshener, TypeOrigin};
use ty::subst::{Subst, Substs, TypeSpace};
use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
use traits;
@ -484,7 +484,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ty::Predicate::Equate(ref p) => {
// does this code ever run?
match self.infcx.equality_predicate(obligation.cause.span, p) {
Ok(()) => EvaluatedToOk,
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
EvaluatedToOk
},
Err(_) => EvaluatedToErr
}
}
@ -1185,7 +1189,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
origin,
trait_bound.clone(),
ty::Binder(skol_trait_ref.clone())) {
Ok(()) => { }
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
Err(_) => { return false; }
}
@ -2487,13 +2494,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let origin = TypeOrigin::RelateOutputImplTypes(obligation_cause.span);
let obligation_trait_ref = obligation_trait_ref.clone();
match self.infcx.sub_poly_trait_refs(false,
origin,
expected_trait_ref.clone(),
obligation_trait_ref.clone()) {
Ok(()) => Ok(()),
Err(e) => Err(OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
}
self.infcx.sub_poly_trait_refs(false,
origin,
expected_trait_ref.clone(),
obligation_trait_ref.clone())
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
}
fn confirm_builtin_unsize_candidate(&mut self,
@ -2524,9 +2531,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds);
let origin = TypeOrigin::Misc(obligation.cause.span);
if self.infcx.sub_types(false, origin, new_trait, target).is_err() {
return Err(Unimplemented);
}
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, new_trait, target)
.map_err(|_| Unimplemented)?;
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
// Register one obligation for 'a: 'b.
let cause = ObligationCause::new(obligation.cause.span,
@ -2589,9 +2598,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// [T; n] -> [T].
(&ty::TyArray(a, _), &ty::TySlice(b)) => {
let origin = TypeOrigin::Misc(obligation.cause.span);
if self.infcx.sub_types(false, origin, a, b).is_err() {
return Err(Unimplemented);
}
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, a, b)
.map_err(|_| Unimplemented)?;
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
// Struct<T> -> Struct<U>.
@ -2647,9 +2658,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
let new_struct = tcx.mk_struct(def, tcx.mk_substs(new_substs));
let origin = TypeOrigin::Misc(obligation.cause.span);
if self.infcx.sub_types(false, origin, new_struct, target).is_err() {
return Err(Unimplemented);
}
let InferOk { obligations, .. } =
self.infcx.sub_types(false, origin, new_struct, target)
.map_err(|_| Unimplemented)?;
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
// Construct the nested Field<T>: Unsize<Field<U>> predicate.
nested.push(util::predicate_for_trait_def(tcx,
@ -2734,13 +2747,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
skol_obligation_trait_ref);
let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span);
if let Err(e) = self.infcx.eq_trait_refs(false,
origin,
impl_trait_ref.value.clone(),
skol_obligation_trait_ref) {
debug!("match_impl: failed eq_trait_refs due to `{}`", e);
return Err(());
}
let InferOk { obligations, .. } =
self.infcx.eq_trait_refs(false,
origin,
impl_trait_ref.value.clone(),
skol_obligation_trait_ref)
.map_err(|e| {
debug!("match_impl: failed eq_trait_refs due to `{}`", e);
()
})?;
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
debug!("match_impl: failed leak check due to `{}`", e);
@ -2803,13 +2820,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
poly_trait_ref);
let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span);
match self.infcx.sub_poly_trait_refs(false,
origin,
poly_trait_ref,
obligation.predicate.to_poly_trait_ref()) {
Ok(()) => Ok(()),
Err(_) => Err(()),
}
self.infcx.sub_poly_trait_refs(false,
origin,
poly_trait_ref,
obligation.predicate.to_poly_trait_ref())
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
.map_err(|_| ())
}
///////////////////////////////////////////////////////////////////////////

View File

@ -24,8 +24,8 @@ use rustc::ty::subst;
use rustc::ty::subst::Subst;
use rustc::traits::ProjectionMode;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::ty::relate::{TypeRelation, RelateResult};
use rustc::infer::{self, TypeOrigin};
use rustc::ty::relate::TypeRelation;
use rustc::infer::{self, InferOk, InferResult, TypeOrigin};
use rustc_metadata::cstore::CStore;
use rustc::front::map as hir_map;
use rustc::session::{self, config};
@ -355,17 +355,17 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
infer::TypeTrace::dummy(self.tcx())
}
pub fn sub(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
pub fn sub(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
let trace = self.dummy_type_trace();
self.infcx.sub(true, trace, t1, t2)
}
pub fn lub(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
pub fn lub(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
let trace = self.dummy_type_trace();
self.infcx.lub(true, trace, t1, t2)
}
pub fn glb(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
pub fn glb(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
let trace = self.dummy_type_trace();
self.infcx.glb(true, trace, t1, t2)
}
@ -374,7 +374,10 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
/// region checks).
pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
match self.sub(&t1, &t2) {
Ok(_) => {}
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) once obligations are being propagated, assert the right thing.
assert!(obligations.is_empty());
}
Err(ref e) => {
panic!("unexpected error computing sub({:?},{:?}): {}", t1, t2, e);
}
@ -395,7 +398,10 @@ impl<'a, 'tcx> Env<'a, '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(&t1, &t2) {
Ok(t) => {
Ok(InferOk { obligations, value: t }) => {
// FIXME(#32730) once obligations are being propagated, assert the right thing.
assert!(obligations.is_empty());
self.assert_eq(t, t_lub);
}
Err(ref e) => {
@ -411,7 +417,10 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
Err(e) => {
panic!("unexpected error computing LUB: {:?}", e)
}
Ok(t) => {
Ok(InferOk { obligations, value: t }) => {
// FIXME(#32730) once obligations are being propagated, assert the right thing.
assert!(obligations.is_empty());
self.assert_eq(t, t_glb);
// sanity check for good measure:

View File

@ -12,7 +12,7 @@
#![allow(unreachable_code)]
use rustc::dep_graph::DepNode;
use rustc::infer::{self, InferCtxt};
use rustc::infer::{self, InferCtxt, InferOk};
use rustc::traits::{self, ProjectionMode};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, Ty, TyCtxt};
@ -338,6 +338,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
{
infer::mk_subty(self.infcx, false, infer::TypeOrigin::Misc(span),
sup, sub)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
fn mk_eqty(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
@ -345,6 +347,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
{
infer::mk_eqty(self.infcx, false, infer::TypeOrigin::Misc(span),
a, b)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
fn tcx(&self) -> &'a TyCtxt<'tcx> {

View File

@ -9,7 +9,7 @@
// except according to those terms.
use middle::def::{self, Def};
use rustc::infer::{self, TypeOrigin};
use rustc::infer::{self, InferOk, TypeOrigin};
use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
use middle::pat_util::pat_is_resolved_const;
use rustc::ty::subst::Substs;
@ -531,7 +531,12 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
};
let result = if is_if_let_fallback {
fcx.infcx().eq_types(true, origin, arm_ty, result_ty).map(|_| arm_ty)
fcx.infcx().eq_types(true, origin, arm_ty, result_ty)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
arm_ty
})
} else if i == 0 {
// Special-case the first arm, as it has no "previous expressions".
coercion::try(fcx, &arm.body, coerce_first)

View File

@ -62,7 +62,7 @@
use check::{autoderef, FnCtxt, UnresolvedTypeAction};
use rustc::infer::{Coercion, TypeOrigin, TypeTrace};
use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace};
use rustc::traits::{self, ObligationCause};
use rustc::traits::{predicate_for_trait_def, report_selection_error};
use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
@ -118,8 +118,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
let trace = TypeTrace::types(self.origin, false, a, b);
if self.use_lub {
infcx.lub(false, trace, &a, &b)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})
} else {
infcx.sub(false, trace, &a, &b)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})
}
})
}
@ -655,12 +665,22 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>,
(&ty::TyFnDef(a_def_id, a_substs, a_fty),
&ty::TyFnDef(b_def_id, b_substs, b_fty)) => {
// The signature must always match.
let fty = fcx.infcx().lub(true, trace.clone(), a_fty, b_fty)?;
let fty = fcx.infcx().lub(true, trace.clone(), a_fty, b_fty)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})?;
if a_def_id == b_def_id {
// Same function, maybe the parameters match.
let substs = fcx.infcx().commit_if_ok(|_| {
fcx.infcx().lub(true, trace.clone(), a_substs, b_substs)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})
}).map(|s| fcx.tcx().mk_substs(s));
if let Ok(substs) = substs {
@ -724,6 +744,11 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>,
if !noop {
return fcx.infcx().commit_if_ok(|_| {
fcx.infcx().lub(true, trace.clone(), &prev_ty, &new_ty)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})
});
}
}
@ -736,6 +761,11 @@ pub fn try_find_lub<'a, 'b, 'tcx, E, I>(fcx: &FnCtxt<'a, 'tcx>,
} else {
fcx.infcx().commit_if_ok(|_| {
fcx.infcx().lub(true, trace, &prev_ty, &new_ty)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})
})
}
}

View File

@ -9,7 +9,7 @@
// except according to those terms.
use middle::free_region::FreeRegionMap;
use rustc::infer::{self, TypeOrigin};
use rustc::infer::{self, InferOk, TypeOrigin};
use rustc::ty::{self, TyCtxt};
use rustc::traits::{self, ProjectionMode};
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
@ -475,7 +475,10 @@ pub fn compare_const_impl<'tcx>(tcx: &TyCtxt<'tcx>,
});
match err {
Ok(()) => { }
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty())
}
Err(terr) => {
debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
impl_ty,

View File

@ -11,7 +11,7 @@
use check::{coercion, FnCtxt};
use rustc::ty::Ty;
use rustc::infer::TypeOrigin;
use rustc::infer::{InferOk, TypeOrigin};
use syntax::codemap::Span;
use rustc_front::hir;
@ -21,16 +21,28 @@ use rustc_front::hir;
pub fn suptype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
expected: Ty<'tcx>, actual: Ty<'tcx>) {
let origin = TypeOrigin::Misc(sp);
if let Err(e) = fcx.infcx().sub_types(false, origin, actual, expected) {
fcx.infcx().report_mismatched_types(origin, expected, actual, e);
match fcx.infcx().sub_types(false, origin, actual, expected) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
},
Err(e) => {
fcx.infcx().report_mismatched_types(origin, expected, actual, e);
}
}
}
pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
expected: Ty<'tcx>, actual: Ty<'tcx>) {
let origin = TypeOrigin::Misc(sp);
if let Err(e) = fcx.infcx().eq_types(false, origin, actual, expected) {
fcx.infcx().report_mismatched_types(origin, expected, actual, e);
match fcx.infcx().eq_types(false, origin, actual, expected) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
},
Err(e) => {
fcx.infcx().report_mismatched_types(origin, expected, actual, e);
}
}
}

View File

@ -21,8 +21,7 @@ use rustc::ty::subst;
use rustc::ty::subst::Subst;
use rustc::traits;
use rustc::ty::{self, NoPreference, Ty, TyCtxt, ToPolyTraitRef, TraitRef, TypeFoldable};
use rustc::infer;
use rustc::infer::{InferCtxt, TypeOrigin};
use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin};
use syntax::ast;
use syntax::codemap::{Span, DUMMY_SP};
use rustc_front::hir;
@ -1151,6 +1150,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::UnitResult<'tcx> {
self.infcx().sub_types(false, TypeOrigin::Misc(DUMMY_SP), sub, sup)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool {

View File

@ -88,8 +88,7 @@ use middle::astconv_util::prohibit_type_params;
use middle::cstore::LOCAL_CRATE;
use middle::def::{self, Def};
use middle::def_id::DefId;
use rustc::infer;
use rustc::infer::{TypeOrigin, TypeTrace, type_variable};
use rustc::infer::{self, InferOk, TypeOrigin, TypeTrace, type_variable};
use middle::pat_util::{self, pat_id_map};
use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
use rustc::traits::{self, report_fulfillment_errors, ProjectionMode};
@ -1627,6 +1626,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sup: Ty<'tcx>)
-> Result<(), TypeError<'tcx>> {
infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
pub fn mk_eqty(&self,
@ -1636,6 +1637,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
sup: Ty<'tcx>)
-> Result<(), TypeError<'tcx>> {
infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
pub fn mk_subr(&self,
@ -1914,7 +1917,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match infer::mk_eqty(self.infcx(), false,
TypeOrigin::Misc(default.origin_span),
ty, default.ty) {
Ok(()) => {}
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty())
},
Err(_) => {
conflicts.push((*ty, default));
}
@ -2007,7 +2013,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
match infer::mk_eqty(self.infcx(), false,
TypeOrigin::Misc(default.origin_span),
ty, default.ty) {
Ok(()) => {}
// FIXME(#32730) propagate obligations
Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()),
Err(_) => {
result = Some(default);
}
@ -2773,8 +2780,10 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
// FIXME(#15760) can't use try! here, FromError doesn't default
// to identity so the resulting type is not constrained.
if let Err(e) = ures {
return Err(e);
match ures {
// FIXME(#32730) propagate obligations
Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()),
Err(e) => return Err(e),
}
// Record all the argument types, with the substitutions
@ -2902,13 +2911,23 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
fcx.infcx().commit_if_ok(|_| {
let trace = TypeTrace::types(origin, true, then_ty, else_ty);
fcx.infcx().lub(true, trace, &then_ty, &else_ty)
.map(|InferOk { value, obligations }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
value
})
})
};
(origin, then_ty, else_ty, result)
} else {
let origin = TypeOrigin::IfExpressionWithNoElse(sp);
(origin, unit, then_ty,
fcx.infcx().eq_types(true, origin, unit, then_ty).map(|_| unit))
fcx.infcx().eq_types(true, origin, unit, then_ty)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
unit
}))
};
let if_ty = match result {

View File

@ -92,7 +92,7 @@ use middle::region::{self, CodeExtent};
use rustc::ty::subst::Substs;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt, MethodCall, TypeFoldable};
use rustc::infer::{self, GenericKind, InferCtxt, SubregionOrigin, TypeOrigin, VerifyBound};
use rustc::infer::{self, GenericKind, InferCtxt, InferOk, SubregionOrigin, TypeOrigin, VerifyBound};
use middle::pat_util;
use rustc::ty::adjustment;
use rustc::ty::wf::ImpliedBound;
@ -1841,7 +1841,11 @@ fn declared_projection_bounds_from_trait<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
// check whether this predicate applies to our current projection
match infer::mk_eqty(infcx, false, TypeOrigin::Misc(span), ty, outlives.0) {
Ok(()) => { Ok(outlives.1) }
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
Ok(outlives.1)
}
Err(_) => { Err(()) }
}
});