Skip to content

Commit 5fe733a

Browse files
authored
Auto merge of #37404 - eddyb:lazy-4, r=nikomatsakis
[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.
2 parents 161f262 + aee1ee3 commit 5fe733a

File tree

7 files changed

+78
-44
lines changed

7 files changed

+78
-44
lines changed

src/librustc/infer/mod.rs

+10-3
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
10691069
self.probe(|_| {
10701070
let origin = TypeOrigin::Misc(syntax_pos::DUMMY_SP);
10711071
let trace = TypeTrace::types(origin, true, a, b);
1072-
self.sub(true, trace, &a, &b).map(|_| ())
1072+
self.sub(true, trace, &a, &b).map(|InferOk { obligations, .. }| {
1073+
// FIXME(#32730) propagate obligations
1074+
assert!(obligations.is_empty());
1075+
})
10731076
})
10741077
}
10751078

@@ -1592,8 +1595,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
15921595
// anyhow. We should make this typetrace stuff more
15931596
// generic so we don't have to do anything quite this
15941597
// terrible.
1595-
self.equate(true, TypeTrace::dummy(self.tcx), a, b)
1596-
}).map(|_| ())
1598+
let trace = TypeTrace::dummy(self.tcx);
1599+
self.equate(true, trace, a, b).map(|InferOk { obligations, .. }| {
1600+
// FIXME(#32730) propagate obligations
1601+
assert!(obligations.is_empty());
1602+
})
1603+
})
15971604
}
15981605

15991606
pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {

src/librustc/traits/coherence.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use super::{SelectionContext, Obligation, ObligationCause};
1414

1515
use hir::def_id::{DefId, LOCAL_CRATE};
1616
use ty::{self, Ty, TyCtxt};
17-
use infer::{InferCtxt, TypeOrigin};
17+
use infer::{InferCtxt, InferOk, TypeOrigin};
1818
use syntax_pos::DUMMY_SP;
1919

2020
#[derive(Copy, Clone)]
@@ -55,11 +55,13 @@ fn overlap<'cx, 'gcx, 'tcx>(selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
5555
debug!("overlap: b_impl_header={:?}", b_impl_header);
5656

5757
// Do `a` and `b` unify? If not, no overlap.
58-
if let Err(_) = selcx.infcx().eq_impl_headers(true,
59-
TypeOrigin::Misc(DUMMY_SP),
60-
&a_impl_header,
61-
&b_impl_header) {
62-
return None;
58+
match selcx.infcx().eq_impl_headers(true, TypeOrigin::Misc(DUMMY_SP), &a_impl_header,
59+
&b_impl_header) {
60+
Ok(InferOk { obligations, .. }) => {
61+
// FIXME(#32730) propagate obligations
62+
assert!(obligations.is_empty());
63+
}
64+
Err(_) => return None
6365
}
6466

6567
debug!("overlap: unification check succeeded");

src/librustc/traits/specialize/mod.rs

+13-9
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use super::util::impl_trait_ref_and_oblig;
2222

2323
use rustc_data_structures::fnv::FnvHashMap;
2424
use hir::def_id::DefId;
25-
use infer::{InferCtxt, TypeOrigin};
25+
use infer::{InferCtxt, InferOk, TypeOrigin};
2626
use middle::region;
2727
use ty::subst::{Subst, Substs};
2828
use traits::{self, Reveal, ObligationCause};
@@ -222,14 +222,18 @@ fn fulfill_implication<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
222222
target_substs);
223223

224224
// do the impls unify? If not, no specialization.
225-
if let Err(_) = infcx.eq_trait_refs(true,
226-
TypeOrigin::Misc(DUMMY_SP),
227-
source_trait_ref,
228-
target_trait_ref) {
229-
debug!("fulfill_implication: {:?} does not unify with {:?}",
230-
source_trait_ref,
231-
target_trait_ref);
232-
return Err(());
225+
match infcx.eq_trait_refs(true, TypeOrigin::Misc(DUMMY_SP), source_trait_ref,
226+
target_trait_ref) {
227+
Ok(InferOk { obligations, .. }) => {
228+
// FIXME(#32730) propagate obligations
229+
assert!(obligations.is_empty())
230+
}
231+
Err(_) => {
232+
debug!("fulfill_implication: {:?} does not unify with {:?}",
233+
source_trait_ref,
234+
target_trait_ref);
235+
return Err(());
236+
}
233237
}
234238

235239
// attempt to prove all of the predicates for impl2 given those for impl1

src/librustc_typeck/check/compare_method.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,13 @@ fn compare_predicate_entailment<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
298298

299299
debug!("compare_impl_method: trait_fty={:?}", trait_fty);
300300

301-
if let Err(terr) = infcx.sub_types(false, origin, impl_fty, trait_fty) {
301+
let sub_result = infcx.sub_types(false, origin, impl_fty, trait_fty)
302+
.map(|InferOk { obligations, .. }| {
303+
// FIXME(#32730) propagate obligations
304+
assert!(obligations.is_empty());
305+
});
306+
307+
if let Err(terr) = sub_result {
302308
debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
303309
impl_fty,
304310
trait_fty);

src/librustc_typeck/check/dropck.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use check::regionck::RegionCtxt;
1313

1414
use hir::def_id::DefId;
1515
use middle::free_region::FreeRegionMap;
16-
use rustc::infer;
16+
use rustc::infer::{self, InferOk};
1717
use middle::region;
1818
use rustc::ty::subst::{Subst, Substs};
1919
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
@@ -93,16 +93,22 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
9393
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did);
9494
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
9595

96-
if let Err(_) = infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span),
97-
named_type, fresh_impl_self_ty) {
98-
let item_span = tcx.map.span(self_type_node_id);
99-
struct_span_err!(tcx.sess, drop_impl_span, E0366,
100-
"Implementations of Drop cannot be specialized")
101-
.span_note(item_span,
102-
"Use same sequence of generic type and region \
103-
parameters that is on the struct/enum definition")
104-
.emit();
105-
return Err(());
96+
match infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span),
97+
named_type, fresh_impl_self_ty) {
98+
Ok(InferOk { obligations, .. }) => {
99+
// FIXME(#32730) propagate obligations
100+
assert!(obligations.is_empty());
101+
}
102+
Err(_) => {
103+
let item_span = tcx.map.span(self_type_node_id);
104+
struct_span_err!(tcx.sess, drop_impl_span, E0366,
105+
"Implementations of Drop cannot be specialized")
106+
.span_note(item_span,
107+
"Use same sequence of generic type and region \
108+
parameters that is on the struct/enum definition")
109+
.emit();
110+
return Err(());
111+
}
106112
}
107113

108114
if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {

src/librustc_typeck/coherence/mod.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -415,15 +415,19 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> {
415415

416416
if f.unsubst_ty().is_phantom_data() {
417417
// Ignore PhantomData fields
418-
None
419-
} else if infcx.sub_types(false, origin, b, a).is_ok() {
420-
// Ignore fields that aren't significantly changed
421-
None
422-
} else {
423-
// Collect up all fields that were significantly changed
424-
// i.e. those that contain T in coerce_unsized T -> U
425-
Some((i, a, b))
418+
return None;
426419
}
420+
421+
// Ignore fields that aren't significantly changed
422+
if let Ok(ok) = infcx.sub_types(false, origin, b, a) {
423+
if ok.obligations.is_empty() {
424+
return None;
425+
}
426+
}
427+
428+
// Collect up all fields that were significantly changed
429+
// i.e. those that contain T in coerce_unsized T -> U
430+
Some((i, a, b))
427431
})
428432
.collect::<Vec<_>>();
429433

src/librustc_typeck/lib.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ pub use rustc::util;
106106

107107
use dep_graph::DepNode;
108108
use hir::map as hir_map;
109-
use rustc::infer::TypeOrigin;
109+
use rustc::infer::{InferOk, TypeOrigin};
110110
use rustc::ty::subst::Substs;
111111
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
112112
use rustc::traits::{self, Reveal};
@@ -198,11 +198,16 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
198198
actual: Ty<'tcx>)
199199
-> bool {
200200
ccx.tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| {
201-
if let Err(err) = infcx.eq_types(false, origin.clone(), expected, actual) {
202-
infcx.report_mismatched_types(origin, expected, actual, err);
203-
false
204-
} else {
205-
true
201+
match infcx.eq_types(false, origin.clone(), expected, actual) {
202+
Ok(InferOk { obligations, .. }) => {
203+
// FIXME(#32730) propagate obligations
204+
assert!(obligations.is_empty());
205+
true
206+
}
207+
Err(err) => {
208+
infcx.report_mismatched_types(origin, expected, actual, err);
209+
false
210+
}
206211
}
207212
})
208213
}

0 commit comments

Comments
 (0)