diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index e3a79fe265330..75b1d78dac4d0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -995,7 +995,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let get_lifetimes = |sig| { use rustc_hir::def::Namespace; let mut s = String::new(); - let (_, (sig, reg)) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS) + let (_, sig, reg) = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS) .name_all_regions(sig) .unwrap(); let lts: Vec = reg.into_iter().map(|(_, kind)| kind.to_string()).collect(); diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6dfbd28f7763b..b5733bd2edc2e 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1776,13 +1776,73 @@ impl FmtPrinter<'_, '_, F> { } } +/// Folds through bound vars and placeholders, naming them +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), +} + +impl<'a, 'tcx> ty::TypeFolder<'tcx> for RegionFolder<'a, 'tcx> { + fn tcx<'b>(&'b self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_binder>( + &mut self, + t: ty::Binder<'tcx, T>, + ) -> ty::Binder<'tcx, T> { + self.current_index.shift_in(1); + let t = t.super_fold_with(self); + self.current_index.shift_out(1); + t + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match *t.kind() { + _ if t.has_vars_bound_at_or_above(self.current_index) || t.has_placeholders() => { + return t.super_fold_with(self); + } + _ => {} + } + t + } + + 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::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 + match kind { + ty::BrAnon(_) | ty::BrEnv => r, + _ => { + // 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)) + } + } + } + _ => return r, + }; + if let ty::ReLateBound(debruijn1, br) = *region { + assert_eq!(debruijn1, ty::INNERMOST); + self.tcx.mk_region(ty::ReLateBound(self.current_index, br)) + } else { + region + } + } +} + // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, // `region_index` and `used_region_names`. impl FmtPrinter<'_, 'tcx, F> { pub fn name_all_regions( mut self, value: &ty::Binder<'tcx, T>, - ) -> Result<(Self, (T, BTreeMap>)), fmt::Error> + ) -> Result<(Self, T, BTreeMap>), fmt::Error> where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { @@ -1805,16 +1865,16 @@ impl FmtPrinter<'_, 'tcx, F> { let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - write!( - cx, - "{}", - if empty { - empty = false; - start - } else { - cont - } - ) + let w = if empty { + empty = false; + start + } else { + cont + }; + let _ = write!(cx, "{}", w); + }; + let do_continue = |cx: &mut Self, cont: Symbol| { + let _ = write!(cx, "{}", cont); }; define_scoped_cx!(self); @@ -1824,18 +1884,18 @@ impl FmtPrinter<'_, 'tcx, F> { // aren't named. Eventually, we might just want this as the default, but // this is not *quite* right and changes the ordering of some output // anyways. - let new_value = if self.tcx().sess.verbose() { + let (new_value, map) = if self.tcx().sess.verbose() { // anon index + 1 (BrEnv takes 0) -> name let mut region_map: BTreeMap = BTreeMap::default(); let bound_vars = value.bound_vars(); for var in bound_vars { match var { ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => { - let _ = start_or_continue(&mut self, "for<", ", "); - let _ = write!(self, "{}", name); + start_or_continue(&mut self, "for<", ", "); + do_continue(&mut self, name); } ty::BoundVariableKind::Region(ty::BrAnon(i)) => { - let _ = start_or_continue(&mut self, "for<", ", "); + start_or_continue(&mut self, "for<", ", "); let name = loop { let name = name_by_region_index(region_index); region_index += 1; @@ -1843,11 +1903,11 @@ impl FmtPrinter<'_, 'tcx, F> { break name; } }; - let _ = write!(self, "{}", name); + do_continue(&mut self, name); region_map.insert(i + 1, name); } ty::BoundVariableKind::Region(ty::BrEnv) => { - let _ = start_or_continue(&mut self, "for<", ", "); + start_or_continue(&mut self, "for<", ", "); let name = loop { let name = name_by_region_index(region_index); region_index += 1; @@ -1855,13 +1915,13 @@ impl FmtPrinter<'_, 'tcx, F> { break name; } }; - let _ = write!(self, "{}", name); + do_continue(&mut self, name); region_map.insert(0, name); } _ => continue, } } - start_or_continue(&mut self, "", "> ")?; + start_or_continue(&mut self, "", "> "); self.tcx.replace_late_bound_regions(value.clone(), |br| { let kind = match br.kind { @@ -1881,11 +1941,12 @@ impl FmtPrinter<'_, 'tcx, F> { )) }) } else { - let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { - let _ = start_or_continue(&mut self, "for<", ", "); + let tcx = self.tcx; + let mut name = |br: ty::BoundRegion| { + start_or_continue(&mut self, "for<", ", "); let kind = match br.kind { ty::BrNamed(_, name) => { - let _ = write!(self, "{}", name); + do_continue(&mut self, name); br.kind } ty::BrAnon(_) | ty::BrEnv => { @@ -1896,22 +1957,27 @@ impl FmtPrinter<'_, 'tcx, F> { break name; } }; - let _ = write!(self, "{}", name); + do_continue(&mut self, name); ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) } }; - self.tcx.mk_region(ty::ReLateBound( - ty::INNERMOST, - ty::BoundRegion { var: br.var, kind }, - )) - }); - start_or_continue(&mut self, "", "> ")?; - new_value + tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind })) + }; + let mut folder = RegionFolder { + tcx, + current_index: ty::INNERMOST, + name: &mut name, + region_map: BTreeMap::new(), + }; + let new_value = value.clone().skip_binder().fold_with(&mut folder); + let region_map = folder.region_map; + start_or_continue(&mut self, "", "> "); + (new_value, region_map) }; self.binder_depth += 1; self.region_index = region_index; - Ok((self, new_value)) + Ok((self, new_value, map)) } pub fn pretty_in_binder(self, value: &ty::Binder<'tcx, T>) -> Result @@ -1919,8 +1985,8 @@ impl FmtPrinter<'_, 'tcx, F> { T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { let old_region_index = self.region_index; - let (new, new_value) = self.name_all_regions(value)?; - let mut inner = new_value.0.print(new)?; + let (new, new_value, _) = self.name_all_regions(value)?; + let mut inner = new_value.print(new)?; inner.region_index = old_region_index; inner.binder_depth -= 1; Ok(inner) @@ -1935,8 +2001,8 @@ impl FmtPrinter<'_, 'tcx, F> { T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, { let old_region_index = self.region_index; - let (new, new_value) = self.name_all_regions(value)?; - let mut inner = f(&new_value.0, new)?; + let (new, new_value, _) = self.name_all_regions(value)?; + let mut inner = f(&new_value, new)?; inner.region_index = old_region_index; inner.binder_depth -= 1; Ok(inner) @@ -1960,6 +2026,12 @@ impl FmtPrinter<'_, 'tcx, F> { debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r); if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { self.used_region_names.insert(name); + } else if let ty::RePlaceholder(ty::PlaceholderRegion { + name: ty::BrNamed(_, name), + .. + }) = *r + { + self.used_region_names.insert(name); } r.super_visit_with(self) } diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.rs b/src/test/ui/associated-types/hr-associated-type-projection-1.rs index 1270cd6706aef..bad736b64c038 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.rs +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.rs @@ -11,7 +11,7 @@ where } impl UnsafeCopy<'_, T> for T { - //~^ ERROR the trait bound `>::Item: Deref` is not satisfied + //~^ ERROR the trait bound `for<'b> >::Item: Deref` is not satisfied type Item = T; //~^ ERROR the trait bound `for<'b> >::Item: Deref } diff --git a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr index cf4ec0babfc21..49fad4e1b1cb8 100644 --- a/src/test/ui/associated-types/hr-associated-type-projection-1.stderr +++ b/src/test/ui/associated-types/hr-associated-type-projection-1.stderr @@ -14,16 +14,16 @@ LL | type Item = T; <&T as Deref> <&mut T as Deref> -error[E0277]: the trait bound `>::Item: Deref` is not satisfied +error[E0277]: the trait bound `for<'b> >::Item: Deref` is not satisfied --> $DIR/hr-associated-type-projection-1.rs:13:33 | LL | impl UnsafeCopy<'_, T> for T { - | ^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `>::Item` + | ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `>::Item` | help: consider further restricting the associated type | -LL | impl UnsafeCopy<'_, T> for T where >::Item: Deref { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl UnsafeCopy<'_, T> for T where for<'b> >::Item: Deref { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/closures/issue-41366.stderr b/src/test/ui/closures/issue-41366.stderr index 72ef5b3b962c7..ffe0bce6f0fd8 100644 --- a/src/test/ui/closures/issue-41366.stderr +++ b/src/test/ui/closures/issue-41366.stderr @@ -5,7 +5,7 @@ LL | (&|_| ()) as &dyn for<'x> Fn(>::V); | ^^------^ | | | | | found signature of `fn(u16) -> _` - | expected signature of `fn(>::V) -> _` + | expected signature of `for<'x> fn(>::V) -> _` | = note: required for the cast to the object type `dyn for<'x> Fn(>::V)` 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 7dabd97b94e82..cfcef9699f372 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(fn(&'r ()))` +error[E0119]: conflicting implementations of trait `Trait` for type `for<'r> fn(for<'r> 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(fn(&'r ()))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `for<'r> fn(for<'r> 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/issues/issue-43623.stderr b/src/test/ui/issues/issue-43623.stderr index 80aca482b3d29..4bc5eb03e922c 100644 --- a/src/test/ui/issues/issue-43623.stderr +++ b/src/test/ui/issues/issue-43623.stderr @@ -10,7 +10,7 @@ LL | { LL | break_me::; | ^^^^^^^^^^^^^^^^^^^^^^^ | | - | expected signature of `fn(>::Assoc) -> _` + | expected signature of `for<'b> fn(>::Assoc) -> _` | found signature of `fn(()) -> _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-60283.stderr b/src/test/ui/issues/issue-60283.stderr index 650570b6471eb..149562f8fb31c 100644 --- a/src/test/ui/issues/issue-60283.stderr +++ b/src/test/ui/issues/issue-60283.stderr @@ -10,7 +10,7 @@ LL | F: for<'a> FnMut(>::Item), LL | foo((), drop) | ^^^^ | | - | expected signature of `fn(<() as Trait<'a>>::Item) -> _` + | expected signature of `for<'a> fn(<() as Trait<'a>>::Item) -> _` | found signature of `fn(()) -> _` error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time