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 |