rustc: harden against InferOk having obligations in more cases.

This commit is contained in:
Eduard Burtescu 2016-10-04 02:19:40 +03:00
parent 161f2623bd
commit aee1ee3cc2
7 changed files with 78 additions and 44 deletions

View File

@ -1069,7 +1069,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
self.probe(|_| {
let origin = TypeOrigin::Misc(syntax_pos::DUMMY_SP);
let trace = TypeTrace::types(origin, true, a, b);
self.sub(true, trace, &a, &b).map(|_| ())
self.sub(true, trace, &a, &b).map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
})
})
}
@ -1592,8 +1595,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
// anyhow. We should make this typetrace stuff more
// generic so we don't have to do anything quite this
// terrible.
self.equate(true, TypeTrace::dummy(self.tcx), a, b)
}).map(|_| ())
let trace = TypeTrace::dummy(self.tcx);
self.equate(true, trace, a, b).map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
})
})
}
pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {

View File

@ -14,7 +14,7 @@ use super::{SelectionContext, Obligation, ObligationCause};
use hir::def_id::{DefId, LOCAL_CRATE};
use ty::{self, Ty, TyCtxt};
use infer::{InferCtxt, TypeOrigin};
use infer::{InferCtxt, InferOk, TypeOrigin};
use syntax_pos::DUMMY_SP;
#[derive(Copy, Clone)]
@ -55,11 +55,13 @@ 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.
if let Err(_) = selcx.infcx().eq_impl_headers(true,
TypeOrigin::Misc(DUMMY_SP),
&a_impl_header,
&b_impl_header) {
return None;
match selcx.infcx().eq_impl_headers(true, TypeOrigin::Misc(DUMMY_SP), &a_impl_header,
&b_impl_header) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
Err(_) => return None
}
debug!("overlap: unification check succeeded");

View File

@ -22,7 +22,7 @@ use super::util::impl_trait_ref_and_oblig;
use rustc_data_structures::fnv::FnvHashMap;
use hir::def_id::DefId;
use infer::{InferCtxt, TypeOrigin};
use infer::{InferCtxt, InferOk, TypeOrigin};
use middle::region;
use ty::subst::{Subst, Substs};
use traits::{self, Reveal, ObligationCause};
@ -222,14 +222,18 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
target_substs);
// do the impls unify? If not, no specialization.
if let Err(_) = infcx.eq_trait_refs(true,
TypeOrigin::Misc(DUMMY_SP),
source_trait_ref,
target_trait_ref) {
debug!("fulfill_implication: {:?} does not unify with {:?}",
source_trait_ref,
target_trait_ref);
return Err(());
match infcx.eq_trait_refs(true, TypeOrigin::Misc(DUMMY_SP), source_trait_ref,
target_trait_ref) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty())
}
Err(_) => {
debug!("fulfill_implication: {:?} does not unify with {:?}",
source_trait_ref,
target_trait_ref);
return Err(());
}
}
// attempt to prove all of the predicates for impl2 given those for impl1

View File

@ -298,7 +298,13 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
if let Err(terr) = infcx.sub_types(false, origin, impl_fty, trait_fty) {
let sub_result = infcx.sub_types(false, origin, impl_fty, trait_fty)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
});
if let Err(terr) = sub_result {
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
impl_fty,
trait_fty);

View File

@ -13,7 +13,7 @@ use check::regionck::RegionCtxt;
use hir::def_id::DefId;
use middle::free_region::FreeRegionMap;
use rustc::infer;
use rustc::infer::{self, InferOk};
use middle::region;
use rustc::ty::subst::{Subst, Substs};
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
@ -93,16 +93,22 @@ 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);
if let Err(_) = infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span),
named_type, fresh_impl_self_ty) {
let item_span = tcx.map.span(self_type_node_id);
struct_span_err!(tcx.sess, drop_impl_span, E0366,
"Implementations of Drop cannot be specialized")
.span_note(item_span,
"Use same sequence of generic type and region \
parameters that is on the struct/enum definition")
.emit();
return Err(());
match infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span),
named_type, fresh_impl_self_ty) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
}
Err(_) => {
let item_span = tcx.map.span(self_type_node_id);
struct_span_err!(tcx.sess, drop_impl_span, E0366,
"Implementations of Drop cannot be specialized")
.span_note(item_span,
"Use same sequence of generic type and region \
parameters that is on the struct/enum definition")
.emit();
return Err(());
}
}
if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {

View File

@ -415,15 +415,19 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
if f.unsubst_ty().is_phantom_data() {
// Ignore PhantomData fields
None
} else if infcx.sub_types(false, origin, b, a).is_ok() {
// Ignore fields that aren't significantly changed
None
} else {
// Collect up all fields that were significantly changed
// i.e. those that contain T in coerce_unsized T -> U
Some((i, a, b))
return None;
}
// Ignore fields that aren't significantly changed
if let Ok(ok) = infcx.sub_types(false, origin, b, a) {
if ok.obligations.is_empty() {
return None;
}
}
// Collect up all fields that were significantly changed
// i.e. those that contain T in coerce_unsized T -> U
Some((i, a, b))
})
.collect::<Vec<_>>();

View File

@ -106,7 +106,7 @@ pub use rustc::util;
use dep_graph::DepNode;
use hir::map as hir_map;
use rustc::infer::TypeOrigin;
use rustc::infer::{InferOk, TypeOrigin};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::traits::{self, Reveal};
@ -198,11 +198,16 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
actual: Ty<'tcx>)
-> bool {
ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
if let Err(err) = infcx.eq_types(false, origin.clone(), expected, actual) {
infcx.report_mismatched_types(origin, expected, actual, err);
false
} else {
true
match infcx.eq_types(false, origin.clone(), expected, actual) {
Ok(InferOk { obligations, .. }) => {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
true
}
Err(err) => {
infcx.report_mismatched_types(origin, expected, actual, err);
false
}
}
})
}