From e1f735a5d1d39cd1d609fe7708bd79639cfa0e64 Mon Sep 17 00:00:00 2001 From: b-naber Date: Thu, 29 Sep 2022 18:33:58 +0200 Subject: [PATCH 1/4] don't repeat lifetime names from outer binder in print --- compiler/rustc_middle/src/ty/print/pretty.rs | 69 ++++++++++++++++---- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index f69ac076820..ad76422ef66 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2055,7 +2055,14 @@ struct RegionFolder<'a, 'tcx> { tcx: TyCtxt<'tcx>, current_index: ty::DebruijnIndex, region_map: BTreeMap>, - name: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), + name: &'a mut ( + dyn FnMut( + Option, + ty::DebruijnIndex, + ty::BoundRegion, + ) -> ty::Region<'tcx> + + 'a + ), } impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { @@ -2086,7 +2093,9 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(_, br) => *self.region_map.entry(br).or_insert_with(|| name(br)), + ty::ReLateBound(db, br) => { + *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) + } ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => { // If this is an anonymous placeholder, don't rename. Otherwise, in some // async fns, we get a `for<'r> Send` bound @@ -2095,7 +2104,10 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { _ => { // Index doesn't matter, since this is just for naming and these never get bound let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind }; - *self.region_map.entry(br).or_insert_with(|| name(br)) + *self + .region_map + .entry(br) + .or_insert_with(|| name(None, self.current_index, br)) } } } @@ -2234,24 +2246,57 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { }) } else { let tcx = self.tcx; - let mut name = |br: ty::BoundRegion| { - start_or_continue(&mut self, "for<", ", "); - let kind = match br.kind { + let mut name = |db: Option, + binder_level: ty::DebruijnIndex, + br: ty::BoundRegion| { + let (name, kind) = match br.kind { ty::BrAnon(_) | ty::BrEnv => { let name = next_name(&self); - do_continue(&mut self, name); - ty::BrNamed(CRATE_DEF_ID.to_def_id(), name) + + if let Some(db) = db { + if db > binder_level { + let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); + return tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: br.var, kind }, + )); + } + } + + (name, ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)) } ty::BrNamed(def_id, kw::UnderscoreLifetime) => { let name = next_name(&self); - do_continue(&mut self, name); - ty::BrNamed(def_id, name) + + if let Some(db) = db { + if db > binder_level { + let kind = ty::BrNamed(def_id, name); + return tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: br.var, kind }, + )); + } + } + + (name, ty::BrNamed(def_id, name)) } ty::BrNamed(_, name) => { - do_continue(&mut self, name); - br.kind + if let Some(db) = db { + if db > binder_level { + let kind = br.kind; + return tcx.mk_region(ty::ReLateBound( + ty::INNERMOST, + ty::BoundRegion { var: br.var, kind }, + )); + } + } + + (name, br.kind) } }; + + start_or_continue(&mut self, "for<", ", "); + do_continue(&mut self, name); tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })) }; let mut folder = RegionFolder { From a8f17e3ad49090fd4b7c1301fbea6858453ecfb9 Mon Sep 17 00:00:00 2001 From: b-naber Date: Fri, 30 Sep 2022 14:21:17 +0200 Subject: [PATCH 2/4] bless tests --- .../issue-70935-complex-spans.drop_tracking.stderr | 2 +- .../coherence-fn-covariant-bound-vs-static.stderr | 4 ++-- src/test/ui/lifetimes/re-empty-in-error.stderr | 2 +- src/test/ui/regions/issue-102392.rs | 6 ++++++ src/test/ui/regions/issue-102392.stderr | 14 ++++++++++++++ .../higher-ranked-fn-type.quiet.stderr | 4 ++-- src/test/ui/where-clauses/higher-ranked-fn-type.rs | 2 +- 7 files changed, 27 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/regions/issue-102392.rs create mode 100644 src/test/ui/regions/issue-102392.stderr diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr index 85f7d1dd674..7fb88116665 100644 --- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr +++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr @@ -18,7 +18,7 @@ LL | async fn baz(_c: impl FnMut() -> T) where T: Future { | ___________________________________________________________________^ LL | | } | |_^ - = note: required because it captures the following types: `ResumeTy`, `impl for<'a, 'b, 'c> Future`, `()` + = note: required because it captures the following types: `ResumeTy`, `impl Future`, `()` note: required because it's used within this `async` block --> $DIR/issue-70935-complex-spans.rs:16:16 | diff --git a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr index cfcef9699f3..7dabd97b94e 100644 --- a/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr +++ b/src/test/ui/coherence/coherence-fn-covariant-bound-vs-static.stderr @@ -1,10 +1,10 @@ -error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(for<'r> fn(&'r ()))` +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(fn(&'r ()))` --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1 | LL | impl Trait for for<'r> fn(fn(&'r ())) {} | ------------------------------------- first implementation here LL | impl<'a> Trait for fn(fn(&'a ())) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(for<'r> fn(&'r ()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(fn(&'r ()))` | = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details diff --git a/src/test/ui/lifetimes/re-empty-in-error.stderr b/src/test/ui/lifetimes/re-empty-in-error.stderr index 840707d9470..c35d8ecec5e 100644 --- a/src/test/ui/lifetimes/re-empty-in-error.stderr +++ b/src/test/ui/lifetimes/re-empty-in-error.stderr @@ -4,7 +4,7 @@ error: higher-ranked lifetime error LL | foo(&10); | ^^^^^^^^ | - = note: could not prove `for<'b, 'a> &'b (): 'a` + = note: could not prove `for<'b> &'b (): 'a` error: aborting due to previous error diff --git a/src/test/ui/regions/issue-102392.rs b/src/test/ui/regions/issue-102392.rs new file mode 100644 index 00000000000..87cc1a8e7a8 --- /dev/null +++ b/src/test/ui/regions/issue-102392.rs @@ -0,0 +1,6 @@ +fn g(f: for<'a> fn(fn(&str, &'a str))) -> bool { + f + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/regions/issue-102392.stderr b/src/test/ui/regions/issue-102392.stderr new file mode 100644 index 00000000000..56f4c0c5db4 --- /dev/null +++ b/src/test/ui/regions/issue-102392.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/issue-102392.rs:2:5 + | +LL | fn g(f: for<'a> fn(fn(&str, &'a str))) -> bool { + | ---- expected `bool` because of return type +LL | f + | ^ expected `bool`, found fn pointer + | + = note: expected type `bool` + found fn pointer `for<'a> fn(for<'b> fn(&'b str, &'a str))` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr index d9950a3d9b7..30248a7a397 100644 --- a/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied +error[E0277]: the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied --> $DIR/higher-ranked-fn-type.rs:20:5 | LL | called() - | ^^^^^^ the trait `for<'b> Foo` is not implemented for `for<'b> fn(&'b ())` + | ^^^^^^ the trait `for<'b> Foo` is not implemented for `fn(&'b ())` | note: required by a bound in `called` --> $DIR/higher-ranked-fn-type.rs:12:25 diff --git a/src/test/ui/where-clauses/higher-ranked-fn-type.rs b/src/test/ui/where-clauses/higher-ranked-fn-type.rs index 0d8893e08d3..ab6edde4ee7 100644 --- a/src/test/ui/where-clauses/higher-ranked-fn-type.rs +++ b/src/test/ui/where-clauses/higher-ranked-fn-type.rs @@ -18,7 +18,7 @@ where (for<'a> fn(&'a ())): Foo, { called() - //[quiet]~^ ERROR the trait bound `for<'b> for<'b> fn(&'b ()): Foo` is not satisfied + //[quiet]~^ ERROR the trait bound `for<'b> fn(&'b ()): Foo` is not satisfied //[verbose]~^^ ERROR the trait bound `for<'b> fn(&ReLateBound( } From e83dcf4ecd678bac474d6aaca1cf0294bcbcd1b3 Mon Sep 17 00:00:00 2001 From: b-naber Date: Mon, 3 Oct 2022 17:37:22 +0200 Subject: [PATCH 3/4] re-name params + add comments --- compiler/rustc_middle/src/ty/print/pretty.rs | 26 ++++++++++++-------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ad76422ef66..b78661270e1 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2057,8 +2057,8 @@ struct RegionFolder<'a, 'tcx> { region_map: BTreeMap>, name: &'a mut ( dyn FnMut( - Option, - ty::DebruijnIndex, + Option, // Debruijn index of the folded late-bound region + ty::DebruijnIndex, // Index corresponding to binder level ty::BoundRegion, ) -> ty::Region<'tcx> + 'a @@ -2246,15 +2246,21 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { }) } else { let tcx = self.tcx; - let mut name = |db: Option, - binder_level: ty::DebruijnIndex, + + // Closure used in `RegionFolder` to create names for anonymous late-bound + // regions. We use two `DebruijnIndex`es (one for the currently folded + // late-bound region and the other for the binder level) to determine + // whether a name has already been created for the currently folded region, + // see issue #102392. + let mut name = |lifetime_idx: Option, + binder_level_idx: ty::DebruijnIndex, br: ty::BoundRegion| { let (name, kind) = match br.kind { ty::BrAnon(_) | ty::BrEnv => { let name = next_name(&self); - if let Some(db) = db { - if db > binder_level { + if let Some(lt_idx) = lifetime_idx { + if lt_idx > binder_level_idx { let kind = ty::BrNamed(CRATE_DEF_ID.to_def_id(), name); return tcx.mk_region(ty::ReLateBound( ty::INNERMOST, @@ -2268,8 +2274,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { ty::BrNamed(def_id, kw::UnderscoreLifetime) => { let name = next_name(&self); - if let Some(db) = db { - if db > binder_level { + if let Some(lt_idx) = lifetime_idx { + if lt_idx > binder_level_idx { let kind = ty::BrNamed(def_id, name); return tcx.mk_region(ty::ReLateBound( ty::INNERMOST, @@ -2281,8 +2287,8 @@ impl<'tcx> FmtPrinter<'_, 'tcx> { (name, ty::BrNamed(def_id, name)) } ty::BrNamed(_, name) => { - if let Some(db) = db { - if db > binder_level { + if let Some(lt_idx) = lifetime_idx { + if lt_idx > binder_level_idx { let kind = br.kind; return tcx.mk_region(ty::ReLateBound( ty::INNERMOST, From 048e637e9ee4c9fe8813109d89f97e140776b0a4 Mon Sep 17 00:00:00 2001 From: b-naber Date: Sat, 8 Oct 2022 15:52:59 +0200 Subject: [PATCH 4/4] handle late-bound vars from inner binders correctly and add test --- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- src/test/ui/lifetimes/nested-binder-print.rs | 10 ++++++++++ src/test/ui/lifetimes/nested-binder-print.stderr | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/lifetimes/nested-binder-print.rs create mode 100644 src/test/ui/lifetimes/nested-binder-print.stderr diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b78661270e1..659bd884556 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2093,7 +2093,7 @@ impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { let name = &mut self.name; let region = match *r { - ty::ReLateBound(db, br) => { + ty::ReLateBound(db, br) if db >= self.current_index => { *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br)) } ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => { diff --git a/src/test/ui/lifetimes/nested-binder-print.rs b/src/test/ui/lifetimes/nested-binder-print.rs new file mode 100644 index 00000000000..f97f349fd82 --- /dev/null +++ b/src/test/ui/lifetimes/nested-binder-print.rs @@ -0,0 +1,10 @@ +struct TwoLt<'a, 'b>(&'a (), &'b ()); +type Foo<'a> = fn(TwoLt<'_, 'a>); + +fn foo() { + let y: for<'a> fn(Foo<'a>); + let x: u32 = y; + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/lifetimes/nested-binder-print.stderr b/src/test/ui/lifetimes/nested-binder-print.stderr new file mode 100644 index 00000000000..32dd896932d --- /dev/null +++ b/src/test/ui/lifetimes/nested-binder-print.stderr @@ -0,0 +1,14 @@ +error[E0308]: mismatched types + --> $DIR/nested-binder-print.rs:6:18 + | +LL | let x: u32 = y; + | --- ^ expected `u32`, found fn pointer + | | + | expected due to this + | + = note: expected type `u32` + found fn pointer `for<'a> fn(for<'b> fn(TwoLt<'b, 'a>))` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.