Skip to content

Commit 4f32381

Browse files
aliemjayjackh726
authored andcommitted
don't touch closure_substs.parent_substs()
... They bite!
1 parent 1e1e5b8 commit 4f32381

9 files changed

+67
-109
lines changed

compiler/rustc_borrowck/src/region_infer/opaque_types.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
105105
.iter()
106106
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
107107
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
108+
// FIXME: This is a troublesome back-compat hack. See #100372.
108109
.unwrap_or(infcx.tcx.lifetimes.re_erased),
109110
_ => region,
110111
});

compiler/rustc_borrowck/src/type_check/mod.rs

-28
Original file line numberDiff line numberDiff line change
@@ -2669,34 +2669,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
26692669
);
26702670
}
26712671

2672-
// Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
2673-
let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
2674-
let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);
2675-
2676-
let parent_substs = match tcx.def_kind(def_id) {
2677-
DefKind::Closure => substs.as_closure().parent_substs(),
2678-
DefKind::Generator => substs.as_generator().parent_substs(),
2679-
DefKind::InlineConst => substs.as_inline_const().parent_substs(),
2680-
other => bug!("unexpected item {:?}", other),
2681-
};
2682-
let parent_substs = tcx.mk_substs(parent_substs.iter());
2683-
2684-
assert_eq!(typeck_root_substs.len(), parent_substs.len());
2685-
if let Err(_) = self.eq_substs(
2686-
typeck_root_substs,
2687-
parent_substs,
2688-
location.to_locations(),
2689-
ConstraintCategory::BoringNoLocation,
2690-
) {
2691-
span_mirbug!(
2692-
self,
2693-
def_id,
2694-
"could not relate closure to parent {:?} != {:?}",
2695-
typeck_root_substs,
2696-
parent_substs
2697-
);
2698-
}
2699-
27002672
tcx.predicates_of(def_id).instantiate(tcx, substs)
27012673
}
27022674

compiler/rustc_borrowck/src/type_check/relate_tys.rs

-17
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
3838
.relate(a, b)?;
3939
Ok(())
4040
}
41-
42-
/// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
43-
pub(super) fn eq_substs(
44-
&mut self,
45-
a: ty::SubstsRef<'tcx>,
46-
b: ty::SubstsRef<'tcx>,
47-
locations: Locations,
48-
category: ConstraintCategory<'tcx>,
49-
) -> Fallible<()> {
50-
TypeRelating::new(
51-
self.infcx,
52-
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
53-
ty::Variance::Invariant,
54-
)
55-
.relate(a, b)?;
56-
Ok(())
57-
}
5841
}
5942

6043
struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {

compiler/rustc_borrowck/src/universal_regions.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,24 @@ impl<'tcx> UniversalRegions<'tcx> {
247247
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
248248
let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
249249
region_mapping.push(tcx.lifetimes.re_static);
250+
251+
let typeck_root_def_id = tcx.local_parent(closure_def_id);
252+
253+
// We rely on the fact that the first N regions in the ClosureSubsts are
254+
// inherited from the `typeck_root_def_id`.
255+
let typeck_root_substs =
256+
ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id.to_def_id());
257+
assert_eq!(closure_substs.regions().count(), typeck_root_substs.regions().count());
258+
259+
// The first N regions in ClosureSubsts are the early-bound regions of `typeck_root_*`.
260+
// Other regions are the early-bound regions in closure signature, upvars, etc.
261+
let mut typeck_root_regions = typeck_root_substs.regions().fuse();
250262
tcx.for_each_free_region(&closure_substs, |fr| {
251-
region_mapping.push(fr);
263+
region_mapping.push(typeck_root_regions.next().unwrap_or(fr));
252264
});
253265

254-
for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
266+
// Now add late-bound regions of `typeck_root_def_id`.
267+
for_each_late_bound_region_in_recursive_scope(tcx, typeck_root_def_id, |r| {
255268
region_mapping.push(r);
256269
});
257270

src/test/ui/nll/issue-98589-closures-relate-named-regions.rs

+6
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,10 @@ fn test_late_type<'a, T>() {
3333
//~^ ERROR the parameter type `T` may not live long enough
3434
}
3535

36+
fn test_closure_arg<'a: 'a>() {
37+
let f = |_: &'a str| {};
38+
f(&String::new());
39+
//~^ ERROR temporary value dropped while borrowed
40+
}
41+
3642
fn main() {}

src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
error: lifetime may not live long enough
2-
--> $DIR/issue-98589-closures-relate-named-regions.rs:10:5
2+
--> $DIR/issue-98589-closures-relate-named-regions.rs:10:10
33
|
44
LL | fn test_early_early<'a: 'a, 'b: 'b>() {
55
| -- -- lifetime `'b` defined here
66
| |
77
| lifetime `'a` defined here
88
LL | || { None::<&'a &'b ()>; };
9-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
9+
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
1010
|
1111
= help: consider adding the following bound: `'b: 'a`
1212

@@ -56,6 +56,19 @@ help: consider adding an explicit lifetime bound...
5656
LL | fn test_late_type<'a, T: 'a>() {
5757
| ++++
5858

59-
error: aborting due to 5 previous errors
59+
error[E0716]: temporary value dropped while borrowed
60+
--> $DIR/issue-98589-closures-relate-named-regions.rs:38:8
61+
|
62+
LL | fn test_closure_arg<'a: 'a>() {
63+
| -- lifetime `'a` defined here
64+
LL | let f = |_: &'a str| {};
65+
LL | f(&String::new());
66+
| ---^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
67+
| | |
68+
| | creates a temporary which is freed while still in use
69+
| argument requires that borrow lasts for `'a`
70+
71+
error: aborting due to 6 previous errors
6072

61-
For more information about this error, try `rustc --explain E0309`.
73+
Some errors have detailed explanations: E0309, E0716.
74+
For more information about an error, try `rustc --explain E0309`.

src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
1-
// If the hidden type is a closure, we require the "outlives" bounds that appear on the
2-
// defining site to also appear on the opaque type.
3-
//
4-
// It's not clear if this is the desired behavior but at least
5-
// it's consistent and has no back-compat risk.
1+
// If the hidden type is a closure, we used to require the "outlives" bounds
2+
// that appear on the defining site to also appear on the opaque type.
63

74
// check-fail
85

96
#![feature(type_alias_impl_trait)]
107
#![allow(dead_code)]
118

12-
// requires `'a: 'b` bound
139
mod test1 {
1410
type Opaque<'a, 'b> = impl Sized + 'a + 'b;
15-
//~^ ERROR lifetime bound not satisfied
1611

1712
fn define<'a, 'b>() -> Opaque<'a, 'b>
1813
where
@@ -25,7 +20,6 @@ mod test1 {
2520
// Same as the above but through indirection `'x`
2621
mod test2 {
2722
type Opaque<'a, 'b> = impl Sized + 'a + 'b;
28-
//~^ ERROR cannot infer an appropriate lifetime
2923

3024
fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
3125
where
@@ -36,7 +30,6 @@ mod test2 {
3630
}
3731
}
3832

39-
// fixed version of the above
4033
mod test2_fixed {
4134
type Opaque<'a: 'b, 'b> = impl Sized + 'a + 'b;
4235

Original file line numberDiff line numberDiff line change
@@ -1,55 +1,11 @@
1-
error[E0478]: lifetime bound not satisfied
2-
--> $DIR/closure_wf_outlives.rs:14:27
3-
|
4-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
5-
| ^^^^^^^^^^^^^^^^^^^^
6-
|
7-
note: lifetime parameter instantiated with the lifetime `'a` as defined here
8-
--> $DIR/closure_wf_outlives.rs:14:17
9-
|
10-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
11-
| ^^
12-
note: but lifetime parameter must outlive the lifetime `'b` as defined here
13-
--> $DIR/closure_wf_outlives.rs:14:21
14-
|
15-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
16-
| ^^
17-
18-
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
19-
--> $DIR/closure_wf_outlives.rs:27:27
20-
|
21-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
22-
| ^^^^^^^^^^^^^^^^^^^^
23-
|
24-
note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
25-
--> $DIR/closure_wf_outlives.rs:27:17
26-
|
27-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
28-
| ^^
29-
note: ...so that the declared lifetime parameter bounds are satisfied
30-
--> $DIR/closure_wf_outlives.rs:27:27
31-
|
32-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
33-
| ^^^^^^^^^^^^^^^^^^^^
34-
note: but, the lifetime must be valid for the lifetime `'b` as defined here...
35-
--> $DIR/closure_wf_outlives.rs:27:21
36-
|
37-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
38-
| ^^
39-
note: ...so that the declared lifetime parameter bounds are satisfied
40-
--> $DIR/closure_wf_outlives.rs:27:27
41-
|
42-
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
43-
| ^^^^^^^^^^^^^^^^^^^^
44-
451
error[E0310]: the parameter type `T` may not live long enough
46-
--> $DIR/closure_wf_outlives.rs:54:22
2+
--> $DIR/closure_wf_outlives.rs:47:22
473
|
484
LL | type Opaque<T> = impl Sized;
495
| ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
506
|
517
note: ...that is required by this bound
52-
--> $DIR/closure_wf_outlives.rs:59:12
8+
--> $DIR/closure_wf_outlives.rs:52:12
539
|
5410
LL | T: 'static,
5511
| ^^^^^^^
@@ -58,7 +14,6 @@ help: consider adding an explicit lifetime bound...
5814
LL | type Opaque<T: 'static> = impl Sized;
5915
| +++++++++
6016

61-
error: aborting due to 3 previous errors
17+
error: aborting due to previous error
6218

63-
Some errors have detailed explanations: E0310, E0478, E0495.
64-
For more information about an error, try `rustc --explain E0310`.
19+
For more information about this error, try `rustc --explain E0310`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Regression test for #100267
2+
//
3+
// Previously the hidden type for Fut was `call::<'a, 'empty>::closure#0`,
4+
// which failed WF checks cecause of the bound `'b: 'a`.
5+
// Now we infer it to be `call::<'a, 'a>::closure#0`.
6+
//
7+
// Note that this is a pesky hack to workaround #100372.
8+
9+
// check-pass
10+
11+
#![feature(type_alias_impl_trait)]
12+
13+
type Fut<'a> = impl Sized;
14+
15+
fn call<'a, 'b>() -> Fut<'a>
16+
where
17+
'b: 'a,
18+
{
19+
|| {}
20+
}
21+
22+
fn main() {}

0 commit comments

Comments
 (0)