Skip to content

Commit 0c94ea0

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 2cbe07b commit 0c94ea0

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 crate::infer::CombinedSnapshot;
78
use crate::ty::relate::{Relate, RelateResult, TypeRelation};
89
use crate::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))
@@ -108,4 +112,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
108112

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

src/librustc/infer/mod.rs

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

940-
Some(self.commit_if_ok(|_snapshot| {
940+
Some(self.commit_if_ok(|snapshot| {
941941
let (
942942
ty::SubtypePredicate {
943943
a_is_expected,
944944
a,
945945
b,
946946
},
947-
_,
947+
placeholder_map,
948948
) = self.replace_bound_vars_with_placeholders(predicate);
949949

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

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

970977
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
@@ -730,9 +730,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
730730
}
731731

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

738743
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 crate::dep_graph::{DepKind, DepNodeIndex};
3131
use crate::hir::def_id::DefId;
32-
use crate::infer::{InferCtxt, InferOk, TypeFreshener};
32+
use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener};
3333
use crate::middle::lang_items;
3434
use crate::mir::interpret::GlobalId;
3535
use crate::ty::fast_reject;
@@ -1667,8 +1667,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16671667
_ => return,
16681668
}
16691669

1670-
let result = self.infcx.probe(|_| {
1671-
self.match_projection_obligation_against_definition_bounds(obligation)
1670+
let result = self.infcx.probe(|snapshot| {
1671+
self.match_projection_obligation_against_definition_bounds(
1672+
obligation,
1673+
snapshot,
1674+
)
16721675
});
16731676

16741677
if result {
@@ -1679,10 +1682,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
16791682
fn match_projection_obligation_against_definition_bounds(
16801683
&mut self,
16811684
obligation: &TraitObligation<'tcx>,
1685+
snapshot: &CombinedSnapshot<'_, 'tcx>,
16821686
) -> bool {
16831687
let poly_trait_predicate = self.infcx()
16841688
.resolve_type_vars_if_possible(&obligation.predicate);
1685-
let (placeholder_trait_predicate, _) = self.infcx()
1689+
let (placeholder_trait_predicate, placeholder_map) = self.infcx()
16861690
.replace_bound_vars_with_placeholders(&poly_trait_predicate);
16871691
debug!(
16881692
"match_projection_obligation_against_definition_bounds: \
@@ -1724,6 +1728,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17241728
obligation,
17251729
bound.clone(),
17261730
placeholder_trait_predicate.trait_ref.clone(),
1731+
&placeholder_map,
1732+
snapshot,
17271733
)
17281734
})
17291735
});
@@ -1741,6 +1747,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17411747
obligation,
17421748
bound,
17431749
placeholder_trait_predicate.trait_ref.clone(),
1750+
&placeholder_map,
1751+
snapshot,
17441752
);
17451753

17461754
assert!(result);
@@ -1754,12 +1762,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
17541762
obligation: &TraitObligation<'tcx>,
17551763
trait_bound: ty::PolyTraitRef<'tcx>,
17561764
placeholder_trait_ref: ty::TraitRef<'tcx>,
1765+
placeholder_map: &PlaceholderMap<'tcx>,
1766+
snapshot: &CombinedSnapshot<'_, 'tcx>,
17571767
) -> bool {
17581768
debug_assert!(!placeholder_trait_ref.has_escaping_bound_vars());
17591769
self.infcx
17601770
.at(&obligation.cause, obligation.param_env)
17611771
.sup(ty::Binder::dummy(placeholder_trait_ref), trait_bound)
17621772
.is_ok()
1773+
&&
1774+
self.infcx.leak_check(false, placeholder_map, snapshot).is_ok()
17631775
}
17641776

17651777
/// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
@@ -1960,8 +1972,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
19601972
obligation.predicate.def_id(),
19611973
obligation.predicate.skip_binder().trait_ref.self_ty(),
19621974
|impl_def_id| {
1963-
self.infcx.probe(|_| {
1964-
if let Ok(_substs) = self.match_impl(impl_def_id, obligation)
1975+
self.infcx.probe(|snapshot| {
1976+
if let Ok(_substs) = self.match_impl(impl_def_id, obligation, snapshot)
19651977
{
19661978
candidates.vec.push(ImplCandidate(impl_def_id));
19671979
}
@@ -2758,9 +2770,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
27582770
}
27592771

27602772
fn confirm_projection_candidate(&mut self, obligation: &TraitObligation<'tcx>) {
2761-
self.infcx.in_snapshot(|_| {
2773+
self.infcx.in_snapshot(|snapshot| {
27622774
let result =
2763-
self.match_projection_obligation_against_definition_bounds(obligation);
2775+
self.match_projection_obligation_against_definition_bounds(
2776+
obligation,
2777+
snapshot,
2778+
);
27642779
assert!(result);
27652780
})
27662781
}
@@ -2912,8 +2927,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
29122927

29132928
// First, create the substitutions by matching the impl again,
29142929
// this time not in a probe.
2915-
self.infcx.in_snapshot(|_| {
2916-
let substs = self.rematch_impl(impl_def_id, obligation);
2930+
self.infcx.in_snapshot(|snapshot| {
2931+
let substs = self.rematch_impl(impl_def_id, obligation, snapshot);
29172932
debug!("confirm_impl_candidate: substs={:?}", substs);
29182933
let cause = obligation.derived_cause(ImplDerivedObligation);
29192934
self.vtable_impl(
@@ -3504,8 +3519,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
35043519
&mut self,
35053520
impl_def_id: DefId,
35063521
obligation: &TraitObligation<'tcx>,
3522+
snapshot: &CombinedSnapshot<'_, 'tcx>,
35073523
) -> Normalized<'tcx, &'tcx Substs<'tcx>> {
3508-
match self.match_impl(impl_def_id, obligation) {
3524+
match self.match_impl(impl_def_id, obligation, snapshot) {
35093525
Ok(substs) => substs,
35103526
Err(()) => {
35113527
bug!(
@@ -3521,6 +3537,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
35213537
&mut self,
35223538
impl_def_id: DefId,
35233539
obligation: &TraitObligation<'tcx>,
3540+
snapshot: &CombinedSnapshot<'_, 'tcx>,
35243541
) -> Result<Normalized<'tcx, &'tcx Substs<'tcx>>, ()> {
35253542
let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
35263543

@@ -3531,7 +3548,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
35313548
return Err(());
35323549
}
35333550

3534-
let (skol_obligation, _) = self.infcx()
3551+
let (skol_obligation, placeholder_map) = self.infcx()
35353552
.replace_bound_vars_with_placeholders(&obligation.predicate);
35363553
let skol_obligation_trait_ref = skol_obligation.trait_ref;
35373554

@@ -3563,6 +3580,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
35633580
.map_err(|e| debug!("match_impl: failed eq_trait_refs due to `{}`", e))?;
35643581
nested_obligations.extend(obligations);
35653582

3583+
if let Err(e) = self.infcx.leak_check(false, &placeholder_map, snapshot) {
3584+
debug!("match_impl: failed leak check due to `{}`", e);
3585+
return Err(());
3586+
}
3587+
35663588
debug!("match_impl: success impl_substs={:?}", impl_substs);
35673589
Ok(Normalized {
35683590
value: impl_substs,

0 commit comments

Comments
 (0)