Skip to content

Commit

Permalink
don't touch closure_substs.parent_substs()
Browse files Browse the repository at this point in the history
... They bite!
  • Loading branch information
aliemjay authored and jackh726 committed Nov 7, 2022
1 parent 1e1e5b8 commit 4f32381
Show file tree
Hide file tree
Showing 9 changed files with 67 additions and 109 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.iter()
.find(|ur_vid| self.eval_equal(vid, **ur_vid))
.and_then(|ur_vid| self.definitions[*ur_vid].external_name)
// FIXME: This is a troublesome back-compat hack. See #100372.
.unwrap_or(infcx.tcx.lifetimes.re_erased),
_ => region,
});
Expand Down
28 changes: 0 additions & 28 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2669,34 +2669,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
);
}

// Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589.
let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id);

let parent_substs = match tcx.def_kind(def_id) {
DefKind::Closure => substs.as_closure().parent_substs(),
DefKind::Generator => substs.as_generator().parent_substs(),
DefKind::InlineConst => substs.as_inline_const().parent_substs(),
other => bug!("unexpected item {:?}", other),
};
let parent_substs = tcx.mk_substs(parent_substs.iter());

assert_eq!(typeck_root_substs.len(), parent_substs.len());
if let Err(_) = self.eq_substs(
typeck_root_substs,
parent_substs,
location.to_locations(),
ConstraintCategory::BoringNoLocation,
) {
span_mirbug!(
self,
def_id,
"could not relate closure to parent {:?} != {:?}",
typeck_root_substs,
parent_substs
);
}

tcx.predicates_of(def_id).instantiate(tcx, substs)
}

Expand Down
17 changes: 0 additions & 17 deletions compiler/rustc_borrowck/src/type_check/relate_tys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,23 +38,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
.relate(a, b)?;
Ok(())
}

/// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types].
pub(super) fn eq_substs(
&mut self,
a: ty::SubstsRef<'tcx>,
b: ty::SubstsRef<'tcx>,
locations: Locations,
category: ConstraintCategory<'tcx>,
) -> Fallible<()> {
TypeRelating::new(
self.infcx,
NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()),
ty::Variance::Invariant,
)
.relate(a, b)?;
Ok(())
}
}

struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> {
Expand Down
17 changes: 15 additions & 2 deletions compiler/rustc_borrowck/src/universal_regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,11 +247,24 @@ impl<'tcx> UniversalRegions<'tcx> {
) -> IndexVec<RegionVid, ty::Region<'tcx>> {
let mut region_mapping = IndexVec::with_capacity(expected_num_vars);
region_mapping.push(tcx.lifetimes.re_static);

let typeck_root_def_id = tcx.local_parent(closure_def_id);

// We rely on the fact that the first N regions in the ClosureSubsts are
// inherited from the `typeck_root_def_id`.
let typeck_root_substs =
ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id.to_def_id());
assert_eq!(closure_substs.regions().count(), typeck_root_substs.regions().count());

// The first N regions in ClosureSubsts are the early-bound regions of `typeck_root_*`.
// Other regions are the early-bound regions in closure signature, upvars, etc.
let mut typeck_root_regions = typeck_root_substs.regions().fuse();
tcx.for_each_free_region(&closure_substs, |fr| {
region_mapping.push(fr);
region_mapping.push(typeck_root_regions.next().unwrap_or(fr));
});

for_each_late_bound_region_in_recursive_scope(tcx, tcx.local_parent(closure_def_id), |r| {
// Now add late-bound regions of `typeck_root_def_id`.
for_each_late_bound_region_in_recursive_scope(tcx, typeck_root_def_id, |r| {
region_mapping.push(r);
});

Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/nll/issue-98589-closures-relate-named-regions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,10 @@ fn test_late_type<'a, T>() {
//~^ ERROR the parameter type `T` may not live long enough
}

fn test_closure_arg<'a: 'a>() {
let f = |_: &'a str| {};
f(&String::new());
//~^ ERROR temporary value dropped while borrowed
}

fn main() {}
21 changes: 17 additions & 4 deletions src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
error: lifetime may not live long enough
--> $DIR/issue-98589-closures-relate-named-regions.rs:10:5
--> $DIR/issue-98589-closures-relate-named-regions.rs:10:10
|
LL | fn test_early_early<'a: 'a, 'b: 'b>() {
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
LL | || { None::<&'a &'b ()>; };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
|
= help: consider adding the following bound: `'b: 'a`

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

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

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0309`.
Some errors have detailed explanations: E0309, E0716.
For more information about an error, try `rustc --explain E0309`.
11 changes: 2 additions & 9 deletions src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
// If the hidden type is a closure, we require the "outlives" bounds that appear on the
// defining site to also appear on the opaque type.
//
// It's not clear if this is the desired behavior but at least
// it's consistent and has no back-compat risk.
// If the hidden type is a closure, we used to require the "outlives" bounds
// that appear on the defining site to also appear on the opaque type.

// check-fail

#![feature(type_alias_impl_trait)]
#![allow(dead_code)]

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

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

fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
where
Expand All @@ -36,7 +30,6 @@ mod test2 {
}
}

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

Expand Down
53 changes: 4 additions & 49 deletions src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr
Original file line number Diff line number Diff line change
@@ -1,55 +1,11 @@
error[E0478]: lifetime bound not satisfied
--> $DIR/closure_wf_outlives.rs:14:27
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^^^^^^^^^^^^^^^^^^^
|
note: lifetime parameter instantiated with the lifetime `'a` as defined here
--> $DIR/closure_wf_outlives.rs:14:17
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^
note: but lifetime parameter must outlive the lifetime `'b` as defined here
--> $DIR/closure_wf_outlives.rs:14:21
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/closure_wf_outlives.rs:27:27
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
--> $DIR/closure_wf_outlives.rs:27:17
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^
note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/closure_wf_outlives.rs:27:27
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^^^^^^^^^^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'b` as defined here...
--> $DIR/closure_wf_outlives.rs:27:21
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^
note: ...so that the declared lifetime parameter bounds are satisfied
--> $DIR/closure_wf_outlives.rs:27:27
|
LL | type Opaque<'a, 'b> = impl Sized + 'a + 'b;
| ^^^^^^^^^^^^^^^^^^^^

error[E0310]: the parameter type `T` may not live long enough
--> $DIR/closure_wf_outlives.rs:54:22
--> $DIR/closure_wf_outlives.rs:47:22
|
LL | type Opaque<T> = impl Sized;
| ^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds...
|
note: ...that is required by this bound
--> $DIR/closure_wf_outlives.rs:59:12
--> $DIR/closure_wf_outlives.rs:52:12
|
LL | T: 'static,
| ^^^^^^^
Expand All @@ -58,7 +14,6 @@ help: consider adding an explicit lifetime bound...
LL | type Opaque<T: 'static> = impl Sized;
| +++++++++

error: aborting due to 3 previous errors
error: aborting due to previous error

Some errors have detailed explanations: E0310, E0478, E0495.
For more information about an error, try `rustc --explain E0310`.
For more information about this error, try `rustc --explain E0310`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Regression test for #100267
//
// Previously the hidden type for Fut was `call::<'a, 'empty>::closure#0`,
// which failed WF checks cecause of the bound `'b: 'a`.
// Now we infer it to be `call::<'a, 'a>::closure#0`.
//
// Note that this is a pesky hack to workaround #100372.

// check-pass

#![feature(type_alias_impl_trait)]

type Fut<'a> = impl Sized;

fn call<'a, 'b>() -> Fut<'a>
where
'b: 'a,
{
|| {}
}

fn main() {}

0 comments on commit 4f32381

Please sign in to comment.