diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 95ea42b584a3a..412848ff3ed35 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -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, }); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 50af229baaaed..bf89f133de8c7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -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) } diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 94d5103286609..6d1ffe5eeefcc 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -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> { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 618da9e325325..140b3e6c40426 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -247,11 +247,24 @@ impl<'tcx> UniversalRegions<'tcx> { ) -> IndexVec> { 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); }); diff --git a/src/test/ui/nll/issue-98589-closures-relate-named-regions.rs b/src/test/ui/nll/issue-98589-closures-relate-named-regions.rs index 6cc4340bbd733..c0f336df58c6e 100644 --- a/src/test/ui/nll/issue-98589-closures-relate-named-regions.rs +++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.rs @@ -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() {} diff --git a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr index d8b26f0b0171e..1be73e36f85d4 100644 --- a/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr +++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -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` @@ -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`. diff --git a/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs index 53974dbb36bdf..e7d04f9908eb9 100644 --- a/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs +++ b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.rs @@ -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 @@ -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 @@ -36,7 +30,6 @@ mod test2 { } } -// fixed version of the above mod test2_fixed { type Opaque<'a: 'b, 'b> = impl Sized + 'a + 'b; diff --git a/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr index ae6462bb62ce5..eaa666923b19e 100644 --- a/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr +++ b/src/test/ui/type-alias-impl-trait/closure_wf_outlives.stderr @@ -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 = 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, | ^^^^^^^ @@ -58,7 +14,6 @@ help: consider adding an explicit lifetime bound... LL | type Opaque = 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`. diff --git a/src/test/ui/type-alias-impl-trait/issue-100267-closure-lifetime-capture.rs b/src/test/ui/type-alias-impl-trait/issue-100267-closure-lifetime-capture.rs new file mode 100644 index 0000000000000..9ad041a4778c3 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/issue-100267-closure-lifetime-capture.rs @@ -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() {}