1
Fork 0

When pretty printing, name placeholders as bound regions

This commit is contained in:
jackh726 2021-07-18 03:18:05 -04:00
parent eb0b95b55a
commit b9ee2fb6d8
8 changed files with 118 additions and 46 deletions

View file

@ -995,7 +995,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
let get_lifetimes = |sig| { let get_lifetimes = |sig| {
use rustc_hir::def::Namespace; use rustc_hir::def::Namespace;
let mut s = String::new(); 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) .name_all_regions(sig)
.unwrap(); .unwrap();
let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect(); let lts: Vec<String> = reg.into_iter().map(|(_, kind)| kind.to_string()).collect();

View file

@ -1776,13 +1776,73 @@ impl<F: fmt::Write> FmtPrinter<'_, '_, F> {
} }
} }
/// Folds through bound vars and placeholders, naming them
struct RegionFolder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
current_index: ty::DebruijnIndex,
region_map: BTreeMap<ty::BoundRegion, ty::Region<'tcx>>,
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<T: TypeFoldable<'tcx>>(
&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`, // HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`,
// `region_index` and `used_region_names`. // `region_index` and `used_region_names`.
impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> { impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
pub fn name_all_regions<T>( pub fn name_all_regions<T>(
mut self, mut self,
value: &ty::Binder<'tcx, T>, value: &ty::Binder<'tcx, T>,
) -> Result<(Self, (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)), fmt::Error> ) -> Result<(Self, T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>), fmt::Error>
where where
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{ {
@ -1805,16 +1865,16 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
let mut empty = true; let mut empty = true;
let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
write!( let w = if empty {
cx, empty = false;
"{}", start
if empty { } else {
empty = false; cont
start };
} else { let _ = write!(cx, "{}", w);
cont };
} let do_continue = |cx: &mut Self, cont: Symbol| {
) let _ = write!(cx, "{}", cont);
}; };
define_scoped_cx!(self); define_scoped_cx!(self);
@ -1824,18 +1884,18 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
// aren't named. Eventually, we might just want this as the default, but // 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 // this is not *quite* right and changes the ordering of some output
// anyways. // 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 // anon index + 1 (BrEnv takes 0) -> name
let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default(); let mut region_map: BTreeMap<u32, Symbol> = BTreeMap::default();
let bound_vars = value.bound_vars(); let bound_vars = value.bound_vars();
for var in bound_vars { for var in bound_vars {
match var { match var {
ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => { ty::BoundVariableKind::Region(ty::BrNamed(_, name)) => {
let _ = start_or_continue(&mut self, "for<", ", "); start_or_continue(&mut self, "for<", ", ");
let _ = write!(self, "{}", name); do_continue(&mut self, name);
} }
ty::BoundVariableKind::Region(ty::BrAnon(i)) => { ty::BoundVariableKind::Region(ty::BrAnon(i)) => {
let _ = start_or_continue(&mut self, "for<", ", "); start_or_continue(&mut self, "for<", ", ");
let name = loop { let name = loop {
let name = name_by_region_index(region_index); let name = name_by_region_index(region_index);
region_index += 1; region_index += 1;
@ -1843,11 +1903,11 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
break name; break name;
} }
}; };
let _ = write!(self, "{}", name); do_continue(&mut self, name);
region_map.insert(i + 1, name); region_map.insert(i + 1, name);
} }
ty::BoundVariableKind::Region(ty::BrEnv) => { ty::BoundVariableKind::Region(ty::BrEnv) => {
let _ = start_or_continue(&mut self, "for<", ", "); start_or_continue(&mut self, "for<", ", ");
let name = loop { let name = loop {
let name = name_by_region_index(region_index); let name = name_by_region_index(region_index);
region_index += 1; region_index += 1;
@ -1855,13 +1915,13 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
break name; break name;
} }
}; };
let _ = write!(self, "{}", name); do_continue(&mut self, name);
region_map.insert(0, name); region_map.insert(0, name);
} }
_ => continue, _ => continue,
} }
} }
start_or_continue(&mut self, "", "> ")?; start_or_continue(&mut self, "", "> ");
self.tcx.replace_late_bound_regions(value.clone(), |br| { self.tcx.replace_late_bound_regions(value.clone(), |br| {
let kind = match br.kind { let kind = match br.kind {
@ -1881,11 +1941,12 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
)) ))
}) })
} else { } else {
let new_value = self.tcx.replace_late_bound_regions(value.clone(), |br| { let tcx = self.tcx;
let _ = start_or_continue(&mut self, "for<", ", "); let mut name = |br: ty::BoundRegion| {
start_or_continue(&mut self, "for<", ", ");
let kind = match br.kind { let kind = match br.kind {
ty::BrNamed(_, name) => { ty::BrNamed(_, name) => {
let _ = write!(self, "{}", name); do_continue(&mut self, name);
br.kind br.kind
} }
ty::BrAnon(_) | ty::BrEnv => { ty::BrAnon(_) | ty::BrEnv => {
@ -1896,22 +1957,27 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
break name; break name;
} }
}; };
let _ = write!(self, "{}", name); do_continue(&mut self, name);
ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name)
} }
}; };
self.tcx.mk_region(ty::ReLateBound( tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { var: br.var, kind }))
ty::INNERMOST, };
ty::BoundRegion { var: br.var, kind }, let mut folder = RegionFolder {
)) tcx,
}); current_index: ty::INNERMOST,
start_or_continue(&mut self, "", "> ")?; name: &mut name,
new_value 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.binder_depth += 1;
self.region_index = region_index; self.region_index = region_index;
Ok((self, new_value)) Ok((self, new_value, map))
} }
pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error> pub fn pretty_in_binder<T>(self, value: &ty::Binder<'tcx, T>) -> Result<Self, fmt::Error>
@ -1919,8 +1985,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{ {
let old_region_index = self.region_index; let old_region_index = self.region_index;
let (new, new_value) = self.name_all_regions(value)?; let (new, new_value, _) = self.name_all_regions(value)?;
let mut inner = new_value.0.print(new)?; let mut inner = new_value.print(new)?;
inner.region_index = old_region_index; inner.region_index = old_region_index;
inner.binder_depth -= 1; inner.binder_depth -= 1;
Ok(inner) Ok(inner)
@ -1935,8 +2001,8 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>, T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{ {
let old_region_index = self.region_index; let old_region_index = self.region_index;
let (new, new_value) = self.name_all_regions(value)?; let (new, new_value, _) = self.name_all_regions(value)?;
let mut inner = f(&new_value.0, new)?; let mut inner = f(&new_value, new)?;
inner.region_index = old_region_index; inner.region_index = old_region_index;
inner.binder_depth -= 1; inner.binder_depth -= 1;
Ok(inner) Ok(inner)
@ -1960,6 +2026,12 @@ impl<F: fmt::Write> FmtPrinter<'_, 'tcx, F> {
debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r); debug!("LateBoundRegionNameCollector::visit_region(r: {:?}, address: {:p})", r, &r);
if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r { if let ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) = *r {
self.used_region_names.insert(name); 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) r.super_visit_with(self)
} }

View file

@ -11,7 +11,7 @@ where
} }
impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T { impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
//~^ ERROR the trait bound `<T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
type Item = T; type Item = T;
//~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref //~^ ERROR the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref
} }

View file

@ -14,16 +14,16 @@ LL | type Item = T;
<&T as Deref> <&T as Deref>
<&mut T as Deref> <&mut T as Deref>
error[E0277]: the trait bound `<T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied error[E0277]: the trait bound `for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref` is not satisfied
--> $DIR/hr-associated-type-projection-1.rs:13:33 --> $DIR/hr-associated-type-projection-1.rs:13:33
| |
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T { LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T {
| ^^^^^^^^^^^^^^^^^ the trait `Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item` | ^^^^^^^^^^^^^^^^^ the trait `for<'b> Deref` is not implemented for `<T as UnsafeCopy<'b, T>>::Item`
| |
help: consider further restricting the associated type help: consider further restricting the associated type
| |
LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where <T as UnsafeCopy<'b, T>>::Item: Deref { LL | impl<T: Copy + std::ops::Deref> UnsafeCopy<'_, T> for T where for<'b> <T as UnsafeCopy<'b, T>>::Item: Deref {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -5,7 +5,7 @@ LL | (&|_| ()) as &dyn for<'x> Fn(<u32 as T<'x>>::V);
| ^^------^ | ^^------^
| | | | | |
| | found signature of `fn(u16) -> _` | | found signature of `fn(u16) -> _`
| expected signature of `fn(<u32 as T<'x>>::V) -> _` | expected signature of `for<'x> fn(<u32 as T<'x>>::V) -> _`
| |
= note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)` = note: required for the cast to the object type `dyn for<'x> Fn(<u32 as T<'x>>::V)`

View file

@ -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 --> $DIR/coherence-fn-covariant-bound-vs-static.rs:17:1
| |
LL | impl Trait for for<'r> fn(fn(&'r ())) {} LL | impl Trait for for<'r> fn(fn(&'r ())) {}
| ------------------------------------- first implementation here | ------------------------------------- first implementation here
LL | impl<'a> Trait for fn(fn(&'a ())) {} 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 = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details

View file

@ -10,7 +10,7 @@ LL | {
LL | break_me::<Type, fn(_)>; LL | break_me::<Type, fn(_)>;
| ^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^
| | | |
| expected signature of `fn(<Type as Trait<'b>>::Assoc) -> _` | expected signature of `for<'b> fn(<Type as Trait<'b>>::Assoc) -> _`
| found signature of `fn(()) -> _` | found signature of `fn(()) -> _`
error: aborting due to previous error error: aborting due to previous error

View file

@ -10,7 +10,7 @@ LL | F: for<'a> FnMut(<T as Trait<'a>>::Item),
LL | foo((), drop) 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(()) -> _` | found signature of `fn(()) -> _`
error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time error[E0277]: the size for values of type `<() as Trait<'_>>::Item` cannot be known at compilation time