Skip to content

Commit

Permalink
Auto merge of #37404 - eddyb:lazy-4, r=nikomatsakis
Browse files Browse the repository at this point in the history
[4/n] rustc: harden against InferOk having obligations in more cases.

_This is part of a series ([prev](#37402) | [next](#37408)) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well.
If any motivation is unclear, please ask for additional PR description clarifications or code comments._

<hr>

This adds more asserts that `InferOk` results have no obligations, pending completion of #32730.

Each of these could accidentally drop obligations on the floor if they start getting produced by unification, and a future change does just that, in order to produce a "shallow success" (hopefully leading to ambiguities during trait selection), _without_ the possibility of an eventual success - mostly guarded by ICEs for now.
  • Loading branch information
bors authored Nov 6, 2016
2 parents 161f262 + aee1ee3 commit 5fe733a
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 44 deletions.
13 changes: 10 additions & 3 deletions src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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());
})
})
}

Expand Down Expand Up @@ -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>> {
Expand Down
14 changes: 8 additions & 6 deletions src/librustc/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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");
Expand Down
22 changes: 13 additions & 9 deletions src/librustc/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion src/librustc_typeck/check/compare_method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
28 changes: 17 additions & 11 deletions src/librustc_typeck/check/dropck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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) {
Expand Down
20 changes: 12 additions & 8 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<_>>();

Expand Down
17 changes: 11 additions & 6 deletions src/librustc_typeck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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
}
}
})
}
Expand Down

0 comments on commit 5fe733a

Please sign in to comment.