Skip to content

Commit bdc70a0

Browse files
committed
introduce a dummy leak check and invoke it in all the right places
This set of diffs was produced by combing through b68fad6 and seeing where the `leak_check` used to be invoked and how.
1 parent ed747ea commit bdc70a0

File tree

7 files changed

+105
-39
lines changed

7 files changed

+105
-39
lines changed

src/librustc/infer/higher_ranked/mod.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
use super::combine::CombineFields;
55
use super::{HigherRankedType, InferCtxt, PlaceholderMap};
66

7+
use infer::CombinedSnapshot;
78
use ty::relate::{Relate, RelateResult, TypeRelation};
89
use ty::{self, Binder, TypeFoldable};
910

@@ -29,10 +30,10 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
2930

3031
let span = self.trace.cause.span;
3132

32-
return self.infcx.commit_if_ok(|_snapshot| {
33+
return self.infcx.commit_if_ok(|snapshot| {
3334
// First, we instantiate each bound region in the supertype with a
3435
// fresh placeholder region.
35-
let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b);
36+
let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b);
3637

3738
// Next, we instantiate each bound region in the subtype
3839
// with a fresh region variable. These region variables --
@@ -48,6 +49,9 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
4849
// Compare types now that bound regions have been replaced.
4950
let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
5051

52+
self.infcx
53+
.leak_check(!a_is_expected, &placeholder_map, snapshot)?;
54+
5155
debug!("higher_ranked_sub: OK result={:?}", result);
5256

5357
Ok(ty::Binder::bind(result))
@@ -111,4 +115,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
111115

112116
(result, map)
113117
}
118+
119+
/// Searches region constraints created since `snapshot` that
120+
/// affect one of the placeholders in `placeholder_map`, returning
121+
/// an error if any of the placeholders are related to another
122+
/// placeholder or would have to escape into some parent universe
123+
/// that cannot name them.
124+
///
125+
/// This is a temporary backwards compatibility measure to try and
126+
/// retain the older (arguably incorrect) behavior of the
127+
/// compiler.
128+
pub fn leak_check(
129+
&self,
130+
_overly_polymorphic: bool,
131+
_placeholder_map: &PlaceholderMap<'tcx>,
132+
_snapshot: &CombinedSnapshot<'_, 'tcx>,
133+
) -> RelateResult<'tcx, ()> {
134+
Ok(())
135+
}
114136
}

src/librustc/infer/mod.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -935,34 +935,41 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
935935
return None;
936936
}
937937

938-
Some(self.commit_if_ok(|_snapshot| {
938+
Some(self.commit_if_ok(|snapshot| {
939939
let (
940940
ty::SubtypePredicate {
941941
a_is_expected,
942942
a,
943943
b,
944944
},
945-
_,
945+
placeholder_map,
946946
) = self.replace_bound_vars_with_placeholders(predicate);
947947

948-
Ok(
949-
self.at(cause, param_env)
950-
.sub_exp(a_is_expected, a, b)?
951-
.unit(),
952-
)
948+
let ok = self.at(cause, param_env)
949+
.sub_exp(a_is_expected, a, b)?;
950+
951+
self.leak_check(false, &placeholder_map, snapshot)?;
952+
953+
Ok(ok.unit())
953954
}))
954955
}
955956

956957
pub fn region_outlives_predicate(
957958
&self,
958959
cause: &traits::ObligationCause<'tcx>,
959960
predicate: &ty::PolyRegionOutlivesPredicate<'tcx>,
960-
) {
961-
let (ty::OutlivesPredicate(r_a, r_b), _) =
962-
self.replace_bound_vars_with_placeholders(predicate);
963-
let origin =
964-
SubregionOrigin::from_obligation_cause(cause, || RelateRegionParamBound(cause.span));
965-
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
961+
) -> UnitResult<'tcx> {
962+
self.commit_if_ok(|snapshot| {
963+
let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
964+
self.replace_bound_vars_with_placeholders(predicate);
965+
let origin = SubregionOrigin::from_obligation_cause(
966+
cause,
967+
|| RelateRegionParamBound(cause.span),
968+
);
969+
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
970+
self.leak_check(false, &placeholder_map, snapshot)?;
971+
Ok(())
972+
})
966973
}
967974

968975
pub fn next_ty_var_id(&self, diverging: bool, origin: TypeVariableOrigin) -> TyVid {

src/librustc/traits/auto_trait.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,13 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
771771
}
772772
}
773773
&ty::Predicate::RegionOutlives(ref binder) => {
774-
let () = select.infcx().region_outlives_predicate(&dummy_cause, binder);
774+
if select
775+
.infcx()
776+
.region_outlives_predicate(&dummy_cause, binder)
777+
.is_err()
778+
{
779+
return false;
780+
}
775781
}
776782
&ty::Predicate::TypeOutlives(ref binder) => {
777783
match (

src/librustc/traits/error_reporting.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -726,9 +726,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
726726
}
727727

728728
ty::Predicate::RegionOutlives(ref predicate) => {
729-
// These errors should show up as region
730-
// inference failures.
731-
panic!("region outlives {:?} failed", predicate);
729+
let predicate = self.resolve_type_vars_if_possible(predicate);
730+
let err = self.region_outlives_predicate(&obligation.cause,
731+
&predicate).err().unwrap();
732+
struct_span_err!(
733+
self.tcx.sess, span, E0279,
734+
"the requirement `{}` is not satisfied (`{}`)",
735+
predicate, err,
736+
)
732737
}
733738

734739
ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {

src/librustc/traits/fulfill.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,10 @@ impl<'a, 'b, 'gcx, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'gcx,
331331
}
332332

333333
ty::Predicate::RegionOutlives(ref binder) => {
334-
let () = self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder);
335-
ProcessResult::Changed(vec![])
334+
match self.selcx.infcx().region_outlives_predicate(&obligation.cause, binder) {
335+
Ok(()) => ProcessResult::Changed(vec![]),
336+
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
337+
}
336338
}
337339

338340
ty::Predicate::TypeOutlives(ref binder) => {

src/librustc/traits/project.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -191,12 +191,15 @@ pub fn poly_project_and_unify_type<'cx, 'gcx, 'tcx>(
191191
obligation);
192192

193193
let infcx = selcx.infcx();
194-
infcx.commit_if_ok(|_| {
195-
let (placeholder_predicate, _) =
194+
infcx.commit_if_ok(|snapshot| {
195+
let (placeholder_predicate, placeholder_map) =
196196
infcx.replace_bound_vars_with_placeholders(&obligation.predicate);
197197

198198
let placeholder_obligation = obligation.with(placeholder_predicate);
199-
project_and_unify_type(selcx, &placeholder_obligation)
199+
let result = project_and_unify_type(selcx, &placeholder_obligation)?;
200+
infcx.leak_check(false, &placeholder_map, snapshot)
201+
.map_err(|err| MismatchedProjectionTypes { err })?;
202+
Ok(result)
200203
})
201204
}
202205

@@ -1427,9 +1430,8 @@ fn confirm_callable_candidate<'cx, 'gcx, 'tcx>(
14271430
fn confirm_param_env_candidate<'cx, 'gcx, 'tcx>(
14281431
selcx: &mut SelectionContext<'cx, 'gcx, 'tcx>,
14291432
obligation: &ProjectionTyObligation<'tcx>,
1430-
poly_cache_entry: ty::PolyProjectionPredicate<'tcx>)
1431-
-> Progress<'tcx>
1432-
{
1433+
poly_cache_entry: ty::PolyProjectionPredicate<'tcx>,
1434+
) -> Progress<'tcx> {
14331435
let infcx = selcx.infcx();
14341436
let cause = &obligation.cause;
14351437
let param_env = obligation.param_env;

src/librustc/traits/select.rs

+34-12
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use super::{
2929

3030
use dep_graph::{DepKind, DepNodeIndex};
3131
use hir::def_id::DefId;
32-
use infer::{InferCtxt, InferOk, TypeFreshener};
32+
use infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
3333
use middle::lang_items;
3434
use mir::interpret::GlobalId;
3535
use ty::fast_reject;
@@ -1624,8 +1624,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16241624
_ => return,
16251625
}
16261626

1627-
let result = self.infcx.probe(|_| {
1628-
self.match_projection_obligation_against_definition_bounds(obligation)
1627+
let result = self.infcx.probe(|snapshot| {
1628+
self.match_projection_obligation_against_definition_bounds(
1629+
obligation,
1630+
snapshot,
1631+
)
16291632
});
16301633

16311634
if result {
@@ -1636,10 +1639,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16361639
fn match_projection_obligation_against_definition_bounds(
16371640
&mut self,
16381641
obligation: &TraitObligation<'tcx>,
1642+
snapshot: &CombinedSnapshot<'_, 'tcx>,
16391643
) -> bool {
16401644
let poly_trait_predicate = self.infcx()
16411645
.resolve_type_vars_if_possible(&obligation.predicate);
1642-
let (placeholder_trait_predicate, _) = self.infcx()
1646+
let (placeholder_trait_predicate, placeholder_map) = self.infcx()
16431647
.replace_bound_vars_with_placeholders(&poly_trait_predicate);
16441648
debug!(
16451649
"match_projection_obligation_against_definition_bounds: \
@@ -1681,6 +1685,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16811685
obligation,
16821686
bound.clone(),
16831687
placeholder_trait_predicate.trait_ref.clone(),
1688+
&placeholder_map,
1689+
snapshot,
16841690
)
16851691
})
16861692
});
@@ -1698,6 +1704,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16981704
obligation,
16991705
bound,
17001706
placeholder_trait_predicate.trait_ref.clone(),
1707+
&placeholder_map,
1708+
snapshot,
17011709
);
17021710

17031711
assert!(result);
@@ -1711,12 +1719,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17111719
obligation: &TraitObligation<'tcx>,
17121720
trait_bound: ty::PolyTraitRef<'tcx>,
17131721
placeholder_trait_ref: ty::TraitRef<'tcx>,
1722+
placeholder_map: &PlaceholderMap<'tcx>,
1723+
snapshot: &CombinedSnapshot<'_, 'tcx>,
17141724
) -> bool {
17151725
debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
17161726
self.infcx
17171727
.at(&obligation.cause, obligation.param_env)
17181728
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
17191729
.is_ok()
1730+
&&
1731+
self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
17201732
}
17211733

17221734
/// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
@@ -1917,8 +1929,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
19171929
obligation.predicate.def_id(),
19181930
obligation.predicate.skip_binder().trait_ref.self_ty(),
19191931
|impl_def_id| {
1920-
self.infcx.probe(|_| {
1921-
if let Ok(_substs) = self.match_impl(impl_def_id, obligation)
1932+
self.infcx.probe(|snapshot| {
1933+
if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot)
19221934
{
19231935
candidates.vec.push(ImplCandidate(impl_def_id));
19241936
}
@@ -2697,9 +2709,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
26972709
}
26982710

26992711
fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
2700-
self.infcx.in_snapshot(|_| {
2712+
self.infcx.in_snapshot(|snapshot| {
27012713
let result =
2702-
self.match_projection_obligation_against_definition_bounds(obligation);
2714+
self.match_projection_obligation_against_definition_bounds(
2715+
obligation,
2716+
snapshot,
2717+
);
27032718
assert!(result);
27042719
})
27052720
}
@@ -2851,8 +2866,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
28512866

28522867
// First, create the substitutions by matching the impl again,
28532868
// this time not in a probe.
2854-
self.infcx.in_snapshot(|_| {
2855-
let substs = self.rematch_impl(impl_def_id, obligation);
2869+
self.infcx.in_snapshot(|snapshot| {
2870+
let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
28562871
debug!("confirm_impl_candidate: substs={:?}", substs);
28572872
let cause = obligation.derived_cause(ImplDerivedObligation);
28582873
self.vtable_impl(
@@ -3443,8 +3458,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
34433458
&mut self,
34443459
impl_def_id: DefId,
34453460
obligation: &TraitObligation<'tcx>,
3461+
snapshot: &CombinedSnapshot<'_, 'tcx>,
34463462
) -> Normalized<'tcx, &'tcx Substs<'tcx>> {
3447-
match self.match_impl(impl_def_id, obligation) {
3463+
match self.match_impl(impl_def_id, obligation, snapshot) {
34483464
Ok(substs) => substs,
34493465
Err(()) => {
34503466
bug!(
@@ -3460,6 +3476,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
34603476
&mut self,
34613477
impl_def_id: DefId,
34623478
obligation: &TraitObligation<'tcx>,
3479+
snapshot: &CombinedSnapshot<'_, 'tcx>,
34633480
) -> Result<Normalized<'tcx, &'tcx Substs<'tcx>>, ()> {
34643481
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
34653482

@@ -3470,7 +3487,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
34703487
return Err(());
34713488
}
34723489

3473-
let (skol_obligation, _) = self.infcx()
3490+
let (skol_obligation, placeholder_map) = self.infcx()
34743491
.replace_bound_vars_with_placeholders(&obligation.predicate);
34753492
let skol_obligation_trait_ref = skol_obligation.trait_ref;
34763493

@@ -3502,6 +3519,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
35023519
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
35033520
nested_obligations.extend(obligations);
35043521

3522+
if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
3523+
debug!("match_impl: failed leak check due to `{}`", e);
3524+
return Err(());
3525+
}
3526+
35053527
debug!("match_impl: success impl_substs={:?}", impl_substs);
35063528
Ok(Normalized {
35073529
value: impl_substs,

0 commit comments

Comments
 (0)