From f74d06c2d1f36f7fc7b99296d795cd578612b5a6 Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 3 Jul 2022 03:22:04 +0300 Subject: [PATCH 1/3] NLL: relate closure to parent fn --- compiler/rustc_borrowck/src/type_check/mod.rs | 22 +++++++ .../src/type_check/relate_tys.rs | 17 ++++++ ...sue-98589-closures-relate-named-regions.rs | 36 +++++++++++ ...98589-closures-relate-named-regions.stderr | 61 +++++++++++++++++++ 4 files changed, 136 insertions(+) create mode 100644 src/test/ui/nll/issue-98589-closures-relate-named-regions.rs create mode 100644 src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index f7d35da02597d..48cf7666f2c8d 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2619,6 +2619,28 @@ 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, + Locations::Single(location), + ConstraintCategory::BoringNoLocation, + ) { + bug!("we shouldn't error, this should only impose region constraints"); + } + 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 c45850c6d840f..7ccd5da6b9195 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -38,6 +38,23 @@ 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<()> { + let mut relation = TypeRelating::new( + self.infcx, + NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()), + ty::Variance::Invariant, + ); + ty::relate::relate_substs(&mut relation, a, b)?; + Ok(()) + } } struct NllTypeRelatingDelegate<'me, 'bccx, 'tcx> { 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 new file mode 100644 index 0000000000000..6cc4340bbd733 --- /dev/null +++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.rs @@ -0,0 +1,36 @@ +// Regression test for #98589. +// Previously, named lifetime `'a` that appears in the closure was unrelated to `'a` +// that appears in the parent function iff `'a` is early-bound. +// This made the following tests pass borrowck. + +// check-fail + +// The bound `'a: 'a` ensures that `'a` is early-bound. +fn test_early_early<'a: 'a, 'b: 'b>() { + || { None::<&'a &'b ()>; }; + //~^ ERROR lifetime may not live long enough +} + +fn test_early_late<'a: 'a, 'b>() { + || { None::<&'a &'b ()>; }; + //~^ ERROR lifetime may not live long enough +} + +// No early-bound lifetime; included for completeness. +fn test_late_late<'a, 'b>() { + || { None::<&'a &'b ()>; }; + //~^ ERROR lifetime may not live long enough +} + +fn test_early_type<'a: 'a, T>() { + || { None::<&'a T>; }; + //~^ ERROR the parameter type `T` may not live long enough +} + +// No early-bound lifetime; included for completeness. +fn test_late_type<'a, T>() { + || { None::<&'a T>; }; + //~^ ERROR the parameter type `T` may not live long enough +} + +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 new file mode 100644 index 0000000000000..6def5602e70b3 --- /dev/null +++ b/src/test/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -0,0 +1,61 @@ +error: lifetime may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:10:5 + | +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` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:15:10 + | +LL | fn test_early_late<'a: 'a, 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | || { None::<&'a &'b ()>; }; + | ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error: lifetime may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:21:10 + | +LL | fn test_late_late<'a, 'b>() { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | || { None::<&'a &'b ()>; }; + | ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:26:5 + | +LL | || { None::<&'a T>; }; + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_early_type<'a: 'a, T: 'a>() { + | ++++ + +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/issue-98589-closures-relate-named-regions.rs:32:5 + | +LL | || { None::<&'a T>; }; + | ^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds + | +help: consider adding an explicit lifetime bound... + | +LL | fn test_late_type<'a, T: 'a>() { + | ++++ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0309`. From 28f24ebe9f1f7a4d1df75b3b48197f022b2df46e Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Sun, 3 Jul 2022 19:56:51 +0300 Subject: [PATCH 2/3] fix rustdoc regression --- src/librustdoc/clean/auto_trait.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 5fe2c9ab4e37b..ef92629c24140 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -24,7 +24,10 @@ pub(crate) struct AutoTraitFinder<'a, 'tcx> { pub(crate) cx: &'a mut core::DocContext<'tcx>, } -impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { +impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> +where + 'tcx: 'a, // should be an implied bound; rustc bug #98852. +{ pub(crate) fn new(cx: &'a mut core::DocContext<'tcx>) -> Self { AutoTraitFinder { cx } } From 78adc0139cda567c1f3633137e70bd4b23106f4e Mon Sep 17 00:00:00 2001 From: Ali MJ Al-Nasrawy Date: Wed, 3 Aug 2022 12:46:04 +0300 Subject: [PATCH 3/3] cosmetic changes --- compiler/rustc_borrowck/src/type_check/mod.rs | 10 ++++++++-- compiler/rustc_borrowck/src/type_check/relate_tys.rs | 6 +++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 48cf7666f2c8d..d32b1edcd8fd7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2635,10 +2635,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(_) = self.eq_substs( typeck_root_substs, parent_substs, - Locations::Single(location), + location.to_locations(), ConstraintCategory::BoringNoLocation, ) { - bug!("we shouldn't error, this should only impose region constraints"); + 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 7ccd5da6b9195..c97a6a1a6587a 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -47,12 +47,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { locations: Locations, category: ConstraintCategory<'tcx>, ) -> Fallible<()> { - let mut relation = TypeRelating::new( + TypeRelating::new( self.infcx, NllTypeRelatingDelegate::new(self, locations, category, UniverseInfo::other()), ty::Variance::Invariant, - ); - ty::relate::relate_substs(&mut relation, a, b)?; + ) + .relate(a, b)?; Ok(()) } }