Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't duplicate region names for late-bound regions in print of Binder #101996

Merged
merged 3 commits into from
Sep 26, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 54 additions & 27 deletions compiler/rustc_middle/src/ty/print/pretty.rs
Original file line number Diff line number Diff line change
@@ -1562,7 +1562,9 @@ pub struct FmtPrinterData<'a, 'tcx> {
in_value: bool,
pub print_alloc_ids: bool,

// set of all named (non-anonymous) region names
used_region_names: FxHashSet<Symbol>,

region_index: usize,
binder_depth: usize,
printed_type_count: usize,
@@ -2118,23 +2120,31 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
where
T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx>,
{
fn name_by_region_index(index: usize) -> Symbol {
match index {
0 => Symbol::intern("'r"),
1 => Symbol::intern("'s"),
i => Symbol::intern(&format!("'t{}", i - 2)),
fn name_by_region_index(
index: usize,
available_names: &mut Vec<Symbol>,
num_available: usize,
) -> Symbol {
if let Some(name) = available_names.pop() {
name
} else {
Symbol::intern(&format!("'z{}", index - num_available))
}
}

debug!("name_all_regions");

// Replace any anonymous late-bound regions with named
// variants, using new unique identifiers, so that we can
// clearly differentiate between named and unnamed regions in
// the output. We'll probably want to tweak this over time to
// decide just how much information to give.
if self.binder_depth == 0 {
self.prepare_late_bound_region_info(value);
self.prepare_region_info(value);
}

debug!("self.used_region_names: {:?}", &self.used_region_names);

let mut empty = true;
let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
let w = if empty {
@@ -2151,13 +2161,24 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {

define_scoped_cx!(self);

let possible_names =
('a'..='z').rev().map(|s| Symbol::intern(&format!("'{s}"))).collect::<Vec<_>>();

let mut available_names = possible_names
.into_iter()
.filter(|name| !self.used_region_names.contains(&name))
.collect::<Vec<_>>();
debug!(?available_names);
let num_available = available_names.len();

let mut region_index = self.region_index;
let mut next_name = |this: &Self| loop {
let name = name_by_region_index(region_index);
let mut next_name = |this: &Self| {
let name = name_by_region_index(region_index, &mut available_names, num_available);
debug!(?name);
region_index += 1;
if !this.used_region_names.contains(&name) {
break name;
}
assert!(!this.used_region_names.contains(&name));

name
};

// If we want to print verbosely, then print *all* binders, even if they
@@ -2178,6 +2199,7 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
ty::BrAnon(_) | ty::BrEnv => {
start_or_continue(&mut self, "for<", ", ");
let name = next_name(&self);
debug!(?name);
do_continue(&mut self, name);
ty::BrNamed(CRATE_DEF_ID.to_def_id(), name)
}
@@ -2271,29 +2293,37 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
Ok(inner)
}

fn prepare_late_bound_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
fn prepare_region_info<T>(&mut self, value: &ty::Binder<'tcx, T>)
where
T: TypeVisitable<'tcx>,
{
struct LateBoundRegionNameCollector<'a, 'tcx> {
used_region_names: &'a mut FxHashSet<Symbol>,
struct RegionNameCollector<'tcx> {
used_region_names: FxHashSet<Symbol>,
type_collector: SsoHashSet<Ty<'tcx>>,
}

impl<'tcx> ty::visit::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
impl<'tcx> RegionNameCollector<'tcx> {
fn new() -> Self {
RegionNameCollector {
used_region_names: Default::default(),
type_collector: SsoHashSet::new(),
}
}
}

impl<'tcx> ty::visit::TypeVisitor<'tcx> for RegionNameCollector<'tcx> {
type BreakTy = ();

fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
trace!("address: {:p}", r.0.0);
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
{

// Collect all named lifetimes. These allow us to prevent duplication
// of already existing lifetime names when introducing names for
// anonymous late-bound regions.
if let Some(name) = r.get_name() {
self.used_region_names.insert(name);
}

r.super_visit_with(self)
}

@@ -2309,12 +2339,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
}
}

self.used_region_names.clear();
let mut collector = LateBoundRegionNameCollector {
used_region_names: &mut self.used_region_names,
type_collector: SsoHashSet::new(),
};
let mut collector = RegionNameCollector::new();
value.visit_with(&mut collector);
self.used_region_names = collector.used_region_names;
self.region_index = 0;
}
}
28 changes: 28 additions & 0 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -85,6 +85,17 @@ impl BoundRegionKind {
_ => false,
}
}

pub fn get_name(&self) -> Option<Symbol> {
if self.is_named() {
match *self {
BoundRegionKind::BrNamed(_, name) => return Some(name),
_ => unreachable!(),
}
}

None
}
}

pub trait Article {
@@ -1445,6 +1456,23 @@ impl<'tcx> Region<'tcx> {
*self.0.0
}

pub fn get_name(self) -> Option<Symbol> {
if self.has_name() {
let name = match *self {
ty::ReEarlyBound(ebr) => Some(ebr.name),
ty::ReLateBound(_, br) => br.kind.get_name(),
ty::ReFree(fr) => fr.bound_region.get_name(),
ty::ReStatic => Some(kw::StaticLifetime),
ty::RePlaceholder(placeholder) => placeholder.name.get_name(),
_ => None,
};

return name;
}

None
}

/// Is this region named by the user?
pub fn has_name(self) -> bool {
match *self {
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@
_2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
// mir::Constant
// + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9
// + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
}

bb1: {
@@ -37,7 +37,7 @@
- _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- // mir::Constant
- // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11
- // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
- // + literal: Const { ty: for<'a> fn(&'a u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
+ _6 = _7; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ _5 = (*_6); // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+ goto -> bb2; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
@@ -53,7 +53,7 @@
- _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- // mir::Constant
- // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16
- // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
- // + literal: Const { ty: for<'a> fn(&'a [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
+ _9 = _10; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ _8 = (*_9); // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+ goto -> bb3; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:44
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:9:36: 9:42
// + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
}

bb1: {
Original file line number Diff line number Diff line change
@@ -35,7 +35,7 @@
_0 = core::slice::<impl [&i32]>::as_ptr(move _1) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/const-promotion-extern-static.rs:+0:31: +0:55
// mir::Constant
// + span: $DIR/const-promotion-extern-static.rs:13:47: 13:53
// + literal: Const { ty: for<'r> fn(&'r [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a [&i32]) -> *const &i32 {core::slice::<impl [&i32]>::as_ptr}, val: Value(<ZST>) }
}

bb1: {
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
_2 = core::str::<impl str>::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
// mir::Constant
// + span: $DIR/deduplicate_blocks.rs:5:13: 5:21
// + literal: Const { ty: for<'r> fn(&'r str) -> &'r [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
}

bb1: {
2 changes: 1 addition & 1 deletion src/test/mir-opt/derefer_complex_case.main.Derefer.diff
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@
_7 = <std::slice::Iter<'_, i32> as Iterator>::next(move _8) -> bb3; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
// mir::Constant
// + span: $DIR/derefer_complex_case.rs:6:17: 6:26
// + literal: Const { ty: for<'r> fn(&'r mut std::slice::Iter<'_, i32>) -> Option<<std::slice::Iter<'_, i32> as Iterator>::Item> {<std::slice::Iter<'_, i32> as Iterator>::next}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a mut std::slice::Iter<'_, i32>) -> Option<<std::slice::Iter<'_, i32> as Iterator>::Item> {<std::slice::Iter<'_, i32> as Iterator>::next}, val: Value(<ZST>) }
}

bb3: {
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
- // MIR for `nrvo` before DestinationPropagation
+ // MIR for `nrvo` after DestinationPropagation

fn nrvo(_1: for<'r> fn(&'r mut [u8; 1024])) -> [u8; 1024] {
fn nrvo(_1: for<'a> fn(&'a mut [u8; 1024])) -> [u8; 1024] {
debug init => _1; // in scope 0 at $DIR/simple.rs:+0:9: +0:13
let mut _0: [u8; 1024]; // return place in scope 0 at $DIR/simple.rs:+0:39: +0:49
let mut _2: [u8; 1024]; // in scope 0 at $DIR/simple.rs:+1:9: +1:16
let _3: (); // in scope 0 at $DIR/simple.rs:+2:5: +2:19
let mut _4: for<'r> fn(&'r mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9
let mut _4: for<'a> fn(&'a mut [u8; 1024]); // in scope 0 at $DIR/simple.rs:+2:5: +2:9
let mut _5: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18
let mut _6: &mut [u8; 1024]; // in scope 0 at $DIR/simple.rs:+2:10: +2:18
scope 1 {
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@
_4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
// mir::Constant
// + span: $DIR/funky_arms.rs:15:26: 15:35
// + literal: Const { ty: for<'r> fn(&'r Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value(<ZST>) }
}

bb1: {
@@ -69,7 +69,7 @@
_7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
// mir::Constant
// + span: $DIR/funky_arms.rs:24:34: 24:43
// + literal: Const { ty: for<'r> fn(&'r Formatter<'_>) -> Option<usize> {Formatter::<'_>::precision}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> Option<usize> {Formatter::<'_>::precision}, val: Value(<ZST>) }
}

bb5: {
@@ -100,7 +100,7 @@
_0 = float_to_exponential_common_exact::<T>(move _11, move _12, move _13, move _14, move _17) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
// mir::Constant
// + span: $DIR/funky_arms.rs:26:9: 26:42
// + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) }
}

bb7: {
@@ -125,7 +125,7 @@
_0 = float_to_exponential_common_shortest::<T>(move _18, move _19, move _20, move _21) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
// mir::Constant
// + span: $DIR/funky_arms.rs:28:9: 28:45
// + literal: Const { ty: for<'r, 's, 't0> fn(&'r mut Formatter<'s>, &'t0 T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) }
}

bb9: {
2 changes: 1 addition & 1 deletion src/test/mir-opt/inline/cycle.f.Inline.diff
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
_2 = <impl Fn() as Fn<()>>::call(move _3, move _4) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/cycle.rs:+1:5: +1:8
// mir::Constant
// + span: $DIR/cycle.rs:6:5: 6:6
// + literal: Const { ty: for<'r> extern "rust-call" fn(&'r impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(), ()) -> <impl Fn() as FnOnce<()>>::Output {<impl Fn() as Fn<()>>::call}, val: Value(<ZST>) }
}

bb1: {
6 changes: 3 additions & 3 deletions src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@
// mir::Constant
// + span: $DIR/dyn-trait.rs:33:13: 33:21
// + user_ty: UserType(0)
// + literal: Const { ty: for<'r> fn(&'r T) -> &'r <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a T) -> &'a <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) }
}

bb1: {
@@ -46,9 +46,9 @@
+ _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22
// mir::Constant
- // + span: $DIR/dyn-trait.rs:34:5: 34:22
- // + literal: Const { ty: for<'r> fn(&'r <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
- // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
+ // + span: $DIR/dyn-trait.rs:21:7: 21:20
+ // + literal: Const { ty: for<'r> fn(&'r dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
}

bb2: {
2 changes: 1 addition & 1 deletion src/test/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
_0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:22
// mir::Constant
// + span: $DIR/dyn-trait.rs:21:7: 21:20
// + literal: Const { ty: for<'r> fn(&'r dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) }
// + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) }
}

bb1: {
Original file line number Diff line number Diff line change
@@ -23,9 +23,9 @@
+ _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22
// mir::Constant
- // + span: $DIR/dyn-trait.rs:27:5: 27:13
- // + literal: Const { ty: for<'r> fn(&'r (dyn Cache<V = <C as Cache>::V> + 'r)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
- // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
+ // + span: $DIR/dyn-trait.rs:21:7: 21:20
+ // + literal: Const { ty: for<'r> fn(&'r dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
+ // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
}

bb1: {
Loading