diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 641273d2b7626..5d33d6e6d2e71 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -274,7 +274,7 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> { { let mut generalize = Generalizer { infcx: self.infcx, - span: self.trace.origin.span(), + span: self.trace.cause.span, for_vid: for_vid, make_region_vars: make_region_vars, cycle_detected: false diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs index d8a7ce72f50d2..58caac4034e34 100644 --- a/src/librustc/infer/error_reporting.rs +++ b/src/librustc/infer/error_reporting.rs @@ -80,8 +80,9 @@ use hir::print as pprust; use lint; use hir::def::Def; use hir::def_id::DefId; -use infer::{self, TypeOrigin}; +use infer; use middle::region; +use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, TyCtxt, TypeFoldable}; use ty::{Region, ReFree}; use ty::error::TypeError; @@ -524,10 +525,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, - origin: &TypeOrigin) + cause: &ObligationCause<'tcx>) { - match origin { - &TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source { + match cause.code { + ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { hir::MatchSource::IfLetDesugar {..} => { err.span_note(arm_span, "`if let` arm with an incompatible type"); } @@ -541,7 +542,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn note_type_err(&self, diag: &mut DiagnosticBuilder<'tcx>, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, secondary_span: Option<(Span, String)>, values: Option>, terr: &TypeError<'tcx>) @@ -558,7 +559,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } }; - let span = origin.span(); + let span = cause.span; if let Some((expected, found)) = expected_found { let is_simple_error = if let &TypeError::Sorts(ref values) = terr { @@ -588,7 +589,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { diag.span_label(sp, &msg); } - self.note_error_origin(diag, &origin); + self.note_error_origin(diag, &cause); self.check_and_note_conflicting_crates(diag, terr, span); self.tcx.note_and_explain_type_err(diag, terr, span); } @@ -598,17 +599,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { terr: &TypeError<'tcx>) -> DiagnosticBuilder<'tcx> { - let span = trace.origin.span(); - let failure_str = trace.origin.as_failure_str(); - let mut diag = match trace.origin { - TypeOrigin::IfExpressionWithNoElse(_) => { + let span = trace.cause.span; + let failure_str = trace.cause.as_failure_str(); + let mut diag = match trace.cause.code { + ObligationCauseCode::IfExpressionWithNoElse => { struct_span_err!(self.tcx.sess, span, E0317, "{}", failure_str) }, _ => { struct_span_err!(self.tcx.sess, span, E0308, "{}", failure_str) }, }; - self.note_type_err(&mut diag, trace.origin, None, Some(trace.values), terr); + self.note_type_err(&mut diag, &trace.cause, None, Some(trace.values), terr); diag } @@ -1695,18 +1696,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some((expected, found)) = self.values_str(&trace.values) { // FIXME: do we want a "the" here? err.span_note( - trace.origin.span(), + trace.cause.span, &format!("...so that {} (expected {}, found {})", - trace.origin.as_requirement_str(), expected, found)); + trace.cause.as_requirement_str(), expected, found)); } else { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. err.span_note( - trace.origin.span(), + trace.cause.span, &format!("...so that {}", - trace.origin.as_requirement_str())); + trace.cause.as_requirement_str())); } } infer::Reborrow(span) => { @@ -1961,3 +1962,45 @@ fn name_to_dummy_lifetime(name: ast::Name) -> hir::Lifetime { span: syntax_pos::DUMMY_SP, name: name } } + +impl<'tcx> ObligationCause<'tcx> { + fn as_failure_str(&self) -> &'static str { + use traits::ObligationCauseCode::*; + match self.code { + CompareImplMethodObligation { .. } => "method not compatible with trait", + MatchExpressionArm { source, .. } => match source { + hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types", + _ => "match arms have incompatible types", + }, + IfExpression => "if and else have incompatible types", + IfExpressionWithNoElse => "if may be missing an else clause", + EquatePredicate => "equality predicate not satisfied", + MainFunctionType => "main function has wrong type", + StartFunctionType => "start function has wrong type", + IntrinsicType => "intrinsic has wrong type", + MethodReceiver => "mismatched method receiver", + _ => "mismatched types", + } + } + + fn as_requirement_str(&self) -> &'static str { + use traits::ObligationCauseCode::*; + match self.code { + CompareImplMethodObligation { .. } => "method type is compatible with trait", + ExprAssignable => "expression is assignable", + MatchExpressionArm { source, .. } => match source { + hir::MatchSource::IfLetDesugar{..} => "`if let` arms have compatible types", + _ => "match arms have compatible types", + }, + IfExpression => "if and else have compatible types", + IfExpressionWithNoElse => "if missing an else returns ()", + EquatePredicate => "equality where clause is satisfied", + MainFunctionType => "`main` function has the correct type", + StartFunctionType => "`start` function has the correct type", + IntrinsicType => "intrinsic has the correct type", + MethodReceiver => "method receiver has the correct type", + _ => "types are compatible", + } + } +} + diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs index 737ce8bdf681d..08e522f5fd6ee 100644 --- a/src/librustc/infer/higher_ranked/mod.rs +++ b/src/librustc/infer/higher_ranked/mod.rs @@ -58,7 +58,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, '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| { - let span = self.trace.origin.span(); + let span = self.trace.cause.span; // First, we instantiate each bound region in the subtype with a fresh // region variable. @@ -230,7 +230,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // created as part of this type comparison". 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.cause.span; let (a_with_fresh, a_map) = self.infcx.replace_late_bound_regions_with_fresh_var( span, HigherRankedType, a); @@ -247,7 +247,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, '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 span = self.trace.cause.span; let result1 = fold_regions_in( self.tcx(), @@ -325,10 +325,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> { // 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.trace.cause.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.trace.cause.span, HigherRankedType, b); let a_vars = var_ids(self, &a_map); let b_vars = var_ids(self, &b_map); @@ -341,7 +341,7 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, '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 span = self.trace.cause.span; let result1 = fold_regions_in( self.tcx(), @@ -463,7 +463,7 @@ fn var_ids<'a, 'gcx, 'tcx>(fields: &CombineFields<'a, 'gcx, 'tcx>, ty::ReVar(r) => { r } _ => { span_bug!( - fields.trace.origin.span(), + fields.trace.cause.span, "found non-region-vid: {:?}", r); } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 2d4b36ec18760..6ae104d79122b 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -32,7 +32,7 @@ use ty::{self, Ty, TyCtxt}; use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use ty::relate::{Relate, RelateResult, TypeRelation}; -use traits::{self, PredicateObligations, Reveal}; +use traits::{self, ObligationCause, PredicateObligations, Reveal}; use rustc_data_structures::unify::{self, UnificationTable}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::fmt; @@ -173,89 +173,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { /// region that each late-bound region was replaced with. pub type SkolemizationMap<'tcx> = FxHashMap; -/// Why did we require that the two types be related? -/// -/// See `error_reporting.rs` for more details -#[derive(Clone, Copy, Debug)] -pub enum TypeOrigin { - // Not yet categorized in a better way - Misc(Span), - - // Checking that method of impl is compatible with trait - MethodCompatCheck(Span), - - // Checking that this expression can be assigned where it needs to be - ExprAssignable(Span), - - // Relating trait type parameters to those found in impl etc - RelateOutputImplTypes(Span), - - // Computing common supertype in the arms of a match expression - MatchExpressionArm(Span, Span, hir::MatchSource), - - // Computing common supertype in an if expression - IfExpression(Span), - - // Computing common supertype of an if expression with no else counter-part - IfExpressionWithNoElse(Span), - - // `where a == b` - EquatePredicate(Span), - - // `main` has wrong type - MainFunctionType(Span), - - // `start` has wrong type - StartFunctionType(Span), - - // intrinsic has wrong type - IntrinsicType(Span), - - // method receiver - MethodReceiver(Span), -} - -impl TypeOrigin { - fn as_failure_str(&self) -> &'static str { - match self { - &TypeOrigin::Misc(_) | - &TypeOrigin::RelateOutputImplTypes(_) | - &TypeOrigin::ExprAssignable(_) => "mismatched types", - &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait", - &TypeOrigin::MatchExpressionArm(.., source) => match source { - hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types", - _ => "match arms have incompatible types", - }, - &TypeOrigin::IfExpression(_) => "if and else have incompatible types", - &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause", - &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied", - &TypeOrigin::MainFunctionType(_) => "main function has wrong type", - &TypeOrigin::StartFunctionType(_) => "start function has wrong type", - &TypeOrigin::IntrinsicType(_) => "intrinsic has wrong type", - &TypeOrigin::MethodReceiver(_) => "mismatched method receiver", - } - } - - fn as_requirement_str(&self) -> &'static str { - match self { - &TypeOrigin::Misc(_) => "types are compatible", - &TypeOrigin::MethodCompatCheck(_) => "method type is compatible with trait", - &TypeOrigin::ExprAssignable(_) => "expression is assignable", - &TypeOrigin::RelateOutputImplTypes(_) => { - "trait type parameters matches those specified on the impl" - } - &TypeOrigin::MatchExpressionArm(..) => "match arms have compatible types", - &TypeOrigin::IfExpression(_) => "if and else have compatible types", - &TypeOrigin::IfExpressionWithNoElse(_) => "if missing an else returns ()", - &TypeOrigin::EquatePredicate(_) => "equality where clause is satisfied", - &TypeOrigin::MainFunctionType(_) => "`main` function has the correct type", - &TypeOrigin::StartFunctionType(_) => "`start` function has the correct type", - &TypeOrigin::IntrinsicType(_) => "intrinsic has the correct type", - &TypeOrigin::MethodReceiver(_) => "method receiver has the correct type", - } - } -} - /// See `error_reporting.rs` for more details #[derive(Clone, Debug)] pub enum ValuePairs<'tcx> { @@ -270,7 +187,7 @@ pub enum ValuePairs<'tcx> { /// See `error_reporting.rs` for more details. #[derive(Clone)] pub struct TypeTrace<'tcx> { - origin: TypeOrigin, + cause: ObligationCause<'tcx>, values: ValuePairs<'tcx>, } @@ -1006,14 +923,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn sub_types(&self, a_is_expected: bool, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, ()> { debug!("sub_types({:?} <: {:?})", a, b); self.commit_if_ok(|_| { - let trace = TypeTrace::types(origin, a_is_expected, a, b); + let trace = TypeTrace::types(cause, a_is_expected, a, b); self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) }) } @@ -1024,7 +941,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { -> UnitResult<'tcx> { self.probe(|_| { - let origin = TypeOrigin::Misc(syntax_pos::DUMMY_SP); + let origin = &ObligationCause::dummy(); let trace = TypeTrace::types(origin, true, a, b); self.sub(true, trace, &a, &b).map(|InferOk { obligations, .. }| { // FIXME(#32730) propagate obligations @@ -1035,20 +952,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn eq_types(&self, a_is_expected: bool, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, a: Ty<'tcx>, b: Ty<'tcx>) -> InferResult<'tcx, ()> { self.commit_if_ok(|_| { - let trace = TypeTrace::types(origin, a_is_expected, a, b); + let trace = TypeTrace::types(cause, a_is_expected, a, b); self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) }) } pub fn eq_trait_refs(&self, a_is_expected: bool, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, a: ty::TraitRef<'tcx>, b: ty::TraitRef<'tcx>) -> InferResult<'tcx, ()> @@ -1056,7 +973,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("eq_trait_refs({:?} = {:?})", a, b); self.commit_if_ok(|_| { let trace = TypeTrace { - origin: origin, + cause: cause.clone(), values: TraitRefs(ExpectedFound::new(a_is_expected, a, b)) }; self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) @@ -1065,22 +982,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn eq_impl_headers(&self, a_is_expected: bool, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, a: &ty::ImplHeader<'tcx>, b: &ty::ImplHeader<'tcx>) -> InferResult<'tcx, ()> { debug!("eq_impl_header({:?} = {:?})", a, b); match (a.trait_ref, b.trait_ref) { - (Some(a_ref), Some(b_ref)) => self.eq_trait_refs(a_is_expected, origin, a_ref, b_ref), - (None, None) => self.eq_types(a_is_expected, origin, a.self_ty, b.self_ty), + (Some(a_ref), Some(b_ref)) => self.eq_trait_refs(a_is_expected, cause, a_ref, b_ref), + (None, None) => self.eq_types(a_is_expected, cause, a.self_ty, b.self_ty), _ => bug!("mk_eq_impl_headers given mismatched impl kinds"), } } pub fn sub_poly_trait_refs(&self, a_is_expected: bool, - origin: TypeOrigin, + cause: ObligationCause<'tcx>, a: ty::PolyTraitRef<'tcx>, b: ty::PolyTraitRef<'tcx>) -> InferResult<'tcx, ()> @@ -1088,7 +1005,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { debug!("sub_poly_trait_refs({:?} <: {:?})", a, b); self.commit_if_ok(|_| { let trace = TypeTrace { - origin: origin, + cause: cause, values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b)) }; self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit()) @@ -1104,16 +1021,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn equality_predicate(&self, - span: Span, + cause: &ObligationCause<'tcx>, predicate: &ty::PolyEquatePredicate<'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 eqty_ok = self.eq_types(false, origin, a, b)?; - self.leak_check(false, span, &skol_map, snapshot)?; + let cause_span = cause.span; + let eqty_ok = self.eq_types(false, cause, a, b)?; + self.leak_check(false, cause_span, &skol_map, snapshot)?; self.pop_skolemized(skol_map, snapshot); Ok(eqty_ok.unit()) }) @@ -1443,26 +1360,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub fn report_mismatched_types(&self, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>, err: TypeError<'tcx>) { - let trace = TypeTrace { - origin: origin, - values: Types(ExpectedFound { - expected: expected, - found: actual - }) - }; + let trace = TypeTrace::types(cause, true, expected, actual); self.report_and_explain_type_error(trace, &err).emit(); } pub fn report_conflicting_default_types(&self, span: Span, + body_id: ast::NodeId, expected: type_variable::Default<'tcx>, actual: type_variable::Default<'tcx>) { let trace = TypeTrace { - origin: TypeOrigin::Misc(span), + cause: ObligationCause::misc(span, body_id), values: Types(ExpectedFound { expected: expected.ty, found: actual.ty @@ -1507,15 +1419,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// See `higher_ranked_match` in `higher_ranked/mod.rs` for more /// details. pub fn match_poly_projection_predicate(&self, - origin: TypeOrigin, + cause: ObligationCause<'tcx>, match_a: ty::PolyProjectionPredicate<'tcx>, match_b: ty::TraitRef<'tcx>) -> InferResult<'tcx, HrMatchResult>> { - let span = origin.span(); + let span = cause.span; let match_trait_ref = match_a.skip_binder().projection_ty.trait_ref; let trace = TypeTrace { - origin: origin, + cause: cause, values: TraitRefs(ExpectedFound::new(true, match_trait_ref, match_b)) }; @@ -1664,23 +1576,23 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { pub fn span(&self) -> Span { - self.origin.span() + self.cause.span } - pub fn types(origin: TypeOrigin, + pub fn types(cause: &ObligationCause<'tcx>, a_is_expected: bool, a: Ty<'tcx>, b: Ty<'tcx>) -> TypeTrace<'tcx> { TypeTrace { - origin: origin, + cause: cause.clone(), values: Types(ExpectedFound::new(a_is_expected, a, b)) } } pub fn dummy(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> TypeTrace<'tcx> { TypeTrace { - origin: TypeOrigin::Misc(syntax_pos::DUMMY_SP), + cause: ObligationCause::dummy(), values: Types(ExpectedFound { expected: tcx.types.err, found: tcx.types.err, @@ -1691,26 +1603,7 @@ impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> { impl<'tcx> fmt::Debug for TypeTrace<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "TypeTrace({:?})", self.origin) - } -} - -impl TypeOrigin { - pub fn span(&self) -> Span { - match *self { - TypeOrigin::MethodCompatCheck(span) => span, - TypeOrigin::ExprAssignable(span) => span, - TypeOrigin::Misc(span) => span, - TypeOrigin::RelateOutputImplTypes(span) => span, - TypeOrigin::MatchExpressionArm(match_span, ..) => match_span, - TypeOrigin::IfExpression(span) => span, - TypeOrigin::IfExpressionWithNoElse(span) => span, - TypeOrigin::EquatePredicate(span) => span, - TypeOrigin::MainFunctionType(span) => span, - TypeOrigin::StartFunctionType(span) => span, - TypeOrigin::IntrinsicType(span) => span, - TypeOrigin::MethodReceiver(span) => span, - } + write!(f, "TypeTrace({:?})", self.cause) } } @@ -1787,16 +1680,6 @@ impl RegionVariableOrigin { } } -impl<'tcx> TypeFoldable<'tcx> for TypeOrigin { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { - self.clone() - } - - fn super_visit_with>(&self, _visitor: &mut V) -> bool { - false - } -} - impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { @@ -1824,12 +1707,12 @@ impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> { impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { TypeTrace { - origin: self.origin.fold_with(folder), + cause: self.cause.fold_with(folder), values: self.values.fold_with(folder) } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.origin.visit_with(visitor) || self.values.visit_with(visitor) + self.cause.visit_with(visitor) || self.values.visit_with(visitor) } } diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs index 159de2faced57..dae30ea97c80d 100644 --- a/src/librustc/infer/sub.rs +++ b/src/librustc/infer/sub.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::combine::CombineFields; use super::SubregionOrigin; +use super::combine::CombineFields; use super::type_variable::{SubtypeOf, SupertypeOf}; use ty::{self, Ty, TyCtxt}; @@ -111,11 +111,13 @@ impl<'combine, 'infcx, 'gcx, 'tcx> TypeRelation<'infcx, 'gcx, 'tcx> -> RelateResult<'tcx, &'tcx ty::Region> { debug!("{}.regions({:?}, {:?}) self.cause={:?}", self.tag(), a, b, self.fields.cause); + // FIXME -- we have more fine-grained information available // from the "cause" field, we could perhaps give more tailored // error messages. let origin = SubregionOrigin::Subtype(self.fields.trace.clone()); self.fields.infcx.region_vars.make_subregion(origin, a, b); + Ok(a) } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 1ccd048cedcaa..2e06e83f8489c 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -14,8 +14,8 @@ use super::{SelectionContext, Obligation, ObligationCause}; use hir::def_id::{DefId, LOCAL_CRATE}; use ty::{self, Ty, TyCtxt}; -use infer::{InferCtxt, InferOk, TypeOrigin}; -use syntax_pos::DUMMY_SP; + +use infer::{InferCtxt, InferOk}; #[derive(Copy, Clone)] struct InferIsLocal(bool); @@ -55,8 +55,10 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>, debug!("overlap: b_impl_header={:?}", b_impl_header); // Do `a` and `b` unify? If not, no overlap. - match selcx.infcx().eq_impl_headers(true, TypeOrigin::Misc(DUMMY_SP), &a_impl_header, - &b_impl_header) { + match selcx.infcx().eq_impl_headers(true, + &ObligationCause::dummy(), + &a_impl_header, + &b_impl_header) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()); diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 7e70fdb92e68b..e0a397ad28fbd 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -26,7 +26,7 @@ use super::{ use fmt_macros::{Parser, Piece, Position}; use hir::def_id::DefId; -use infer::{self, InferCtxt, TypeOrigin}; +use infer::{self, InferCtxt}; use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::ExpectedFound; @@ -100,7 +100,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } self.probe(|_| { - let origin = TypeOrigin::Misc(obligation.cause.span); let err_buf; let mut err = &error.err; let mut values = None; @@ -121,9 +120,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { obligation.cause.clone(), 0 ); - let origin = TypeOrigin::Misc(obligation.cause.span); if let Err(error) = self.eq_types( - false, origin, + false, &obligation.cause, data.ty, normalized.value ) { values = Some(infer::ValuePairs::Types(ExpectedFound { @@ -136,10 +134,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } let mut diag = struct_span_err!( - self.tcx.sess, origin.span(), E0271, + self.tcx.sess, obligation.cause.span, E0271, "type mismatch resolving `{}`", predicate ); - self.note_type_err(&mut diag, origin, None, values, err); + self.note_type_err(&mut diag, &obligation.cause, None, values, err); self.note_obligation_cause(&mut diag, obligation); diag.emit(); }); @@ -529,7 +527,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::Predicate::Equate(ref predicate) => { let predicate = self.resolve_type_vars_if_possible(predicate); - let err = self.equality_predicate(span, + let err = self.equality_predicate(&obligation.cause, &predicate).err().unwrap(); struct_span_err!(self.tcx.sess, span, E0278, "the requirement `{}` is not satisfied (`{}`)", @@ -851,7 +849,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { { let tcx = self.tcx; match *cause_code { - ObligationCauseCode::MiscObligation => { } + ObligationCauseCode::ExprAssignable | + ObligationCauseCode::MatchExpressionArm { .. } | + ObligationCauseCode::IfExpression | + ObligationCauseCode::IfExpressionWithNoElse | + ObligationCauseCode::EquatePredicate | + ObligationCauseCode::MainFunctionType | + ObligationCauseCode::StartFunctionType | + ObligationCauseCode::IntrinsicType | + ObligationCauseCode::MethodReceiver | + ObligationCauseCode::MiscObligation => { + } ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index b4592a03bcd1f..f406580286da9 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -519,11 +519,9 @@ fn process_predicate<'a, 'gcx, 'tcx>( } ty::Predicate::Equate(ref binder) => { - match selcx.infcx().equality_predicate(obligation.cause.span, binder) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - Ok(Some(Vec::new())) + match selcx.infcx().equality_predicate(&obligation.cause, binder) { + Ok(InferOk { obligations, value: () }) => { + Ok(Some(obligations)) }, Err(_) => Err(CodeSelectionError(Unimplemented)), } diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index eba24bfd2c9e2..a5fdaed971257 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -15,6 +15,7 @@ pub use self::FulfillmentErrorCode::*; pub use self::Vtable::*; pub use self::ObligationCauseCode::*; +use hir; use hir::def_id::DefId; use middle::free_region::FreeRegionMap; use ty::subst::Substs; @@ -148,6 +149,35 @@ pub enum ObligationCauseCode<'tcx> { trait_item_def_id: DefId, lint_id: Option, }, + + // Checking that this expression can be assigned where it needs to be + // FIXME(eddyb) #11161 is the original Expr required? + ExprAssignable, + + // Computing common supertype in the arms of a match expression + MatchExpressionArm { arm_span: Span, + source: hir::MatchSource }, + + // Computing common supertype in an if expression + IfExpression, + + // Computing common supertype of an if expression with no else counter-part + IfExpressionWithNoElse, + + // `where a == b` + EquatePredicate, + + // `main` has wrong type + MainFunctionType, + + // `start` has wrong type + StartFunctionType, + + // intrinsic has wrong type + IntrinsicType, + + // method receiver + MethodReceiver, } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index f1b69feb545ef..986e4192f889e 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -24,7 +24,7 @@ use super::VtableImplData; use super::util; use hir::def_id::DefId; -use infer::{InferOk, TypeOrigin}; +use infer::InferOk; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use syntax::parse::token; use syntax::ast; @@ -209,11 +209,8 @@ fn project_and_unify_type<'cx, 'gcx, 'tcx>( obligations); let infcx = selcx.infcx(); - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); - match infcx.eq_types(true, origin, normalized_ty, obligation.predicate.ty) { - Ok(InferOk { obligations: inferred_obligations, .. }) => { - // FIXME(#32730) once obligations are generated in inference, drop this assertion - assert!(inferred_obligations.is_empty()); + match infcx.eq_types(true, &obligation.cause, normalized_ty, obligation.predicate.ty) { + Ok(InferOk { obligations: inferred_obligations, value: () }) => { obligations.extend(inferred_obligations); Ok(Some(obligations)) }, @@ -840,18 +837,18 @@ fn assemble_candidates_from_predicates<'cx, 'gcx, 'tcx, I>( let same_name = data.item_name() == obligation.predicate.item_name; let is_match = same_name && infcx.probe(|_| { - let origin = TypeOrigin::Misc(obligation.cause.span); let data_poly_trait_ref = data.to_poly_trait_ref(); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); infcx.sub_poly_trait_refs(false, - origin, + obligation.cause.clone(), data_poly_trait_ref, obligation_poly_trait_ref) - // FIXME(#32730) once obligations are propagated from unification in - // inference, drop this assertion - .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) + .map(|InferOk { obligations: _, value: () }| { + // FIXME(#32730) -- do we need to take obligations + // into account in any way? At the moment, no. + }) .is_ok() }); @@ -1153,12 +1150,11 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( // select those with a relevant trait-ref let mut env_predicates = env_predicates.filter(|data| { - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); let data_poly_trait_ref = data.to_poly_trait_ref(); let obligation_poly_trait_ref = obligation_trait_ref.to_poly_trait_ref(); selcx.infcx().probe(|_| { selcx.infcx().sub_poly_trait_refs(false, - origin, + obligation.cause.clone(), data_poly_trait_ref, obligation_poly_trait_ref).is_ok() }) @@ -1187,12 +1183,10 @@ fn confirm_fn_pointer_candidate<'cx, 'gcx, 'tcx>( fn_pointer_vtable: VtableFnPointerData<'tcx, PredicateObligation<'tcx>>) -> Progress<'tcx> { - // FIXME(#32730) drop this assertion once obligations are propagated from inference (fn pointer - // vtable nested obligations ONLY come from unification in inference) - assert!(fn_pointer_vtable.nested.is_empty()); let fn_type = selcx.infcx().shallow_resolve(fn_pointer_vtable.fn_ty); let sig = fn_type.fn_sig(); confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes) + .with_addl_obligations(fn_pointer_vtable.nested) } fn confirm_closure_candidate<'cx, 'gcx, 'tcx>( @@ -1265,12 +1259,10 @@ fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>( -> Progress<'tcx> { let infcx = selcx.infcx(); - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); + let cause = obligation.cause.clone(); let trait_ref = obligation.predicate.trait_ref; - match infcx.match_poly_projection_predicate(origin, poly_projection, trait_ref) { + match infcx.match_poly_projection_predicate(cause, poly_projection, trait_ref) { Ok(InferOk { value: ty_match, obligations }) => { - // FIXME(#32730) once obligations are generated in inference, drop this assertion - assert!(obligations.is_empty()); Progress { ty: ty_match.value, obligations: obligations, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 6f6534cb2064a..c25e7ee344f6e 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -35,7 +35,7 @@ use super::util; use hir::def_id::DefId; use infer; -use infer::{InferCtxt, InferOk, TypeFreshener, TypeOrigin}; +use infer::{InferCtxt, InferOk, TypeFreshener}; use ty::subst::{Kind, Subst, Substs}; use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use traits; @@ -418,9 +418,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { None => Ok(None), Some(candidate) => { let mut candidate = self.confirm_candidate(obligation, candidate)?; - // FIXME(#32730) remove this assertion once inferred obligations are propagated - // from inference - assert!(self.inferred_obligations.len() == 0); let inferred_obligations = (*self.inferred_obligations).into_iter().cloned(); candidate.nested_obligations_mut().extend(inferred_obligations); Ok(Some(candidate)) @@ -521,7 +518,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::Predicate::Equate(ref p) => { // does this code ever run? - match self.infcx.equality_predicate(obligation.cause.span, p) { + match self.infcx.equality_predicate(&obligation.cause, p) { Ok(InferOk { obligations, .. }) => { self.inferred_obligations.extend(obligations); EvaluatedToOk @@ -1247,9 +1244,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { -> bool { assert!(!skol_trait_ref.has_escaping_regions()); - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); + let cause = obligation.cause.clone(); match self.infcx.sub_poly_trait_refs(false, - origin, + cause, trait_bound.clone(), ty::Binder(skol_trait_ref.clone())) { Ok(InferOk { obligations, .. }) => { @@ -2439,16 +2436,14 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { /// selection of the impl. Therefore, if there is a mismatch, we /// report an error to the user. fn confirm_poly_trait_refs(&mut self, - obligation_cause: ObligationCause, + obligation_cause: ObligationCause<'tcx>, obligation_trait_ref: ty::PolyTraitRef<'tcx>, expected_trait_ref: ty::PolyTraitRef<'tcx>) -> Result<(), SelectionError<'tcx>> { - let origin = TypeOrigin::RelateOutputImplTypes(obligation_cause.span); - let obligation_trait_ref = obligation_trait_ref.clone(); self.infcx.sub_poly_trait_refs(false, - origin, + obligation_cause.clone(), expected_trait_ref.clone(), obligation_trait_ref.clone()) .map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations)) @@ -2482,9 +2477,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { builtin_bounds: data_b.builtin_bounds, projection_bounds: data_a.projection_bounds.clone(), }); - let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = - self.infcx.sub_types(false, origin, new_trait, target) + self.infcx.sub_types(false, &obligation.cause, new_trait, target) .map_err(|_| Unimplemented)?; self.inferred_obligations.extend(obligations); @@ -2553,9 +2547,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // [T; n] -> [T]. (&ty::TyArray(a, _), &ty::TySlice(b)) => { - let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = - self.infcx.sub_types(false, origin, a, b) + self.infcx.sub_types(false, &obligation.cause, a, b) .map_err(|_| Unimplemented)?; self.inferred_obligations.extend(obligations); } @@ -2617,9 +2610,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } }); let new_struct = tcx.mk_adt(def, tcx.mk_substs(params)); - let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = - self.infcx.sub_types(false, origin, new_struct, target) + self.infcx.sub_types(false, &obligation.cause, new_struct, target) .map_err(|_| Unimplemented)?; self.inferred_obligations.extend(obligations); @@ -2705,10 +2697,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { impl_trait_ref, skol_obligation_trait_ref); - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); let InferOk { obligations, .. } = self.infcx.eq_trait_refs(false, - origin, + &obligation.cause, impl_trait_ref.value.clone(), skol_obligation_trait_ref) .map_err(|e| { @@ -2780,9 +2771,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { obligation, poly_trait_ref); - let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span); self.infcx.sub_poly_trait_refs(false, - origin, + obligation.cause.clone(), poly_trait_ref, obligation.predicate.to_poly_trait_ref()) .map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations)) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 91c40a5cc8516..870494363c85a 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -22,7 +22,7 @@ use super::util::impl_trait_ref_and_oblig; use rustc_data_structures::fx::FxHashMap; use hir::def_id::DefId; -use infer::{InferCtxt, InferOk, TypeOrigin}; +use infer::{InferCtxt, InferOk}; use middle::region; use ty::subst::{Subst, Substs}; use traits::{self, Reveal, ObligationCause}; @@ -223,8 +223,10 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, target_substs); // do the impls unify? If not, no specialization. - match infcx.eq_trait_refs(true, TypeOrigin::Misc(DUMMY_SP), source_trait_ref, - target_trait_ref) { + match infcx.eq_trait_refs(true, + &ObligationCause::dummy(), + source_trait_ref, + target_trait_ref) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()) diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index d33e8b5675f55..d03ba5b0a31f1 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -213,6 +213,34 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { lint_id: lint_id, }) } + super::ExprAssignable => { + Some(super::ExprAssignable) + } + super::MatchExpressionArm { arm_span, source } => { + Some(super::MatchExpressionArm { arm_span: arm_span, + source: source }) + } + super::IfExpression => { + Some(super::IfExpression) + } + super::IfExpressionWithNoElse => { + Some(super::IfExpressionWithNoElse) + } + super::EquatePredicate => { + Some(super::EquatePredicate) + } + super::MainFunctionType => { + Some(super::MainFunctionType) + } + super::StartFunctionType => { + Some(super::StartFunctionType) + } + super::IntrinsicType => { + Some(super::IntrinsicType) + } + super::MethodReceiver => { + Some(super::MethodReceiver) + } } } } @@ -461,6 +489,15 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> { impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { + super::ExprAssignable | + super::MatchExpressionArm { arm_span: _, source: _ } | + super::IfExpression | + super::IfExpressionWithNoElse | + super::EquatePredicate | + super::MainFunctionType | + super::StartFunctionType | + super::IntrinsicType | + super::MethodReceiver | super::MiscObligation | super::SliceOrArrayElem | super::TupleElem | @@ -497,6 +534,15 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { fn super_visit_with>(&self, visitor: &mut V) -> bool { match *self { + super::ExprAssignable | + super::MatchExpressionArm { arm_span: _, source: _ } | + super::IfExpression | + super::IfExpressionWithNoElse | + super::EquatePredicate | + super::MainFunctionType | + super::StartFunctionType | + super::IntrinsicType | + super::MethodReceiver | super::MiscObligation | super::SliceOrArrayElem | super::TupleElem | diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 8dc21550148c0..782c74c8c78c7 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -21,9 +21,9 @@ use rustc::middle::region::CodeExtentData; use rustc::middle::resolve_lifetime; use rustc::middle::stability; use rustc::ty::subst::{Kind, Subst}; -use rustc::traits::Reveal; +use rustc::traits::{ObligationCause, Reveal}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::infer::{self, InferOk, InferResult, TypeOrigin}; +use rustc::infer::{self, InferOk, InferResult}; use rustc_metadata::cstore::CStore; use rustc::hir::map as hir_map; use rustc::session::{self, config}; @@ -36,7 +36,6 @@ use errors::emitter::Emitter; use errors::{Level, DiagnosticBuilder}; use syntax::parse::token; use syntax::feature_gate::UnstableFeatures; -use syntax_pos::DUMMY_SP; use rustc::hir; @@ -245,7 +244,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn make_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - match self.infcx.sub_types(true, TypeOrigin::Misc(DUMMY_SP), a, b) { + match self.infcx.sub_types(true, &ObligationCause::dummy(), a, b) { Ok(_) => true, Err(ref e) => panic!("Encountered error: {}", e), } diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 79bb14b7336c1..0ceed274b6da6 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -306,32 +306,43 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, fulfillment_cx: traits::FulfillmentContext<'tcx>, - last_span: Span + last_span: Span, + body_id: ast::NodeId, } impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { - fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self { + fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, body_id: ast::NodeId) -> Self { TypeChecker { infcx: infcx, fulfillment_cx: traits::FulfillmentContext::new(), - last_span: DUMMY_SP + last_span: DUMMY_SP, + body_id: body_id, + } + } + + fn misc(&self, span: Span) -> traits::ObligationCause<'tcx> { + traits::ObligationCause::misc(span, self.body_id) + } + + pub fn register_infer_ok_obligations(&mut self, infer_ok: InferOk<'tcx, T>) -> T { + for obligation in infer_ok.obligations { + self.fulfillment_cx.register_predicate_obligation(self.infcx, obligation); } + infer_ok.value } - fn sub_types(&self, span: Span, sup: Ty<'tcx>, sub: Ty<'tcx>) + fn sub_types(&mut self, sup: Ty<'tcx>, sub: Ty<'tcx>) -> infer::UnitResult<'tcx> { - self.infcx.sub_types(false, infer::TypeOrigin::Misc(span), sup, sub) - // FIXME(#32730) propagate obligations - .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) + self.infcx.sub_types(false, &self.misc(self.last_span), sup, sub) + .map(|ok| self.register_infer_ok_obligations(ok)) } - fn eq_types(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>) + fn eq_types(&mut self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>) -> infer::UnitResult<'tcx> { - self.infcx.eq_types(false, infer::TypeOrigin::Misc(span), a, b) - // FIXME(#32730) propagate obligations - .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())) + self.infcx.eq_types(false, &self.misc(span), a, b) + .map(|ok| self.register_infer_ok_obligations(ok)) } fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> { @@ -346,7 +357,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { let lv_ty = lv.ty(mir, tcx).to_ty(tcx); let rv_ty = rv.ty(mir, tcx); if let Some(rv_ty) = rv_ty { - if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) { + if let Err(terr) = self.sub_types(rv_ty, lv_ty) { span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}", lv_ty, rv_ty, terr); } @@ -407,7 +418,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } => { let lv_ty = location.ty(mir, tcx).to_ty(tcx); let rv_ty = value.ty(mir, tcx); - if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) { + if let Err(terr) = self.sub_types(rv_ty, lv_ty) { span_mirbug!(self, term, "bad DropAndReplace ({:?} = {:?}): {:?}", lv_ty, rv_ty, terr); } @@ -424,7 +435,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => { let discr_ty = discr.ty(mir, tcx).to_ty(tcx); - if let Err(terr) = self.sub_types(self.last_span, discr_ty, switch_ty) { + if let Err(terr) = self.sub_types(discr_ty, switch_ty) { span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}", switch_ty, discr_ty, terr); } @@ -486,7 +497,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn check_call_dest(&self, + fn check_call_dest(&mut self, mir: &Mir<'tcx>, term: &Terminator<'tcx>, sig: &ty::FnSig<'tcx>, @@ -495,7 +506,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { match *destination { Some((ref dest, _)) => { let dest_ty = dest.ty(mir, tcx).to_ty(tcx); - if let Err(terr) = self.sub_types(self.last_span, sig.output, dest_ty) { + if let Err(terr) = self.sub_types(sig.output, dest_ty) { span_mirbug!(self, term, "call dest mismatch ({:?} <- {:?}): {:?}", dest_ty, sig.output, terr); @@ -510,7 +521,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn check_call_inputs(&self, + fn check_call_inputs(&mut self, mir: &Mir<'tcx>, term: &Terminator<'tcx>, sig: &ty::FnSig<'tcx>, @@ -523,7 +534,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } for (n, (fn_arg, op_arg)) in sig.inputs.iter().zip(args).enumerate() { let op_arg_ty = op_arg.ty(mir, self.tcx()); - if let Err(terr) = self.sub_types(self.last_span, op_arg_ty, fn_arg) { + if let Err(terr) = self.sub_types(op_arg_ty, fn_arg) { span_mirbug!(self, term, "bad arg #{:?} ({:?} <- {:?}): {:?}", n, fn_arg, op_arg_ty, terr); } @@ -541,7 +552,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn check_box_free_inputs(&self, + fn check_box_free_inputs(&mut self, mir: &Mir<'tcx>, term: &Terminator<'tcx>, sig: &ty::FnSig<'tcx>, @@ -578,7 +589,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } }; - if let Err(terr) = self.sub_types(self.last_span, arg_ty, pointee_ty) { + if let Err(terr) = self.sub_types(arg_ty, pointee_ty) { span_mirbug!(self, term, "bad box_free arg ({:?} <- {:?}): {:?}", pointee_ty, arg_ty, terr); } @@ -715,7 +726,7 @@ impl<'tcx> MirPass<'tcx> for TypeckMir { } let param_env = ty::ParameterEnvironment::for_item(tcx, src.item_id()); tcx.infer_ctxt(None, Some(param_env), Reveal::NotSpecializable).enter(|infcx| { - let mut checker = TypeChecker::new(&infcx); + let mut checker = TypeChecker::new(&infcx, src.item_id()); { let mut verifier = TypeVerifier::new(&mut checker, mir); verifier.visit_mir(mir); diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index ca630624cdb38..556d1f84fccdc 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -11,7 +11,8 @@ use rustc::hir::{self, PatKind}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; -use rustc::infer::{self, InferOk, TypeOrigin}; +use rustc::infer; +use rustc::traits::ObligationCauseCode; use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference}; use check::{FnCtxt, Expectation, Diverges}; use util::nodemap::FxHashMap; @@ -450,17 +451,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => false }; - let origin = if is_if_let_fallback { - TypeOrigin::IfExpressionWithNoElse(expr.span) + let cause = if is_if_let_fallback { + self.cause(expr.span, ObligationCauseCode::IfExpressionWithNoElse) } else { - TypeOrigin::MatchExpressionArm(expr.span, arm.body.span, match_src) + self.cause(expr.span, ObligationCauseCode::MatchExpressionArm { + arm_span: arm.body.span, + source: match_src + }) }; let result = if is_if_let_fallback { - self.eq_types(true, origin, arm_ty, result_ty) - .map(|InferOk { obligations, .. }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.eq_types(true, &cause, arm_ty, result_ty) + .map(|infer_ok| { + self.register_infer_ok_obligations(infer_ok); arm_ty }) } else if i == 0 { @@ -468,7 +471,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.try_coerce(&arm.body, arm_ty, coerce_first) } else { let prev_arms = || arms[..i].iter().map(|arm| &*arm.body); - self.try_find_coercion_lub(origin, prev_arms, result_ty, &arm.body, arm_ty) + self.try_find_coercion_lub(&cause, prev_arms, result_ty, &arm.body, arm_ty) }; result_ty = match result { @@ -479,7 +482,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { (result_ty, arm_ty) }; - self.report_mismatched_types(origin, expected, found, e); + self.report_mismatched_types(&cause, expected, found, e); self.tcx.types.err } }; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 16493412d690b..718c273785ae9 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -63,8 +63,8 @@ use check::FnCtxt; use rustc::hir; -use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace}; -use rustc::traits::{self, ObligationCause}; +use rustc::infer::{Coercion, InferOk, TypeTrace}; +use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::{self, LvaluePreference, TypeAndMut, Ty}; use rustc::ty::fold::TypeFoldable; @@ -78,7 +78,7 @@ use std::ops::Deref; struct Coerce<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - origin: TypeOrigin, + cause: ObligationCause<'tcx>, use_lub: bool, unsizing_obligations: RefCell>>, } @@ -104,10 +104,10 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability, } impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { - fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, origin: TypeOrigin) -> Self { + fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, cause: ObligationCause<'tcx>) -> Self { Coerce { fcx: fcx, - origin: origin, + cause: cause, use_lub: false, unsizing_obligations: RefCell::new(vec![]), } @@ -115,19 +115,14 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { fn unify(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { self.commit_if_ok(|_| { - let trace = TypeTrace::types(self.origin, false, a, b); + let trace = TypeTrace::types(&self.cause, false, a, b); if self.use_lub { self.lub(false, trace, &a, &b) - .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - value - }) + .map(|ok| self.register_infer_ok_obligations(ok)) } else { self.sub(false, trace, &a, &b) .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + self.fcx.register_predicates(obligations); value }) } @@ -238,7 +233,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { _ => return self.unify_and_identity(a, b), }; - let span = self.origin.span(); + let span = self.cause.span; let mut first_error = None; let mut r_borrow_var = None; @@ -430,7 +425,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { (&ty::TyRef(_, mt_a), &ty::TyRef(_, mt_b)) => { coerce_mutbls(mt_a.mutbl, mt_b.mutbl)?; - let coercion = Coercion(self.origin.span()); + let coercion = Coercion(self.cause.span); let r_borrow = self.next_region_var(coercion); (mt_a.ty, Some(AutoBorrow::Ref(r_borrow, mt_b.mutbl))) } @@ -449,7 +444,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { let mut leftover_predicates = vec![]; // Create an obligation for `Source: CoerceUnsized`. - let cause = ObligationCause::misc(self.origin.span(), self.body_id); + let cause = ObligationCause::misc(self.cause.span, self.body_id); queue.push_back(self.tcx .predicate_for_trait_def(cause, coerce_unsized_did, 0, source, &[target])); @@ -635,7 +630,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let source = self.resolve_type_vars_with_obligations(expr_ty); debug!("coercion::try({:?}: {:?} -> {:?})", expr, source, target); - let mut coerce = Coerce::new(self, TypeOrigin::ExprAssignable(expr.span)); + let cause = self.cause(expr.span, ObligationCauseCode::ExprAssignable); + let mut coerce = Coerce::new(self, cause); self.commit_if_ok(|_| { let adjustment = apply(&mut coerce, &|| Some(expr), source, target)?; if !adjustment.is_identity() { @@ -655,7 +651,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { /// tries to unify the types, potentially inserting coercions on any of the /// provided expressions and returns their LUB (aka "common supertype"). pub fn try_find_coercion_lub<'b, E, I>(&self, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, exprs: E, prev_ty: Ty<'tcx>, new: &'b hir::Expr, @@ -669,7 +665,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let new_ty = self.resolve_type_vars_with_obligations(new_ty); debug!("coercion::try_find_lub({:?}, {:?})", prev_ty, new_ty); - let trace = TypeTrace::types(origin, true, prev_ty, new_ty); + let trace = TypeTrace::types(cause, true, prev_ty, new_ty); // Special-case that coercion alone cannot handle: // Two function item types of differing IDs or Substs. @@ -677,21 +673,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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 = self.lub(true, trace.clone(), &a_fty, &b_fty) - .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - value - })?; + .map(|ok| self.register_infer_ok_obligations(ok))?; if a_def_id == b_def_id { // Same function, maybe the parameters match. let substs = self.commit_if_ok(|_| { self.lub(true, trace.clone(), &a_substs, &b_substs) - .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - value - }) + .map(|ok| self.register_infer_ok_obligations(ok)) }); if let Ok(substs) = substs { @@ -715,7 +703,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { _ => {} } - let mut coerce = Coerce::new(self, origin); + let mut coerce = Coerce::new(self, cause.clone()); coerce.use_lub = true; // First try to coerce the new expression to the type of the previous ones, @@ -760,11 +748,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if !noop { return self.commit_if_ok(|_| { self.lub(true, trace.clone(), &prev_ty, &new_ty) - .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - value - }) + .map(|ok| self.register_infer_ok_obligations(ok)) }); } } @@ -777,11 +761,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } else { self.commit_if_ok(|_| { self.lub(true, trace, &prev_ty, &new_ty) - .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - value - }) + .map(|ok| self.register_infer_ok_obligations(ok)) }) } } diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 54a0ef071ce4b..2602ff05badd4 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -9,10 +9,10 @@ // except according to those terms. use rustc::hir; -use rustc::infer::{self, InferOk, TypeOrigin}; +use rustc::infer::{self, InferOk}; use rustc::middle::free_region::FreeRegionMap; use rustc::ty; -use rustc::traits::{self, Reveal}; +use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{Subst, Substs}; use rustc::hir::{ImplItemKind, TraitItem_, Ty_}; @@ -95,6 +95,17 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let trait_to_impl_substs = impl_trait_ref.substs; + let cause = ObligationCause { + span: impl_m_span, + body_id: impl_m_body_id, + code: ObligationCauseCode::CompareImplMethodObligation { + item_name: impl_m.name, + impl_item_def_id: impl_m.def_id, + trait_item_def_id: trait_m.def_id, + lint_id: if !old_broken_mode { Some(impl_m_body_id) } else { None }, + }, + }; + // This code is best explained by example. Consider a trait: // // trait Trait<'t,T> { @@ -235,20 +246,9 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); - let cause = traits::ObligationCause { - span: impl_m_span, - body_id: impl_m_body_id, - code: traits::ObligationCauseCode::CompareImplMethodObligation { - item_name: impl_m.name, - impl_item_def_id: impl_m.def_id, - trait_item_def_id: trait_m.def_id, - lint_id: if !old_broken_mode { Some(impl_m_body_id) } else { None }, - }, - }; - fulfillment_cx.borrow_mut().register_predicate_obligation( &infcx, - traits::Obligation::new(cause, predicate)); + traits::Obligation::new(cause.clone(), predicate)); } // We now need to check that the signature of the impl method is @@ -266,7 +266,6 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Compute skolemized form of impl and trait method tys. let tcx = infcx.tcx; - let origin = TypeOrigin::MethodCompatCheck(impl_m_span); let m_fty = |method: &ty::AssociatedItem| { match tcx.item_type(method.def_id).sty { @@ -315,7 +314,7 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, debug!("compare_impl_method: trait_fty={:?}", trait_fty); - let sub_result = infcx.sub_types(false, origin, impl_fty, trait_fty) + let sub_result = infcx.sub_types(false, &cause, impl_fty, trait_fty) .map(|InferOk { obligations, .. }| { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()); @@ -328,22 +327,25 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let (impl_err_span, trait_err_span) = extract_spans_for_error_reporting(&infcx, &terr, - origin, + &cause, impl_m, impl_sig, trait_m, trait_sig); - let origin = TypeOrigin::MethodCompatCheck(impl_err_span); + let cause = ObligationCause { + span: impl_err_span, + ..cause.clone() + }; let mut diag = struct_span_err!(tcx.sess, - origin.span(), + cause.span, E0053, "method `{}` has an incompatible type for trait", trait_m.name); infcx.note_type_err(&mut diag, - origin, + &cause, trait_err_span.map(|sp| (sp, format!("type in trait"))), Some(infer::ValuePairs::Types(ExpectedFound { expected: trait_fty, @@ -429,7 +431,7 @@ fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, terr: &TypeError, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, impl_m: &ty::AssociatedItem, impl_sig: ty::FnSig<'tcx>, trait_m: &ty::AssociatedItem, @@ -478,9 +480,9 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a } } }) - .unwrap_or((origin.span(), tcx.map.span_if_local(trait_m.def_id))) + .unwrap_or((cause.span, tcx.map.span_if_local(trait_m.def_id))) } else { - (origin.span(), tcx.map.span_if_local(trait_m.def_id)) + (cause.span, tcx.map.span_if_local(trait_m.def_id)) } } TypeError::Sorts(ExpectedFound { .. }) => { @@ -499,25 +501,25 @@ fn extract_spans_for_error_reporting<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a .zip(impl_m_iter) .zip(trait_m_iter) .filter_map(|(((impl_arg_ty, trait_arg_ty), impl_arg), trait_arg)| { - match infcx.sub_types(true, origin, trait_arg_ty, impl_arg_ty) { + match infcx.sub_types(true, &cause, trait_arg_ty, impl_arg_ty) { Ok(_) => None, Err(_) => Some((impl_arg.ty.span, Some(trait_arg.ty.span))), } }) .next() .unwrap_or_else(|| { - if infcx.sub_types(false, origin, impl_sig.output, trait_sig.output) + if infcx.sub_types(false, &cause, impl_sig.output, trait_sig.output) .is_err() { (impl_m_output.span(), Some(trait_m_output.span())) } else { - (origin.span(), tcx.map.span_if_local(trait_m.def_id)) + (cause.span, tcx.map.span_if_local(trait_m.def_id)) } }) } else { - (origin.span(), tcx.map.span_if_local(trait_m.def_id)) + (cause.span, tcx.map.span_if_local(trait_m.def_id)) } } - _ => (origin.span(), tcx.map.span_if_local(trait_m.def_id)), + _ => (cause.span, tcx.map.span_if_local(trait_m.def_id)), } } @@ -787,7 +789,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Compute skolemized form of impl and trait const tys. let impl_ty = tcx.item_type(impl_c.def_id).subst(tcx, impl_to_skol_substs); let trait_ty = tcx.item_type(trait_c.def_id).subst(tcx, trait_to_skol_substs); - let mut origin = TypeOrigin::Misc(impl_c_span); + let mut cause = ObligationCause::misc(impl_c_span, impl_c_node_id); let err = infcx.commit_if_ok(|_| { // There is no "body" here, so just pass dummy id. @@ -807,11 +809,12 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, debug!("compare_const_impl: trait_ty={:?}", trait_ty); - infcx.sub_types(false, origin, impl_ty, trait_ty) - .map(|InferOk { obligations, .. }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()) - }) + infcx.sub_types(false, &cause, impl_ty, trait_ty) + .map(|InferOk { obligations, value: () }| { + for obligation in obligations { + fulfillment_cx.register_predicate_obligation(&infcx, obligation); + } + }) }); if let Err(terr) = err { @@ -821,12 +824,12 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Locate the Span containing just the type of the offending impl match tcx.map.expect_impl_item(impl_c_node_id).node { - ImplItemKind::Const(ref ty, _) => origin = TypeOrigin::Misc(ty.span), + ImplItemKind::Const(ref ty, _) => cause.span = ty.span, _ => bug!("{:?} is not a impl const", impl_c), } let mut diag = struct_span_err!(tcx.sess, - origin.span(), + cause.span, E0326, "implemented const `{}` has an incompatible type for \ trait", @@ -840,7 +843,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, }; infcx.note_type_err(&mut diag, - origin, + &cause, Some((trait_c_span, format!("type in trait"))), Some(infer::ValuePairs::Types(ExpectedFound { expected: trait_ty, diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index d622bc7f751d7..ef1c08bdab549 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -11,7 +11,8 @@ use check::FnCtxt; use rustc::ty::Ty; -use rustc::infer::{InferOk, TypeOrigin}; +use rustc::infer::{InferOk}; +use rustc::traits::ObligationCause; use syntax_pos::Span; use rustc::hir; @@ -20,34 +21,32 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // Requires that the two types unify, and prints an error message if // they don't. pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { - let origin = TypeOrigin::Misc(sp); - match self.sub_types(false, origin, actual, expected) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + let cause = self.misc(sp); + match self.sub_types(false, &cause, actual, expected) { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations); }, Err(e) => { - self.report_mismatched_types(origin, expected, actual, e); + self.report_mismatched_types(&cause, expected, actual, e); } } } pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) { - self.demand_eqtype_with_origin(TypeOrigin::Misc(sp), expected, actual); + self.demand_eqtype_with_origin(&self.misc(sp), expected, actual); } pub fn demand_eqtype_with_origin(&self, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) { - match self.eq_types(false, origin, actual, expected) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + match self.eq_types(false, cause, actual, expected) { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations); }, Err(e) => { - self.report_mismatched_types(origin, expected, actual, e); + self.report_mismatched_types(cause, expected, actual, e); } } } @@ -56,9 +55,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn demand_coerce(&self, expr: &hir::Expr, checked_ty: Ty<'tcx>, expected: Ty<'tcx>) { let expected = self.resolve_type_vars_with_obligations(expected); if let Err(e) = self.try_coerce(expr, checked_ty, expected) { - let origin = TypeOrigin::Misc(expr.span); + let cause = self.misc(expr.span); let expr_ty = self.resolve_type_vars_with_obligations(checked_ty); - self.report_mismatched_types(origin, expected, expr_ty, e); + self.report_mismatched_types(&cause, expected, expr_ty, e); } } } diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 09e1f6592c170..8868d1e54f4b9 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -17,7 +17,7 @@ use rustc::infer::{self, InferOk}; use middle::region; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, AdtKind, Ty, TyCtxt}; -use rustc::traits::{self, Reveal}; +use rustc::traits::{self, ObligationCause, Reveal}; use util::nodemap::FxHashSet; use syntax::ast; @@ -93,8 +93,8 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did); let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs); - match infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span), - named_type, fresh_impl_self_ty) { + let cause = &ObligationCause::misc(drop_impl_span, drop_impl_node_id); + match infcx.eq_types(true, cause, named_type, fresh_impl_self_ty) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()); diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index ac6343cae1c8e..77106b8b0c3a1 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -12,7 +12,7 @@ //! intrinsics that the compiler exposes. use intrinsics; -use rustc::infer::TypeOrigin; +use rustc::traits::{ObligationCause, ObligationCauseCode}; use rustc::ty::subst::Substs; use rustc::ty::FnSig; use rustc::ty::{self, Ty}; @@ -63,7 +63,9 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, .emit(); } else { require_same_types(ccx, - TypeOrigin::IntrinsicType(it.span), + &ObligationCause::new(it.span, + it.id, + ObligationCauseCode::IntrinsicType), tcx.item_type(def_id), fty); } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 0b6f7794e9fe1..54e93978b798d 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -17,7 +17,7 @@ use rustc::traits; use rustc::ty::{self, LvaluePreference, NoPreference, PreferMutLvalue, Ty}; use rustc::ty::adjustment::{Adjustment, Adjust, AutoBorrow}; use rustc::ty::fold::TypeFoldable; -use rustc::infer::{self, InferOk, TypeOrigin}; +use rustc::infer::{self, InferOk}; use syntax_pos::Span; use rustc::hir; @@ -330,10 +330,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { } fn unify_receivers(&mut self, self_ty: Ty<'tcx>, method_self_ty: Ty<'tcx>) { - match self.sub_types(false, TypeOrigin::Misc(self.span), self_ty, method_self_ty) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + match self.sub_types(false, &self.misc(self.span), self_ty, method_self_ty) { + Ok(InferOk { obligations, value: () }) => { + self.register_predicates(obligations); } Err(_) => { span_bug!(self.span, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 481923c259787..545d4e788524f 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -16,13 +16,13 @@ use super::suggest; use check::FnCtxt; use hir::def_id::DefId; use hir::def::Def; +use rustc::infer::InferOk; use rustc::ty::subst::{Subst, Substs}; -use rustc::traits; +use rustc::traits::{self, ObligationCause}; use rustc::ty::{self, Ty, ToPolyTraitRef, TraitRef, TypeFoldable}; -use rustc::infer::{InferOk, TypeOrigin}; use rustc::util::nodemap::FxHashSet; use syntax::ast; -use syntax_pos::{Span, DUMMY_SP}; +use syntax_pos::Span; use rustc::hir; use std::mem; use std::ops::Deref; @@ -1032,10 +1032,10 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { self.probe(|_| { // First check that the self type can be related. match self.sub_types(false, - TypeOrigin::Misc(DUMMY_SP), + &ObligationCause::dummy(), self_ty, probe.xform_self_ty) { - Ok(InferOk { obligations, .. }) => { + Ok(InferOk { obligations, value: () }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a95b3f4a973bb..8e9dfe54f0131 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -87,9 +87,9 @@ use hir::def::{Def, CtorKind, PathResolution}; use hir::def_id::{DefId, LOCAL_CRATE}; use hir::pat_util; use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin, - TypeOrigin, TypeTrace, type_variable}; + TypeTrace, type_variable}; use rustc::ty::subst::{Kind, Subst, Substs}; -use rustc::traits::{self, Reveal}; +use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::{ParamTy, ParameterEnvironment}; use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue}; use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, Visibility}; @@ -1521,6 +1521,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + pub fn cause(&self, + span: Span, + code: ObligationCauseCode<'tcx>) + -> ObligationCause<'tcx> { + ObligationCause::new(span, self.body_id, code) + } + + pub fn misc(&self, span: Span) -> ObligationCause<'tcx> { + self.cause(span, ObligationCauseCode::MiscObligation) + } + /// Resolves type variables in `ty` if possible. Unlike the infcx /// version (resolve_type_vars_if_possible), this version will /// also select obligations if it seems useful, in an effort @@ -1786,6 +1797,19 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { .register_predicate_obligation(self, obligation); } + pub fn register_predicates(&self, + obligations: Vec>) + { + for obligation in obligations { + self.register_predicate(obligation); + } + } + + pub fn register_infer_ok_obligations(&self, infer_ok: InferOk<'tcx, T>) -> T { + self.register_predicates(infer_ok.obligations); + infer_ok.value + } + pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> { let t = AstConv::ast_ty_to_ty(self, self, ast_t); self.register_wf_obligation(t, ast_t.span, traits::MiscObligation); @@ -2096,15 +2120,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(default) = default_map.get(ty) { let default = default.clone(); match self.eq_types(false, - TypeOrigin::Misc(default.origin_span), - ty, default.ty) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()) - }, - Err(_) => { - conflicts.push((*ty, default)); - } + &self.misc(default.origin_span), + ty, + default.ty) { + Ok(ok) => self.register_infer_ok_obligations(ok), + Err(_) => conflicts.push((*ty, default)), } } } @@ -2146,6 +2166,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.report_conflicting_default_types( first_default.origin_span, + self.body_id, first_default, second_default) } @@ -2194,10 +2215,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(default) = default_map.get(ty) { let default = default.clone(); match self.eq_types(false, - TypeOrigin::Misc(default.origin_span), - ty, default.ty) { - // FIXME(#32730) propagate obligations - Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()), + &self.misc(default.origin_span), + ty, + default.ty) { + Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { result = Some(default); } @@ -2765,13 +2786,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // return type (likely containing type variables if the function // is polymorphic) and the expected return type. // No argument expectations are produced if unification fails. - let origin = TypeOrigin::Misc(call_span); - let ures = self.sub_types(false, origin, formal_ret, ret_ty); + let origin = self.misc(call_span); + let ures = self.sub_types(false, &origin, formal_ret, ret_ty); // FIXME(#15760) can't use try! here, FromError doesn't default // to identity so the resulting type is not constrained. match ures { - // FIXME(#32730) propagate obligations - Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()), + Ok(ok) => self.register_infer_ok_obligations(ok), Err(e) => return Err(e), } @@ -2852,16 +2872,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.diverges.set(Diverges::Maybe); let unit = self.tcx.mk_nil(); - let (origin, expected, found, result) = + let (cause, expected_ty, found_ty, result); if let Some(else_expr) = opt_else_expr { let else_ty = self.check_expr_with_expectation(else_expr, expected); let else_diverges = self.diverges.get(); + cause = self.cause(sp, ObligationCauseCode::IfExpression); // Only try to coerce-unify if we have a then expression // to assign coercions to, otherwise it's () or diverging. - let origin = TypeOrigin::IfExpression(sp); - let result = if let Some(ref then) = then_blk.expr { - let res = self.try_find_coercion_lub(origin, || Some(&**then), + expected_ty = then_ty; + found_ty = else_ty; + result = if let Some(ref then) = then_blk.expr { + let res = self.try_find_coercion_lub(&cause, || Some(&**then), then_ty, else_expr, else_ty); // In case we did perform an adjustment, we have to update @@ -2876,33 +2898,27 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { res } else { self.commit_if_ok(|_| { - let trace = TypeTrace::types(origin, true, then_ty, else_ty); + let trace = TypeTrace::types(&cause, true, then_ty, else_ty); self.lub(true, trace, &then_ty, &else_ty) - .map(|InferOk { value, obligations }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - value - }) + .map(|ok| self.register_infer_ok_obligations(ok)) }) }; // We won't diverge unless both branches do (or the condition does). self.diverges.set(cond_diverges | then_diverges & else_diverges); - - (origin, then_ty, else_ty, result) } else { // If the condition is false we can't diverge. self.diverges.set(cond_diverges); - let origin = TypeOrigin::IfExpressionWithNoElse(sp); - (origin, unit, then_ty, - self.eq_types(true, origin, unit, then_ty) - .map(|InferOk { obligations, .. }| { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - unit - })) - }; + cause = self.cause(sp, ObligationCauseCode::IfExpressionWithNoElse); + expected_ty = unit; + found_ty = then_ty; + result = self.eq_types(true, &cause, unit, then_ty) + .map(|ok| { + self.register_infer_ok_obligations(ok); + unit + }); + } match result { Ok(ty) => { @@ -2913,7 +2929,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } Err(e) => { - self.report_mismatched_types(origin, expected, found, e); + self.report_mismatched_types(&cause, expected_ty, found_ty, e); self.tcx.types.err } } @@ -3564,17 +3580,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(ref e) = *expr_opt { self.check_expr_coercable_to_type(&e, self.ret_ty); } else { - let eq_result = self.eq_types(false, - TypeOrigin::Misc(expr.span), - self.ret_ty, - tcx.mk_nil()) - // FIXME(#32730) propagate obligations - .map(|InferOk { obligations, .. }| assert!(obligations.is_empty())); - if eq_result.is_err() { - struct_span_err!(tcx.sess, expr.span, E0069, - "`return;` in a function whose return type is not `()`") - .span_label(expr.span, &format!("return type is not ()")) - .emit(); + match self.eq_types(false, + &self.misc(expr.span), + self.ret_ty, + tcx.mk_nil()) + { + Ok(ok) => self.register_infer_ok_obligations(ok), + Err(_) => { + struct_span_err!(tcx.sess, expr.span, E0069, + "`return;` in a function whose return type is not `()`") + .span_label(expr.span, &format!("return type is not ()")) + .emit(); + } } } tcx.types.never @@ -3695,20 +3712,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for (i, e) in args.iter().enumerate() { let e_ty = self.check_expr_with_hint(e, coerce_to); - let origin = TypeOrigin::Misc(e.span); + let cause = self.misc(e.span); // Special-case the first element, as it has no "previous expressions". let result = if i == 0 { self.try_coerce(e, e_ty, coerce_to) } else { let prev_elems = || args[..i].iter().map(|e| &**e); - self.try_find_coercion_lub(origin, prev_elems, unified, e, e_ty) + self.try_find_coercion_lub(&cause, prev_elems, unified, e, e_ty) }; match result { Ok(ty) => unified = ty, Err(e) => { - self.report_mismatched_types(origin, unified, e_ty, e); + self.report_mismatched_types(&cause, unified, e_ty, e); } } } @@ -4064,9 +4081,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // We're not diverging and there's an expected type, which, // in case it's not `()`, could result in an error higher-up. // We have a chance to error here early and be more helpful. - let origin = TypeOrigin::Misc(blk.span); - let trace = TypeTrace::types(origin, false, ty, ety); - match self.sub_types(false, origin, ty, ety) { + let cause = self.misc(blk.span); + let trace = TypeTrace::types(&cause, false, ty, ety); + match self.sub_types(false, &cause, ty, ety) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()); @@ -4367,11 +4384,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let ty = self.tcx.item_type(impl_def_id); let impl_ty = self.instantiate_type_scheme(span, &substs, &ty); - match self.sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); - } + match self.sub_types(false, &self.misc(span), self_ty, impl_ty) { + Ok(ok) => self.register_infer_ok_obligations(ok), Err(_) => { span_bug!(span, "instantiate_value_path: (UFCS) {:?} was a subtype of {:?} but now is not?", diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index e019c4c761483..a280001d5e99d 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -91,7 +91,7 @@ use middle::region::{self, CodeExtent}; use rustc::ty::subst::Substs; use rustc::traits; use rustc::ty::{self, Ty, MethodCall, TypeFoldable}; -use rustc::infer::{self, GenericKind, InferOk, SubregionOrigin, TypeOrigin, VerifyBound}; +use rustc::infer::{self, GenericKind, SubregionOrigin, VerifyBound}; use hir::pat_util; use rustc::ty::adjustment; use rustc::ty::wf::ImpliedBound; @@ -1762,10 +1762,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { outlives); // check whether this predicate applies to our current projection - match self.eq_types(false, TypeOrigin::Misc(span), ty, outlives.0) { - Ok(InferOk { obligations, .. }) => { - // FIXME(#32730) propagate obligations - assert!(obligations.is_empty()); + let cause = self.fcx.misc(span); + match self.eq_types(false, &cause, ty, outlives.0) { + Ok(ok) => { + self.register_infer_ok_obligations(ok); Ok(outlives.1) } Err(_) => { Err(()) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 066b3d4be0881..41bea18741629 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -15,8 +15,7 @@ use CrateCtxt; use hir::def_id::DefId; use middle::region::{CodeExtent}; -use rustc::infer::TypeOrigin; -use rustc::traits; +use rustc::traits::{self, ObligationCauseCode}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::{FxHashSet, FxHashMap}; @@ -29,7 +28,7 @@ use rustc::hir; pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> { ccx: &'ccx CrateCtxt<'ccx, 'tcx>, - code: traits::ObligationCauseCode<'tcx>, + code: ObligationCauseCode<'tcx>, } /// Helper type of a temporary returned by .for_item(...). @@ -37,7 +36,7 @@ pub struct CheckTypeWellFormedVisitor<'ccx, 'tcx:'ccx> { /// F: for<'b, 'tcx> where 'gcx: 'tcx FnOnce(FnCtxt<'b, 'gcx, 'tcx>). struct CheckWfFcxBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { inherited: super::InheritedBuilder<'a, 'gcx, 'tcx>, - code: traits::ObligationCauseCode<'gcx>, + code: ObligationCauseCode<'gcx>, id: ast::NodeId, span: Span } @@ -67,7 +66,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { -> CheckTypeWellFormedVisitor<'ccx, 'gcx> { CheckTypeWellFormedVisitor { ccx: ccx, - code: traits::ObligationCauseCode::MiscObligation + code: ObligationCauseCode::MiscObligation } } @@ -515,8 +514,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty); - let origin = TypeOrigin::MethodReceiver(span); - fcx.demand_eqtype_with_origin(origin, rcvr_ty, self_arg_ty); + let cause = fcx.cause(span, ObligationCauseCode::MethodReceiver); + fcx.demand_eqtype_with_origin(&cause, rcvr_ty, self_arg_ty); } fn check_variances_for_type_defn(&self, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 5863305826462..7c860bc5aecb3 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -19,7 +19,7 @@ use hir::def_id::DefId; use middle::lang_items::UnsizeTraitLangItem; use rustc::ty::subst::Subst; use rustc::ty::{self, TyCtxt, TypeFoldable}; -use rustc::traits::{self, Reveal}; +use rustc::traits::{self, ObligationCause, Reveal}; use rustc::ty::ParameterEnvironment; use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{TyParam, TyRawPtr}; @@ -30,7 +30,7 @@ use rustc::ty::{TyProjection, TyAnon}; use rustc::ty::util::CopyImplementationError; use middle::free_region::FreeRegionMap; use CrateCtxt; -use rustc::infer::{self, InferCtxt, TypeOrigin}; +use rustc::infer::{self, InferCtxt}; use syntax_pos::Span; use rustc::dep_graph::DepNode; use rustc::hir::map as hir_map; @@ -344,12 +344,12 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { target); tcx.infer_ctxt(None, Some(param_env), Reveal::ExactMatch).enter(|infcx| { - let origin = TypeOrigin::Misc(span); + let cause = ObligationCause::misc(span, impl_node_id); let check_mutbl = |mt_a: ty::TypeAndMut<'gcx>, mt_b: ty::TypeAndMut<'gcx>, mk_ptr: &Fn(Ty<'gcx>) -> Ty<'gcx>| { if (mt_a.mutbl, mt_b.mutbl) == (hir::MutImmutable, hir::MutMutable) { - infcx.report_mismatched_types(origin, + infcx.report_mismatched_types(&cause, mk_ptr(mt_b.ty), target, ty::error::TypeError::Mutability); @@ -397,7 +397,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { } // Ignore fields that aren't significantly changed - if let Ok(ok) = infcx.sub_types(false, origin, b, a) { + if let Ok(ok) = infcx.sub_types(false, &cause, b, a) { if ok.obligations.is_empty() { return None; } diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 2c12959dbdde2..76f8254cb0fef 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -106,10 +106,10 @@ pub use rustc::util; use dep_graph::DepNode; use hir::map as hir_map; -use rustc::infer::{InferOk, TypeOrigin}; +use rustc::infer::InferOk; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::traits::{self, Reveal}; +use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use session::{config, CompileResult}; use util::common::time; @@ -172,19 +172,19 @@ fn require_c_abi_if_variadic(tcx: TyCtxt, } fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, - origin: TypeOrigin, + cause: &ObligationCause<'tcx>, expected: Ty<'tcx>, actual: Ty<'tcx>) -> bool { ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { - match infcx.eq_types(false, origin.clone(), expected, actual) { + match infcx.eq_types(false, &cause, expected, actual) { Ok(InferOk { obligations, .. }) => { // FIXME(#32730) propagate obligations assert!(obligations.is_empty()); true } Err(err) => { - infcx.report_mismatched_types(origin, expected, actual, err); + infcx.report_mismatched_types(cause, expected, actual, err); false } } @@ -231,7 +231,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, require_same_types( ccx, - TypeOrigin::MainFunctionType(main_span), + &ObligationCause::new(main_span, main_id, ObligationCauseCode::MainFunctionType), se_ty, main_t); } @@ -286,7 +286,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, require_same_types( ccx, - TypeOrigin::StartFunctionType(start_span), + &ObligationCause::new(start_span, start_id, ObligationCauseCode::StartFunctionType), se_ty, start_t); }