remove TypeOrigin and use ObligationCause instead

In general having all these different structs for "origins" is not
great, since equating types can cause obligations and vice-versa.  I
think we should gradually collapse these things. We almost certainly
also need to invest a big more energy into the `error_reporting` code to
rationalize it: this PR does kind of the minimal effort in that
direction.
This commit is contained in:
Niko Matsakis 2016-11-07 13:25:06 -05:00
parent 43006fcea0
commit 19c1a47713
28 changed files with 389 additions and 354 deletions

View file

@ -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

View file

@ -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<ValuePairs<'tcx>>,
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",
}
}
}

View file

@ -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);
}

View file

@ -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<ty::BoundRegion, &'tcx ty::Region>;
/// 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<Ty<'tcx>>>
{
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<V: TypeVisitor<'tcx>>(&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<V: TypeVisitor<'tcx>>(&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)
}
}

View file

@ -111,6 +111,7 @@ 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.

View file

@ -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());

View file

@ -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");
}

View file

@ -519,7 +519,7 @@ fn process_predicate<'a, 'gcx, 'tcx>(
}
ty::Predicate::Equate(ref binder) => {
match selcx.infcx().equality_predicate(obligation.cause.span, binder) {
match selcx.infcx().equality_predicate(&obligation.cause, binder) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());

View file

@ -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<ast::NodeId>,
},
// 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)]

View file

@ -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,8 +209,7 @@ 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) {
match infcx.eq_types(true, &obligation.cause, 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());
@ -840,13 +839,12 @@ 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
@ -1153,12 +1151,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()
})
@ -1265,9 +1262,9 @@ 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());

View file

@ -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;
@ -521,7 +521,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 +1247,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 +2439,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 +2480,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 +2550,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 +2613,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 +2700,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 +2774,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))

View file

@ -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())

View file

@ -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<V: TypeVisitor<'tcx>>(&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 |

View file

@ -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),
}

View file

@ -306,22 +306,28 @@ 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)
}
fn sub_types(&self, span: Span, sup: Ty<'tcx>, sub: Ty<'tcx>)
-> infer::UnitResult<'tcx>
{
self.infcx.sub_types(false, infer::TypeOrigin::Misc(span), sup, sub)
self.infcx.sub_types(false, &self.misc(span), sup, sub)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
@ -329,7 +335,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
fn eq_types(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
-> infer::UnitResult<'tcx>
{
self.infcx.eq_types(false, infer::TypeOrigin::Misc(span), a, b)
self.infcx.eq_types(false, &self.misc(span), a, b)
// FIXME(#32730) propagate obligations
.map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
}
@ -715,7 +721,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);

View file

@ -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::{self, InferOk};
use rustc::traits::ObligationCauseCode;
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
use check::{FnCtxt, Expectation, Diverges};
use util::nodemap::FxHashMap;
@ -450,14 +451,17 @@ 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)
self.eq_types(true, &cause, arm_ty, result_ty)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
@ -468,7 +472,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 +483,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
}
};

View file

@ -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<Vec<traits::PredicateObligation<'tcx>>>,
}
@ -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,7 +115,7 @@ 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 }| {
@ -238,7 +238,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 +430,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 +449,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
let mut leftover_predicates = vec![];
// Create an obligation for `Source: CoerceUnsized<Target>`.
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 +635,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 +656,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 +670,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.
@ -715,7 +716,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,

View file

@ -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,7 +809,7 @@ 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)
infcx.sub_types(false, &cause, impl_ty, trait_ty)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty())
@ -821,12 +823,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 +842,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,

View file

@ -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,34 @@ 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) {
let cause = self.misc(sp);
match self.sub_types(false, &cause, actual, expected) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
},
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) {
match self.eq_types(false, cause, actual, expected) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
},
Err(e) => {
self.report_mismatched_types(origin, expected, actual, e);
self.report_mismatched_types(cause, expected, actual, e);
}
}
}
@ -56,9 +57,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);
}
}
}

View file

@ -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());

View file

@ -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);
}

View file

@ -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,7 +330,7 @@ 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) {
match self.sub_types(false, &self.misc(self.span), self_ty, method_self_ty) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());

View file

@ -17,12 +17,12 @@ use check::FnCtxt;
use hir::def_id::DefId;
use hir::def::Def;
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::infer::InferOk;
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,7 +1032,7 @@ 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, .. }) => {

View file

@ -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
@ -2096,8 +2107,9 @@ 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) {
&self.misc(default.origin_span),
ty,
default.ty) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty())
@ -2146,6 +2158,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,8 +2207,9 @@ 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) {
&self.misc(default.origin_span),
ty,
default.ty) {
// FIXME(#32730) propagate obligations
Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()),
Err(_) => {
@ -2765,8 +2779,8 @@ 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 {
@ -2852,16 +2866,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,7 +2892,7 @@ 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
@ -2888,21 +2904,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
// 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(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
unit
});
}
match result {
Ok(ty) => {
@ -2913,7 +2928,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
}
}
@ -3565,7 +3580,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
self.check_expr_coercable_to_type(&e, self.ret_ty);
} else {
let eq_result = self.eq_types(false,
TypeOrigin::Misc(expr.span),
&self.misc(expr.span),
self.ret_ty,
tcx.mk_nil())
// FIXME(#32730) propagate obligations
@ -3695,20 +3710,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 +4079,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,7 +4382,7 @@ 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) {
match self.sub_types(false, &self.misc(span), self_ty, impl_ty) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());

View file

@ -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, InferOk, SubregionOrigin, VerifyBound};
use hir::pat_util;
use rustc::ty::adjustment;
use rustc::ty::wf::ImpliedBound;
@ -1762,7 +1762,8 @@ 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) {
let cause = self.fcx.misc(span);
match self.eq_types(false, &cause, ty, outlives.0) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());

View file

@ -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,

View file

@ -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;
}

View file

@ -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);
}