Skip to content

Commit 903823c

Browse files
authored
Rollup merge of #72493 - nikomatsakis:move-leak-check, r=matthewjasper
move leak-check to during coherence, candidate eval Implementation of MCP rust-lang/compiler-team#295. I'd like to do a crater run on this. Note to @rust-lang/lang: This PR is a breaking change (bugfix). It causes tests like the following to go from a future-compatibility warning #56105 to a hard error: ```rust trait Trait {} impl Trait for for<'a, 'b> fn(&'a u32, &'b u32) {} impl Trait for for<'c> fn(&'c u32, &'c u32) {} // now rejected, used to warn ``` I am not aware of any instances of this code in the wild, but that is why we are doing a crater run. The reason for this change is that those two types are, in fact, the same type, and hence the two impls are overlapping. There will still be impls that trigger #56105 after this lands, however -- I hope that we will eventually just accept those impls without warning, for the most part. One example of such an impl is this pattern, which is used by wasm-bindgen and other crates as well: ```rust trait Trait {} impl<T> Trait for fn(&T) { } impl<T> Trait for fn(T) { } // still accepted, but warns ```
2 parents 59e87c0 + d57689f commit 903823c

File tree

135 files changed

+2143
-1250
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

135 files changed

+2143
-1250
lines changed

src/librustc_infer/infer/higher_ranked/mod.rs

+16-7
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
3030

3131
let span = self.trace.cause.span;
3232

33-
self.infcx.commit_if_ok(|snapshot| {
33+
self.infcx.commit_if_ok(|_| {
3434
// First, we instantiate each bound region in the supertype with a
3535
// fresh placeholder region.
36-
let (b_prime, placeholder_map) = self.infcx.replace_bound_vars_with_placeholders(b);
36+
let (b_prime, _) = self.infcx.replace_bound_vars_with_placeholders(b);
3737

3838
// Next, we instantiate each bound region in the subtype
3939
// with a fresh region variable. These region variables --
@@ -48,8 +48,6 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
4848
// Compare types now that bound regions have been replaced.
4949
let result = self.sub(a_is_expected).relate(&a_prime, &b_prime)?;
5050

51-
self.infcx.leak_check(!a_is_expected, &placeholder_map, snapshot)?;
52-
5351
debug!("higher_ranked_sub: OK result={:?}", result);
5452

5553
Ok(ty::Binder::bind(result))
@@ -75,7 +73,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
7573
where
7674
T: TypeFoldable<'tcx>,
7775
{
78-
let next_universe = self.create_next_universe();
76+
// Figure out what the next universe will be, but don't actually create
77+
// it until after we've done the substitution (in particular there may
78+
// be no bound variables). This is a performance optimization, since the
79+
// leak check for example can be skipped if no new universes are created
80+
// (i.e., if there are no placeholders).
81+
let next_universe = self.universe().next_universe();
7982

8083
let fld_r = |br| {
8184
self.tcx.mk_region(ty::RePlaceholder(ty::PlaceholderRegion {
@@ -103,6 +106,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
103106

104107
let (result, map) = self.tcx.replace_bound_vars(binder, fld_r, fld_t, fld_c);
105108

109+
// If there were higher-ranked regions to replace, then actually create
110+
// the next universe (this avoids needlessly creating universes).
111+
if !map.is_empty() {
112+
let n_u = self.create_next_universe();
113+
assert_eq!(n_u, next_universe);
114+
}
115+
106116
debug!(
107117
"replace_bound_vars_with_placeholders(\
108118
next_universe={:?}, \
@@ -119,7 +129,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
119129
pub fn leak_check(
120130
&self,
121131
overly_polymorphic: bool,
122-
placeholder_map: &PlaceholderMap<'tcx>,
123132
snapshot: &CombinedSnapshot<'_, 'tcx>,
124133
) -> RelateResult<'tcx, ()> {
125134
// If the user gave `-Zno-leak-check`, or we have been
@@ -135,7 +144,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
135144
self.inner.borrow_mut().unwrap_region_constraints().leak_check(
136145
self.tcx,
137146
overly_polymorphic,
138-
placeholder_map,
147+
self.universe(),
139148
snapshot,
140149
)
141150
}

src/librustc_infer/infer/mod.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -991,14 +991,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
991991
return None;
992992
}
993993

994-
Some(self.commit_if_ok(|snapshot| {
995-
let (ty::SubtypePredicate { a_is_expected, a, b }, placeholder_map) =
994+
Some(self.commit_if_ok(|_snapshot| {
995+
let (ty::SubtypePredicate { a_is_expected, a, b }, _) =
996996
self.replace_bound_vars_with_placeholders(&predicate);
997997

998998
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
999999

1000-
self.leak_check(false, &placeholder_map, snapshot)?;
1001-
10021000
Ok(ok.unit())
10031001
}))
10041002
}
@@ -1008,14 +1006,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
10081006
cause: &traits::ObligationCause<'tcx>,
10091007
predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
10101008
) -> UnitResult<'tcx> {
1011-
self.commit_if_ok(|snapshot| {
1012-
let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
1009+
self.commit_if_ok(|_snapshot| {
1010+
let (ty::OutlivesPredicate(r_a, r_b), _) =
10131011
self.replace_bound_vars_with_placeholders(&predicate);
10141012
let origin = SubregionOrigin::from_obligation_cause(cause, || {
10151013
RelateRegionParamBound(cause.span)
10161014
});
10171015
self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
1018-
self.leak_check(false, &placeholder_map, snapshot)?;
10191016
Ok(())
10201017
})
10211018
}

src/librustc_infer/infer/nll_relate/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,13 @@ where
522522
}
523523

524524
if a == b {
525-
return Ok(a);
525+
// Subtle: if a or b has a bound variable that we are lazilly
526+
// substituting, then even if a == b, it could be that the values we
527+
// will substitute for those bound variables are *not* the same, and
528+
// hence returning `Ok(a)` is incorrect.
529+
if !a.has_escaping_bound_vars() && !b.has_escaping_bound_vars() {
530+
return Ok(a);
531+
}
526532
}
527533

528534
match (&a.kind, &b.kind) {

0 commit comments

Comments
 (0)