From db7d629ca0be043a72cd06b68b759a579ef7ccbf Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Dec 2018 22:42:08 +0200 Subject: [PATCH 01/68] rustc: remove unnecessary extern_prelude logic from ty::item_path. --- src/librustc/ty/item_path.rs | 107 +++++++++------------ src/librustc_codegen_utils/symbol_names.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- 3 files changed, 47 insertions(+), 64 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 0ddc5ae87208d..f5c502810e569 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -67,7 +67,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }); let mut buffer = LocalPathBuffer::new(mode); debug!("item_path_str: buffer={:?} def_id={:?}", buffer, def_id); - self.push_item_path(&mut buffer, def_id, false); + self.push_item_path(&mut buffer, def_id); buffer.into_string() } @@ -81,19 +81,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn absolute_item_path_str(self, def_id: DefId) -> String { let mut buffer = LocalPathBuffer::new(RootMode::Absolute); debug!("absolute_item_path_str: buffer={:?} def_id={:?}", buffer, def_id); - self.push_item_path(&mut buffer, def_id, false); + self.push_item_path(&mut buffer, def_id); buffer.into_string() } /// Returns the "path" to a particular crate. This can proceed in /// various ways, depending on the `root_mode` of the `buffer`. /// (See `RootMode` enum for more details.) - /// - /// `pushed_prelude_crate` argument should be `true` when the buffer - /// has had a prelude crate pushed to it. If this is the case, then - /// we do not want to prepend `crate::` (as that would not be a valid - /// path). - pub fn push_krate_path(self, buffer: &mut T, cnum: CrateNum, pushed_prelude_crate: bool) + pub fn push_krate_path(self, buffer: &mut T, cnum: CrateNum) where T: ItemPathBuffer + Debug { debug!( @@ -115,28 +110,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // // Returns `None` for the local crate. if cnum != LOCAL_CRATE { - let opt_extern_crate = self.extern_crate(cnum.as_def_id()); - if let Some(ExternCrate { - src: ExternCrateSource::Extern(def_id), - direct: true, - .. - }) = *opt_extern_crate - { - debug!("push_krate_path: def_id={:?}", def_id); - self.push_item_path(buffer, def_id, pushed_prelude_crate); - } else { - let name = self.crate_name(cnum).as_str(); - debug!("push_krate_path: name={:?}", name); - buffer.push(&name); - } - } else if self.sess.rust_2018() && !pushed_prelude_crate { - SHOULD_PREFIX_WITH_CRATE.with(|flag| { - // We only add the `crate::` keyword where appropriate. In particular, - // when we've not previously pushed a prelude crate to this path. - if flag.get() { - buffer.push(&keywords::Crate.name().as_str()) + match *self.extern_crate(cnum.as_def_id()) { + Some(ExternCrate { + src: ExternCrateSource::Extern(def_id), + direct: true, + span, + .. + }) if !span.is_dummy() => { + debug!("push_krate_path: def_id={:?}", def_id); + self.push_item_path(buffer, def_id); } - }) + _ => { + let name = self.crate_name(cnum).as_str(); + debug!("push_krate_path: name={:?}", name); + buffer.push(&name); + } + } + } else if self.sess.rust_2018() { + // We add the `crate::` keyword on Rust 2018, only when desired. + if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + buffer.push(&keywords::Crate.name().as_str()) + } } } RootMode::Absolute => { @@ -156,7 +150,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self, buffer: &mut T, external_def_id: DefId, - pushed_prelude_crate: bool, ) -> bool where T: ItemPathBuffer + Debug { @@ -179,10 +172,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { Some(ExternCrate { src: ExternCrateSource::Extern(def_id), direct: true, + span, .. }) => { debug!("try_push_visible_item_path: def_id={:?}", def_id); - self.push_item_path(buffer, def_id, pushed_prelude_crate); + if !span.is_dummy() { + self.push_item_path(buffer, def_id); + } else { + buffer.push(&self.crate_name(cur_def.krate).as_str()); + } cur_path.iter().rev().for_each(|segment| buffer.push(&segment)); return true; } @@ -280,16 +278,16 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn push_item_path(self, buffer: &mut T, def_id: DefId, pushed_prelude_crate: bool) + pub fn push_item_path(self, buffer: &mut T, def_id: DefId) where T: ItemPathBuffer + Debug { debug!( - "push_item_path: buffer={:?} def_id={:?} pushed_prelude_crate={:?}", - buffer, def_id, pushed_prelude_crate + "push_item_path: buffer={:?} def_id={:?}", + buffer, def_id ); match *buffer.root_mode() { RootMode::Local if !def_id.is_local() => - if self.try_push_visible_item_path(buffer, def_id, pushed_prelude_crate) { return }, + if self.try_push_visible_item_path(buffer, def_id) { return }, _ => {} } @@ -298,11 +296,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); - self.push_krate_path(buffer, def_id.krate, pushed_prelude_crate); + self.push_krate_path(buffer, def_id.krate); } DefPathData::Impl => { - self.push_impl_path(buffer, def_id, pushed_prelude_crate); + self.push_impl_path(buffer, def_id); } // Unclear if there is any value in distinguishing these. @@ -326,36 +324,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::ClosureExpr | data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { - let parent_did = self.parent_def_id(def_id).unwrap(); - - // Keep track of whether we are one recursion away from the `CrateRoot` and - // pushing the name of a prelude crate. If we are, we'll want to know this when - // printing the `CrateRoot` so we don't prepend a `crate::` to paths. - let mut is_prelude_crate = false; - if let DefPathData::CrateRoot = self.def_key(parent_did).disambiguated_data.data { - if self.extern_prelude.contains_key(&data.as_interned_str().as_symbol()) { - is_prelude_crate = true; - } - } - - self.push_item_path( - buffer, parent_did, pushed_prelude_crate || is_prelude_crate - ); + let parent_def_id = self.parent_def_id(def_id).unwrap(); + self.push_item_path(buffer, parent_def_id); buffer.push(&data.as_interned_str().as_symbol().as_str()); }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.parent_def_id(def_id).unwrap(); - self.push_item_path(buffer, parent_def_id, pushed_prelude_crate); + self.push_item_path(buffer, parent_def_id); } } } fn push_impl_path( self, - buffer: &mut T, - impl_def_id: DefId, - pushed_prelude_crate: bool, + buffer: &mut T, + impl_def_id: DefId, ) where T: ItemPathBuffer + Debug { @@ -371,7 +355,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; if !use_types { - return self.push_impl_path_fallback(buffer, impl_def_id, pushed_prelude_crate); + return self.push_impl_path_fallback(buffer, impl_def_id); } // Decide whether to print the parent path for the impl. @@ -395,7 +379,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - self.push_item_path(buffer, parent_def_id, pushed_prelude_crate); + self.push_item_path(buffer, parent_def_id); if let Some(trait_ref) = impl_trait_ref { buffer.push(&format!("", trait_ref, self_ty)); } else { @@ -419,13 +403,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { match self_ty.sty { ty::Adt(adt_def, substs) => { if substs.types().next().is_none() { // ignore regions - self.push_item_path(buffer, adt_def.did, pushed_prelude_crate); + self.push_item_path(buffer, adt_def.did); } else { buffer.push(&format!("<{}>", self_ty)); } } - ty::Foreign(did) => self.push_item_path(buffer, did, pushed_prelude_crate), + ty::Foreign(did) => self.push_item_path(buffer, did), ty::Bool | ty::Char | @@ -446,7 +430,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self, buffer: &mut T, impl_def_id: DefId, - pushed_prelude_crate: bool, ) where T: ItemPathBuffer + Debug { @@ -454,7 +437,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // pretty printing some span information. This should // only occur very early in the compiler pipeline. let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); - self.push_item_path(buffer, parent_def_id, pushed_prelude_crate); + self.push_item_path(buffer, parent_def_id); let node_id = self.hir().as_local_node_id(impl_def_id).unwrap(); let item = self.hir().expect_item(node_id); let span_str = self.sess.source_map().span_to_string(item.span); diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 9267f14f24234..7aa06c6124c66 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -223,7 +223,7 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { let mut buffer = SymbolPathBuffer::new(); item_path::with_forced_absolute_paths(|| { - tcx.push_item_path(&mut buffer, def_id, false); + tcx.push_item_path(&mut buffer, def_id); }); buffer.into_interned() } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6eea95b61c990..ec51a17768b90 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4063,7 +4063,7 @@ where F: Fn(DefId) -> Def { let mut apb = AbsolutePathBuffer { names: vec![] }; - tcx.push_item_path(&mut apb, def_id, false); + tcx.push_item_path(&mut apb, def_id); hir::Path { span: DUMMY_SP, From 37c02c34f71c7ad3033d5497170ff8533071245d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:13:37 +0200 Subject: [PATCH 02/68] rustc: start moving util::ppaux to ty::print. --- src/librustc/ty/mod.rs | 1 + src/librustc/ty/print.rs | 91 ++++++++++++++++++++++++++++++++++++++ src/librustc/util/ppaux.rs | 84 +---------------------------------- 3 files changed, 93 insertions(+), 83 deletions(-) create mode 100644 src/librustc/ty/print.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c9089428b2324..a41d50895ab21 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -98,6 +98,7 @@ pub mod item_path; pub mod layout; pub mod _match; pub mod outlives; +pub mod print; pub mod query; pub mod relate; pub mod steal; diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs new file mode 100644 index 0000000000000..c065ab7f87150 --- /dev/null +++ b/src/librustc/ty/print.rs @@ -0,0 +1,91 @@ +use ty::{self, TypeFoldable}; + +use rustc_data_structures::fx::FxHashSet; +use syntax::symbol::InternedString; + +use std::fmt; + +// FIXME(eddyb) this module uses `pub(crate)` for things used only +// from `ppaux` - when that is removed, they can be re-privatized. + +struct LateBoundRegionNameCollector(FxHashSet); +impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + match *r { + ty::ReLateBound(_, ty::BrNamed(_, name)) => { + self.0.insert(name); + }, + _ => {}, + } + r.super_visit_with(self) + } +} + +#[derive(Debug)] +pub struct PrintContext { + pub(crate) is_debug: bool, + pub(crate) is_verbose: bool, + pub(crate) identify_regions: bool, + pub(crate) used_region_names: Option>, + pub(crate) region_index: usize, + pub(crate) binder_depth: usize, +} + +impl PrintContext { + pub(crate) fn new() -> Self { + ty::tls::with_opt(|tcx| { + let (is_verbose, identify_regions) = tcx.map( + |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions) + ).unwrap_or((false, false)); + PrintContext { + is_debug: false, + is_verbose: is_verbose, + identify_regions: identify_regions, + used_region_names: None, + region_index: 0, + binder_depth: 0, + } + }) + } + pub(crate) fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder) + where T: TypeFoldable<'tcx> + { + let mut collector = LateBoundRegionNameCollector(Default::default()); + value.visit_with(&mut collector); + self.used_region_names = Some(collector.0); + self.region_index = 0; + } +} + +pub trait Print { + fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result; + fn print_to_string(&self, cx: &mut PrintContext) -> String { + let mut result = String::new(); + let _ = self.print(&mut result, cx); + result + } + fn print_display(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + let old_debug = cx.is_debug; + cx.is_debug = false; + let result = self.print(f, cx); + cx.is_debug = old_debug; + result + } + fn print_display_to_string(&self, cx: &mut PrintContext) -> String { + let mut result = String::new(); + let _ = self.print_display(&mut result, cx); + result + } + fn print_debug(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + let old_debug = cx.is_debug; + cx.is_debug = true; + let result = self.print(f, cx); + cx.is_debug = old_debug; + result + } + fn print_debug_to_string(&self, cx: &mut PrintContext) -> String { + let mut result = String::new(); + let _ = self.print_debug(&mut result, cx); + result + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 51e9192cd290d..18b24aae37947 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; -use util::nodemap::FxHashSet; +use ty::print::{PrintContext, Print}; use std::cell::Cell; use std::fmt; @@ -275,88 +275,6 @@ macro_rules! print { }; } - -struct LateBoundRegionNameCollector(FxHashSet); -impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { - match *r { - ty::ReLateBound(_, ty::BrNamed(_, name)) => { - self.0.insert(name); - }, - _ => {}, - } - r.super_visit_with(self) - } -} - -#[derive(Debug)] -pub struct PrintContext { - is_debug: bool, - is_verbose: bool, - identify_regions: bool, - used_region_names: Option>, - region_index: usize, - binder_depth: usize, -} -impl PrintContext { - fn new() -> Self { - ty::tls::with_opt(|tcx| { - let (is_verbose, identify_regions) = tcx.map( - |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions) - ).unwrap_or((false, false)); - PrintContext { - is_debug: false, - is_verbose: is_verbose, - identify_regions: identify_regions, - used_region_names: None, - region_index: 0, - binder_depth: 0, - } - }) - } - fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder) - where T: TypeFoldable<'tcx> - { - let mut collector = LateBoundRegionNameCollector(Default::default()); - value.visit_with(&mut collector); - self.used_region_names = Some(collector.0); - self.region_index = 0; - } -} - -pub trait Print { - fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result; - fn print_to_string(&self, cx: &mut PrintContext) -> String { - let mut result = String::new(); - let _ = self.print(&mut result, cx); - result - } - fn print_display(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { - let old_debug = cx.is_debug; - cx.is_debug = false; - let result = self.print(f, cx); - cx.is_debug = old_debug; - result - } - fn print_display_to_string(&self, cx: &mut PrintContext) -> String { - let mut result = String::new(); - let _ = self.print_display(&mut result, cx); - result - } - fn print_debug(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { - let old_debug = cx.is_debug; - cx.is_debug = true; - let result = self.print(f, cx); - cx.is_debug = old_debug; - result - } - fn print_debug_to_string(&self, cx: &mut PrintContext) -> String { - let mut result = String::new(); - let _ = self.print_debug(&mut result, cx); - result - } -} - impl PrintContext { fn fn_sig(&mut self, f: &mut F, From 59be9a0a1315cf446c4a436d12fe93c5769dabfd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:13:55 +0200 Subject: [PATCH 03/68] rustc: add a 'tcx parameter to Print. --- src/librustc/ty/print.rs | 2 +- src/librustc/util/ppaux.rs | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index c065ab7f87150..cef99af44fa50 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -57,7 +57,7 @@ impl PrintContext { } } -pub trait Print { +pub trait Print<'tcx> { fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result; fn print_to_string(&self, cx: &mut PrintContext) -> String { let mut result = String::new(); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 18b24aae37947..06216c4fd749f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -212,7 +212,7 @@ macro_rules! gen_display_debug { } macro_rules! gen_print_impl { ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { - impl<$($x)+> Print for $target { + impl<$($x)+> Print<'tcx> for $target { fn print(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result { if $cx.is_debug $dbg else $disp @@ -220,7 +220,7 @@ macro_rules! gen_print_impl { } }; ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { - impl Print for $target { + impl Print<'tcx> for $target { fn print(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result { if $cx.is_debug $dbg else $disp @@ -517,12 +517,15 @@ impl PrintContext { Ok(()) } - fn in_binder<'a, 'gcx, 'tcx, T, U, F>(&mut self, - f: &mut F, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - original: &ty::Binder, - lifted: Option>) -> fmt::Result - where T: Print, U: Print + TypeFoldable<'tcx>, F: fmt::Write + // FIXME(eddyb) replace `'almost_tcx` with `'tcx` when possible/needed. + fn in_binder<'a, 'gcx, 'tcx, 'almost_tcx, T, U, F>( + &mut self, + f: &mut F, + tcx: TyCtxt<'a, 'gcx, 'tcx>, + original: &ty::Binder, + lifted: Option>, + ) -> fmt::Result + where T: Print<'almost_tcx>, U: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -617,7 +620,7 @@ pub fn parameterized(f: &mut F, PrintContext::new().parameterized(f, substs, did, projections) } -impl<'a, T: Print> Print for &'a T { +impl<'a, 'tcx, T: Print<'tcx>> Print<'tcx> for &'a T { fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { (*self).print(f, cx) } @@ -1393,7 +1396,7 @@ define_print! { } define_print! { - ('tcx, T: Print + fmt::Debug, U: Print + fmt::Debug) ty::OutlivesPredicate, + ('tcx, T: Print<'tcx> + fmt::Debug, U: Print<'tcx> + fmt::Debug) ty::OutlivesPredicate, (self, f, cx) { display { print!(f, cx, print(self.0), write(" : "), print(self.1)) From 3c5821667033372f7db19c54241cc3e86aaede86 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:25:17 +0200 Subject: [PATCH 04/68] rustc: uniformize all lift expect messages to "could not lift for printing". --- src/librustc/util/ppaux.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 06216c4fd749f..b285e8992a87f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -638,11 +638,11 @@ define_print! { if let Some(principal) = self.principal() { let principal = tcx .lift(&principal) - .expect("could not lift TraitRef for printing") + .expect("could not lift for printing") .with_self_ty(tcx, dummy_self); let projections = self.projection_bounds().map(|p| { tcx.lift(&p) - .expect("could not lift projection for printing") + .expect("could not lift for printing") .with_self_ty(tcx, dummy_self) }).collect::>(); cx.parameterized(f, principal.substs, principal.def_id, &projections)?; @@ -770,7 +770,7 @@ define_print! { let dummy_self = tcx.mk_infer(ty::FreshTy(0)); let trait_ref = *tcx.lift(&ty::Binder::bind(*self)) - .expect("could not lift TraitRef for printing") + .expect("could not lift for printing") .with_self_ty(tcx, dummy_self).skip_binder(); cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) }) From 4cdc4415046fb51f6f992c0a17655a09e3dd5db3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:35:48 +0200 Subject: [PATCH 05/68] rustc: don't support `tcx.lift` returning `None` in ppaux. --- src/librustc/util/ppaux.rs | 57 ++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 33 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b285e8992a87f..ee990fc38f980 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -402,17 +402,16 @@ impl PrintContext { *has_default.unwrap_or(&false) }; if has_default { - if let Some(substs) = tcx.lift(&substs) { - let types = substs.types().rev().skip(child_types); - for ((def_id, has_default), actual) in type_params.zip(types) { - if !has_default { - break; - } - if tcx.type_of(def_id).subst(tcx, substs) != actual { - break; - } - num_supplied_defaults += 1; + let substs = tcx.lift(&substs).expect("could not lift for printing"); + let types = substs.types().rev().skip(child_types); + for ((def_id, has_default), actual) in type_params.zip(types) { + if !has_default { + break; } + if tcx.type_of(def_id).subst(tcx, substs) != actual { + break; + } + num_supplied_defaults += 1; } } } @@ -517,15 +516,13 @@ impl PrintContext { Ok(()) } - // FIXME(eddyb) replace `'almost_tcx` with `'tcx` when possible/needed. - fn in_binder<'a, 'gcx, 'tcx, 'almost_tcx, T, U, F>( + fn in_binder<'a, 'gcx, 'tcx, T, F>( &mut self, f: &mut F, tcx: TyCtxt<'a, 'gcx, 'tcx>, - original: &ty::Binder, - lifted: Option>, + value: ty::Binder, ) -> fmt::Result - where T: Print<'almost_tcx>, U: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write + where T: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -540,12 +537,6 @@ impl PrintContext { // 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. - let value = if let Some(v) = lifted { - v - } else { - return original.skip_binder().print_display(f, self); - }; - if self.binder_depth == 0 { self.prepare_late_bound_region_info(&value); } @@ -1084,7 +1075,8 @@ impl fmt::Debug for ty::FloatVarValue { for<'a> >::Lifted: fmt::Display + TypeFoldable<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) + ty::tls::with(|tcx| in_binder(f, tcx, tcx.lift(self) + .expect("could not lift for printing"))) } }*/ @@ -1101,7 +1093,8 @@ define_print_multi! { ] (self, f, cx) { display { - ty::tls::with(|tcx| cx.in_binder(f, tcx, self, tcx.lift(self))) + ty::tls::with(|tcx| cx.in_binder(f, tcx, tcx.lift(self) + .expect("could not lift for printing"))) } } } @@ -1169,10 +1162,9 @@ define_print! { } FnDef(def_id, substs) => { ty::tls::with(|tcx| { - let mut sig = tcx.fn_sig(def_id); - if let Some(substs) = tcx.lift(&substs) { - sig = sig.subst(tcx, substs); - } + let substs = tcx.lift(&substs) + .expect("could not lift for printing"); + let sig = tcx.fn_sig(def_id).subst(tcx, substs); print!(f, cx, print(sig), write(" {{")) })?; cx.parameterized(f, substs, def_id, &[])?; @@ -1243,11 +1235,9 @@ define_print! { } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let predicates_of = tcx.predicates_of(def_id); - let substs = tcx.lift(&substs).unwrap_or_else(|| { - tcx.intern_substs(&[]) - }); - let bounds = predicates_of.instantiate(tcx, substs); + let substs = tcx.lift(&substs) + .expect("could not lift for printing"); + let bounds = tcx.predicates_of(def_id).instantiate(tcx, substs); let mut first = true; let mut is_sized = false; @@ -1314,7 +1304,8 @@ define_print! { print!(f, cx, write(" "), print(witness), write("]")) }), GeneratorWitness(types) => { - ty::tls::with(|tcx| cx.in_binder(f, tcx, &types, tcx.lift(&types))) + ty::tls::with(|tcx| cx.in_binder(f, tcx, tcx.lift(&types) + .expect("could not lift for printing"))) } Closure(did, substs) => ty::tls::with(|tcx| { let upvar_tys = substs.upvar_tys(did, tcx); From c40411c53852cfd917c138254cf5ee8e36432dac Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 20:04:21 +0200 Subject: [PATCH 06/68] rustc: don't support missing TLS TyCtxt in ty::print. --- src/librustc/ty/print.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index cef99af44fa50..0e51a6b14be9b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -33,10 +33,9 @@ pub struct PrintContext { impl PrintContext { pub(crate) fn new() -> Self { - ty::tls::with_opt(|tcx| { - let (is_verbose, identify_regions) = tcx.map( - |tcx| (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions) - ).unwrap_or((false, false)); + ty::tls::with(|tcx| { + let (is_verbose, identify_regions) = + (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions); PrintContext { is_debug: false, is_verbose: is_verbose, From 93fd485b9880580d9983b8f5b51335d89c6cd812 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 16:17:44 +0200 Subject: [PATCH 07/68] rustc: rename PrintContext to PrintCx. --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/ty/print.rs | 18 +++++++++--------- src/librustc/util/ppaux.rs | 14 +++++++------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 66e4cd49c807f..0d3262f1c8356 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -675,7 +675,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// For generic types with parameters with defaults, remove the parameters corresponding to - /// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`. + /// the defaults. This repeats a lot of the logic found in `PrintCx::parameterized`. fn strip_generic_default_params( &self, def_id: DefId, diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 0e51a6b14be9b..6d480bbe24d37 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -22,7 +22,7 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } #[derive(Debug)] -pub struct PrintContext { +pub struct PrintCx { pub(crate) is_debug: bool, pub(crate) is_verbose: bool, pub(crate) identify_regions: bool, @@ -31,12 +31,12 @@ pub struct PrintContext { pub(crate) binder_depth: usize, } -impl PrintContext { +impl PrintCx { pub(crate) fn new() -> Self { ty::tls::with(|tcx| { let (is_verbose, identify_regions) = (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions); - PrintContext { + PrintCx { is_debug: false, is_verbose: is_verbose, identify_regions: identify_regions, @@ -57,32 +57,32 @@ impl PrintContext { } pub trait Print<'tcx> { - fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result; - fn print_to_string(&self, cx: &mut PrintContext) -> String { + fn print(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result; + fn print_to_string(&self, cx: &mut PrintCx) -> String { let mut result = String::new(); let _ = self.print(&mut result, cx); result } - fn print_display(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + fn print_display(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = false; let result = self.print(f, cx); cx.is_debug = old_debug; result } - fn print_display_to_string(&self, cx: &mut PrintContext) -> String { + fn print_display_to_string(&self, cx: &mut PrintCx) -> String { let mut result = String::new(); let _ = self.print_display(&mut result, cx); result } - fn print_debug(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + fn print_debug(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = true; let result = self.print(f, cx); cx.is_debug = old_debug; result } - fn print_debug_to_string(&self, cx: &mut PrintContext) -> String { + fn print_debug_to_string(&self, cx: &mut PrintCx) -> String { let mut result = String::new(); let _ = self.print_debug(&mut result, cx); result diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ee990fc38f980..84aaaa4858ddb 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; -use ty::print::{PrintContext, Print}; +use ty::print::{PrintCx, Print}; use std::cell::Cell; use std::fmt; @@ -182,7 +182,7 @@ impl RegionHighlightMode { macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut cx = PrintContext::new(); + let mut cx = PrintCx::new(); $with(self, f, &mut cx) } }; @@ -213,7 +213,7 @@ macro_rules! gen_display_debug { macro_rules! gen_print_impl { ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { impl<$($x)+> Print<'tcx> for $target { - fn print(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result { + fn print(&$self, $f: &mut F, $cx: &mut PrintCx) -> fmt::Result { if $cx.is_debug $dbg else $disp } @@ -221,7 +221,7 @@ macro_rules! gen_print_impl { }; ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { impl Print<'tcx> for $target { - fn print(&$self, $f: &mut F, $cx: &mut PrintContext) -> fmt::Result { + fn print(&$self, $f: &mut F, $cx: &mut PrintCx) -> fmt::Result { if $cx.is_debug $dbg else $disp } @@ -275,7 +275,7 @@ macro_rules! print { }; } -impl PrintContext { +impl PrintCx { fn fn_sig(&mut self, f: &mut F, inputs: &[Ty<'_>], @@ -608,11 +608,11 @@ pub fn parameterized(f: &mut F, did: DefId, projections: &[ty::ProjectionPredicate<'_>]) -> fmt::Result { - PrintContext::new().parameterized(f, substs, did, projections) + PrintCx::new().parameterized(f, substs, did, projections) } impl<'a, 'tcx, T: Print<'tcx>> Print<'tcx> for &'a T { - fn print(&self, f: &mut F, cx: &mut PrintContext) -> fmt::Result { + fn print(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result { (*self).print(f, cx) } } From 48319322529570062a6bbefba19bc3eb2e9b9121 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 15:22:50 +0200 Subject: [PATCH 08/68] rustc: keep a TyCtxt in PrintCx and use it instead of ty::tls. --- src/librustc/mir/mod.rs | 24 +-- src/librustc/ty/print.rs | 35 ++-- src/librustc/util/ppaux.rs | 335 +++++++++++++++++-------------------- 3 files changed, 188 insertions(+), 206 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 82083b4f69964..812ce2a7d7895 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2341,17 +2341,19 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; // When printing regions, add trailing space if necessary. - let region = if ppaux::verbose() || ppaux::identify_regions() { - let mut region = region.to_string(); - if region.len() > 0 { - region.push(' '); - } - region - } else { - // Do not even print 'static - String::new() - }; - write!(fmt, "&{}{}{:?}", region, kind_str, place) + ty::print::PrintCx::with(|cx| { + let region = if cx.is_verbose || cx.identify_regions { + let mut region = region.to_string(); + if region.len() > 0 { + region.push(' '); + } + region + } else { + // Do not even print 'static + String::new() + }; + write!(fmt, "&{}{}{:?}", region, kind_str, place) + }) } Aggregate(ref kind, ref places) => { diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 6d480bbe24d37..617e3183f576e 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -1,4 +1,4 @@ -use ty::{self, TypeFoldable}; +use ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashSet; use syntax::symbol::InternedString; @@ -21,8 +21,8 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } } -#[derive(Debug)] -pub struct PrintCx { +pub struct PrintCx<'a, 'gcx, 'tcx> { + pub(crate) tcx: TyCtxt<'a, 'gcx, 'tcx>, pub(crate) is_debug: bool, pub(crate) is_verbose: bool, pub(crate) identify_regions: bool, @@ -31,22 +31,21 @@ pub struct PrintCx { pub(crate) binder_depth: usize, } -impl PrintCx { - pub(crate) fn new() -> Self { +impl PrintCx<'a, 'gcx, 'tcx> { + pub(crate) fn with(f: impl FnOnce(PrintCx<'_, '_, '_>) -> R) -> R { ty::tls::with(|tcx| { - let (is_verbose, identify_regions) = - (tcx.sess.verbose(), tcx.sess.opts.debugging_opts.identify_regions); - PrintCx { + f(PrintCx { + tcx, is_debug: false, - is_verbose: is_verbose, - identify_regions: identify_regions, + is_verbose: tcx.sess.verbose(), + identify_regions: tcx.sess.opts.debugging_opts.identify_regions, used_region_names: None, region_index: 0, binder_depth: 0, - } + }) }) } - pub(crate) fn prepare_late_bound_region_info<'tcx, T>(&mut self, value: &ty::Binder) + pub(crate) fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) where T: TypeFoldable<'tcx> { let mut collector = LateBoundRegionNameCollector(Default::default()); @@ -57,32 +56,32 @@ impl PrintCx { } pub trait Print<'tcx> { - fn print(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result; - fn print_to_string(&self, cx: &mut PrintCx) -> String { + fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result; + fn print_to_string(&self, cx: &mut PrintCx<'_, '_, '_>) -> String { let mut result = String::new(); let _ = self.print(&mut result, cx); result } - fn print_display(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result { + fn print_display(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = false; let result = self.print(f, cx); cx.is_debug = old_debug; result } - fn print_display_to_string(&self, cx: &mut PrintCx) -> String { + fn print_display_to_string(&self, cx: &mut PrintCx<'_, '_, '_>) -> String { let mut result = String::new(); let _ = self.print_display(&mut result, cx); result } - fn print_debug(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result { + fn print_debug(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = true; let result = self.print(f, cx); cx.is_debug = old_debug; result } - fn print_debug_to_string(&self, cx: &mut PrintCx) -> String { + fn print_debug_to_string(&self, cx: &mut PrintCx<'_, '_, '_>) -> String { let mut result = String::new(); let _ = self.print_debug(&mut result, cx); result diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 84aaaa4858ddb..7f8d2d7c42706 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,7 +8,7 @@ use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; -use ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind}; +use ty::{self, Ty, TypeFoldable, GenericParamCount, GenericParamDefKind}; use ty::print::{PrintCx, Print}; use std::cell::Cell; @@ -182,8 +182,7 @@ impl RegionHighlightMode { macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut cx = PrintCx::new(); - $with(self, f, &mut cx) + PrintCx::with(|mut cx| $with(self, f, &mut cx)) } }; } @@ -213,7 +212,11 @@ macro_rules! gen_display_debug { macro_rules! gen_print_impl { ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { impl<$($x)+> Print<'tcx> for $target { - fn print(&$self, $f: &mut F, $cx: &mut PrintCx) -> fmt::Result { + fn print( + &$self, + $f: &mut F, + $cx: &mut PrintCx<'_, '_, '_>, + ) -> fmt::Result { if $cx.is_debug $dbg else $disp } @@ -221,7 +224,11 @@ macro_rules! gen_print_impl { }; ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { impl Print<'tcx> for $target { - fn print(&$self, $f: &mut F, $cx: &mut PrintCx) -> fmt::Result { + fn print( + &$self, + $f: &mut F, + $cx: &mut PrintCx<'_, '_, '_>, + ) -> fmt::Result { if $cx.is_debug $dbg else $disp } @@ -275,7 +282,7 @@ macro_rules! print { }; } -impl PrintCx { +impl PrintCx<'a, 'gcx, 'tcx> { fn fn_sig(&mut self, f: &mut F, inputs: &[Ty<'_>], @@ -307,21 +314,22 @@ impl PrintCx { did: DefId, projections: &[ty::ProjectionPredicate<'_>]) -> fmt::Result { - let key = ty::tls::with(|tcx| tcx.def_key(did)); + let key = self.tcx.def_key(did); let verbose = self.is_verbose; let mut num_supplied_defaults = 0; - let mut has_self = false; + let has_self; let mut own_counts: GenericParamCount = Default::default(); let mut is_value_path = false; let mut item_name = Some(key.disambiguated_data.data.as_interned_str()); - let fn_trait_kind = ty::tls::with(|tcx| { + let mut path_def_id = did; + { // Unfortunately, some kinds of items (e.g., closures) don't have // generics. So walk back up the find the closest parent that DOES // have them. let mut item_def_id = did; loop { - let key = tcx.def_key(item_def_id); + let key = self.tcx.def_key(item_def_id); match key.disambiguated_data.data { DefPathData::AssocTypeInTrait(_) | DefPathData::AssocTypeInImpl(_) | @@ -359,9 +367,8 @@ impl PrintCx { } } } - let mut generics = tcx.generics_of(item_def_id); + let mut generics = self.tcx.generics_of(item_def_id); let child_own_counts = generics.own_counts(); - let mut path_def_id = did; has_self = generics.has_self; let mut child_types = 0; @@ -369,7 +376,7 @@ impl PrintCx { // Methods. assert!(is_value_path); child_types = child_own_counts.types; - generics = tcx.generics_of(def_id); + generics = self.tcx.generics_of(def_id); own_counts = generics.own_counts(); if has_self { @@ -402,23 +409,22 @@ impl PrintCx { *has_default.unwrap_or(&false) }; if has_default { - let substs = tcx.lift(&substs).expect("could not lift for printing"); + let substs = self.tcx.lift(&substs).expect("could not lift for printing"); let types = substs.types().rev().skip(child_types); for ((def_id, has_default), actual) in type_params.zip(types) { if !has_default { break; } - if tcx.type_of(def_id).subst(tcx, substs) != actual { + if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { break; } num_supplied_defaults += 1; } } } - - print!(f, self, write("{}", tcx.item_path_str(path_def_id)))?; - Ok(tcx.lang_items().fn_trait_kind(path_def_id)) - })?; + } + print!(f, self, write("{}", self.tcx.item_path_str(path_def_id)))?; + let fn_trait_kind = self.tcx.lang_items().fn_trait_kind(path_def_id); if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { let projection_ty = projections[0].ty; @@ -480,12 +486,10 @@ impl PrintCx { for projection in projections { start_or_continue(f, "<", ", ")?; - ty::tls::with(|tcx| - print!(f, self, - write("{}=", - tcx.associated_item(projection.projection_ty.item_def_id).ident), - print_display(projection.ty)) - )?; + print!(f, self, + write("{}=", + self.tcx.associated_item(projection.projection_ty.item_def_id).ident), + print_display(projection.ty))?; } start_or_continue(f, "", ">")?; @@ -516,12 +520,7 @@ impl PrintCx { Ok(()) } - fn in_binder<'a, 'gcx, 'tcx, T, F>( - &mut self, - f: &mut F, - tcx: TyCtxt<'a, 'gcx, 'tcx>, - value: ty::Binder, - ) -> fmt::Result + fn in_binder(&mut self, f: &mut F, value: ty::Binder) -> fmt::Result where T: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write { fn name_by_region_index(index: usize) -> InternedString { @@ -553,7 +552,7 @@ impl PrintCx { let old_region_index = self.region_index; let mut region_index = old_region_index; - let new_value = tcx.replace_late_bound_regions(&value, |br| { + let new_value = self.tcx.replace_late_bound_regions(&value, |br| { let _ = start_or_continue(f, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { @@ -571,10 +570,10 @@ impl PrintCx { } }; let _ = write!(f, "{}", name); - ty::BrNamed(tcx.hir().local_def_id(CRATE_NODE_ID), name) + ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name) } }; - tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) + self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) }).0; start_or_continue(f, "", "> ")?; @@ -595,24 +594,16 @@ impl PrintCx { } } -pub fn verbose() -> bool { - ty::tls::with(|tcx| tcx.sess.verbose()) -} - -pub fn identify_regions() -> bool { - ty::tls::with(|tcx| tcx.sess.opts.debugging_opts.identify_regions) -} - pub fn parameterized(f: &mut F, substs: &subst::Substs<'_>, did: DefId, projections: &[ty::ProjectionPredicate<'_>]) -> fmt::Result { - PrintCx::new().parameterized(f, substs, did, projections) + PrintCx::with(|mut cx| cx.parameterized(f, substs, did, projections)) } impl<'a, 'tcx, T: Print<'tcx>> Print<'tcx> for &'a T { - fn print(&self, f: &mut F, cx: &mut PrintCx) -> fmt::Result { + fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result { (*self).print(f, cx) } } @@ -621,50 +612,47 @@ define_print! { ('tcx) &'tcx ty::List>, (self, f, cx) { display { // Generate the main trait ref, including associated types. - ty::tls::with(|tcx| { - // Use a type that can't appear in defaults of type parameters. - let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - let mut first = true; - - if let Some(principal) = self.principal() { - let principal = tcx - .lift(&principal) - .expect("could not lift for printing") - .with_self_ty(tcx, dummy_self); - let projections = self.projection_bounds().map(|p| { - tcx.lift(&p) - .expect("could not lift for printing") - .with_self_ty(tcx, dummy_self) - }).collect::>(); - cx.parameterized(f, principal.substs, principal.def_id, &projections)?; - first = false; - } - // Builtin bounds. - let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { - tcx.item_path_str(did) - }).collect(); - - // The auto traits come ordered by `DefPathHash`. While - // `DefPathHash` is *stable* in the sense that it depends on - // neither the host nor the phase of the moon, it depends - // "pseudorandomly" on the compiler version and the target. - // - // To avoid that causing instabilities in compiletest - // output, sort the auto-traits alphabetically. - auto_traits.sort(); - - for auto_trait in auto_traits { - if !first { - write!(f, " + ")?; - } - first = false; + // Use a type that can't appear in defaults of type parameters. + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); + let mut first = true; + + if let Some(principal) = self.principal() { + let principal = cx.tcx + .lift(&principal) + .expect("could not lift for printing") + .with_self_ty(tcx, dummy_self); + let projections = self.projection_bounds().map(|p| { + cx.tcx.lift(&p) + .expect("could not lift for printing") + .with_self_ty(cx.tcx, dummy_self) + }).collect::>(); + cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + first = false; + } - write!(f, "{}", auto_trait)?; + // Builtin bounds. + let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { + cx.tcx.item_path_str(did) + }).collect(); + + // The auto traits come ordered by `DefPathHash`. While + // `DefPathHash` is *stable* in the sense that it depends on + // neither the host nor the phase of the moon, it depends + // "pseudorandomly" on the compiler version and the target. + // + // To avoid that causing instabilities in compiletest + // output, sort the auto-traits alphabetically. + auto_traits.sort(); + + for auto_trait in auto_traits { + if !first { + write!(f, " + ")?; } + first = false; - Ok(()) - })?; + write!(f, "{}", auto_trait)?; + } Ok(()) } @@ -687,16 +675,16 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| { - write!(f, "{}", tcx.item_path_str(self.def_id)) + PrintCx::with(|cx| { + write!(f, "{}", cx.tcx.item_path_str(self.def_id)) }) } } impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| { - write!(f, "{}", tcx.item_path_str(self.did)) + PrintCx::with(|cx| { + write!(f, "{}", cx.tcx.item_path_str(self.did)) }) } } @@ -713,7 +701,9 @@ impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, - ty::tls::with(|tcx| tcx.hir().name(tcx.hir().hir_to_node_id(self.var_path.hir_id))), + PrintCx::with(|cx| { + cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)) + }), self.closure_expr_id) } } @@ -757,14 +747,12 @@ define_print! { cx.parameterized(f, self.substs, self.def_id, &[]) } debug { - ty::tls::with(|tcx| { - let dummy_self = tcx.mk_infer(ty::FreshTy(0)); + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let trait_ref = *tcx.lift(&ty::Binder::bind(*self)) - .expect("could not lift for printing") - .with_self_ty(tcx, dummy_self).skip_binder(); - cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) - }) + let trait_ref = *cx.tcx.lift(&ty::Binder::bind(*self)) + .expect("could not lift for printing") + .with_self_ty(cx.tcx, dummy_self).skip_binder(); + cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) } } } @@ -1075,7 +1063,7 @@ impl fmt::Debug for ty::FloatVarValue { for<'a> >::Lifted: fmt::Display + TypeFoldable<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| in_binder(f, tcx, tcx.lift(self) + PrintCx::with(|cx| cx.in_binder(f, cx.tcx.lift(self) .expect("could not lift for printing"))) } }*/ @@ -1093,8 +1081,8 @@ define_print_multi! { ] (self, f, cx) { display { - ty::tls::with(|tcx| cx.in_binder(f, tcx, tcx.lift(self) - .expect("could not lift for printing"))) + cx.in_binder(f, cx.tcx.lift(self) + .expect("could not lift for printing")) } } } @@ -1161,12 +1149,10 @@ define_print! { write!(f, ")") } FnDef(def_id, substs) => { - ty::tls::with(|tcx| { - let substs = tcx.lift(&substs) - .expect("could not lift for printing"); - let sig = tcx.fn_sig(def_id).subst(tcx, substs); - print!(f, cx, print(sig), write(" {{")) - })?; + let substs = cx.tcx.lift(&substs) + .expect("could not lift for printing"); + let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); + print!(f, cx, print(sig), write(" {{"))?; cx.parameterized(f, substs, def_id, &[])?; write!(f, "}}") } @@ -1218,71 +1204,69 @@ define_print! { return write!(f, "Opaque({:?}, {:?})", def_id, substs); } - ty::tls::with(|tcx| { - let def_key = tcx.def_key(def_id); - if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - write!(f, "{}", name)?; - let mut substs = substs.iter(); - if let Some(first) = substs.next() { - write!(f, "::<")?; - write!(f, "{}", first)?; - for subst in substs { - write!(f, ", {}", subst)?; - } - write!(f, ">")?; + let def_key = cx.tcx.def_key(def_id); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { + write!(f, "{}", name)?; + let mut substs = substs.iter(); + if let Some(first) = substs.next() { + write!(f, "::<")?; + write!(f, "{}", first)?; + for subst in substs { + write!(f, ", {}", subst)?; } - return Ok(()); + write!(f, ">")?; } - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let substs = tcx.lift(&substs) - .expect("could not lift for printing"); - let bounds = tcx.predicates_of(def_id).instantiate(tcx, substs); - - let mut first = true; - let mut is_sized = false; - write!(f, "impl")?; - for predicate in bounds.predicates { - if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == tcx.lang_items().sized_trait() { - is_sized = true; - continue; - } - - print!(f, cx, - write("{}", if first { " " } else { "+" }), - print(trait_ref))?; - first = false; + return Ok(()); + } + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let substs = cx.tcx.lift(&substs) + .expect("could not lift for printing"); + let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs); + + let mut first = true; + let mut is_sized = false; + write!(f, "impl")?; + for predicate in bounds.predicates { + if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() { + is_sized = true; + continue; } + + print!(f, cx, + write("{}", if first { " " } else { "+" }), + print(trait_ref))?; + first = false; } - if !is_sized { - write!(f, "{}?Sized", if first { " " } else { "+" })?; + } + if !is_sized { + write!(f, "{}?Sized", if first { " " } else { "+" })?; } else if first { write!(f, " Sized")?; - } - Ok(()) - }) + } + Ok(()) } Str => write!(f, "str"), - Generator(did, substs, movability) => ty::tls::with(|tcx| { - let upvar_tys = substs.upvar_tys(did, tcx); - let witness = substs.witness(did, tcx); + Generator(did, substs, movability) => { + let upvar_tys = substs.upvar_tys(did, cx.tcx); + let witness = substs.witness(did, cx.tcx); if movability == hir::GeneratorMovability::Movable { write!(f, "[generator")?; } else { write!(f, "[static generator")?; } - if let Some(node_id) = tcx.hir().as_local_node_id(did) { - write!(f, "@{:?}", tcx.hir().span(node_id))?; + if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { + write!(f, "@{:?}", cx.tcx.hir().span(node_id))?; let mut sep = " "; - tcx.with_freevars(node_id, |freevars| { + cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { print!(f, cx, write("{}{}:", sep, - tcx.hir().name(freevar.var_id())), + cx.tcx.hir().name(freevar.var_id())), print(upvar_ty))?; sep = ", "; } @@ -1302,28 +1286,28 @@ define_print! { } print!(f, cx, write(" "), print(witness), write("]")) - }), + }, GeneratorWitness(types) => { - ty::tls::with(|tcx| cx.in_binder(f, tcx, tcx.lift(&types) - .expect("could not lift for printing"))) + cx.in_binder(f, cx.tcx.lift(&types) + .expect("could not lift for printing")) } - Closure(did, substs) => ty::tls::with(|tcx| { - let upvar_tys = substs.upvar_tys(did, tcx); + Closure(did, substs) => { + let upvar_tys = substs.upvar_tys(did, cx.tcx); write!(f, "[closure")?; - if let Some(node_id) = tcx.hir().as_local_node_id(did) { - if tcx.sess.opts.debugging_opts.span_free_formats { + if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { + if cx.tcx.sess.opts.debugging_opts.span_free_formats { write!(f, "@{:?}", node_id)?; } else { - write!(f, "@{:?}", tcx.hir().span(node_id))?; + write!(f, "@{:?}", cx.tcx.hir().span(node_id))?; } let mut sep = " "; - tcx.with_freevars(node_id, |freevars| { + cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { print!(f, cx, write("{}{}:", sep, - tcx.hir().name(freevar.var_id())), + cx.tcx.hir().name(freevar.var_id())), print(upvar_ty))?; sep = ", "; } @@ -1343,16 +1327,16 @@ define_print! { } write!(f, "]") - }), + }, Array(ty, sz) => { print!(f, cx, write("["), print(ty), write("; "))?; match sz { ty::LazyConst::Unevaluated(_def_id, _substs) => { write!(f, "_")?; } - ty::LazyConst::Evaluated(c) => ty::tls::with(|tcx| { - write!(f, "{}", c.unwrap_usize(tcx)) - })?, + ty::LazyConst::Evaluated(c) => { + write!(f, "{}", c.unwrap_usize(cx.tcx))?; + } } write!(f, "]") } @@ -1437,9 +1421,8 @@ define_print! { // FIXME(tschottdorf): use something like // parameterized(f, self.substs, self.item_def_id, &[]) // (which currently ICEs). - let (trait_ref, item_name) = ty::tls::with(|tcx| - (self.trait_ref(tcx), tcx.associated_item(self.item_def_id).ident) - ); + let trait_ref = self.trait_ref(cx.tcx); + let item_name = cx.tcx.associated_item(self.item_def_id).ident; print!(f, cx, print_debug(trait_ref), write("::{}", item_name)) } } @@ -1467,15 +1450,13 @@ define_print! { ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx), ty::Predicate::Projection(ref predicate) => predicate.print(f, cx), ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")), - ty::Predicate::ObjectSafe(trait_def_id) => - ty::tls::with(|tcx| { - write!(f, "the trait `{}` is object-safe", tcx.item_path_str(trait_def_id)) - }), - ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => - ty::tls::with(|tcx| { - write!(f, "the closure `{}` implements the trait `{}`", - tcx.item_path_str(closure_def_id), kind) - }), + ty::Predicate::ObjectSafe(trait_def_id) => { + write!(f, "the trait `{}` is object-safe", cx.tcx.item_path_str(trait_def_id)) + } + ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { + write!(f, "the closure `{}` implements the trait `{}`", + cx.tcx.item_path_str(closure_def_id), kind) + } ty::Predicate::ConstEvaluatable(def_id, substs) => { write!(f, "the constant `")?; cx.parameterized(f, substs, def_id, &[])?; From dc56a2f89637396b5d6e358ea8fd2ed8531d0750 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 19:14:30 +0200 Subject: [PATCH 09/68] rustc: remove fmt::{Debug,Display} from ty::TyKind. --- src/librustc/middle/mem_categorization.rs | 17 ++++++++------ src/librustc/traits/error_reporting.rs | 9 ++++---- src/librustc/ty/relate.rs | 6 ++--- src/librustc/ty/sty.rs | 7 +++--- src/librustc/util/ppaux.rs | 14 +++-------- src/librustc_codegen_llvm/intrinsic.rs | 23 +++++++++---------- src/librustc_codegen_ssa/mir/constant.rs | 2 +- src/librustc_codegen_ssa/traits/type_.rs | 2 +- .../borrow_check/error_reporting.rs | 2 +- src/librustc_mir/hair/cx/expr.rs | 5 ++-- src/librustc_mir/hair/pattern/mod.rs | 10 ++++---- src/librustc_mir/hair/util.rs | 10 +++++--- src/librustc_mir/interpret/cast.rs | 6 ++--- src/librustc_mir/interpret/operator.rs | 2 +- src/librustc_mir/interpret/place.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 2 +- src/librustc_typeck/astconv.rs | 4 +++- src/librustc_typeck/check/_match.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 6 ++--- src/librustc_typeck/check/upvar.rs | 7 +++--- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/check/writeback.rs | 2 +- 22 files changed, 73 insertions(+), 71 deletions(-) diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 370f0d1a6c6d7..158d5bf9fb394 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -786,7 +786,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { // FnMut | copied -> &'env mut | upvar -> &'env mut -> &'up bk // FnOnce | copied | upvar -> &'up bk - let kind = match self.node_ty(fn_hir_id)?.sty { + let ty = self.node_ty(fn_hir_id)?; + let kind = match ty.sty { ty::Generator(..) => ty::ClosureKind::FnOnce, ty::Closure(closure_def_id, closure_substs) => { match self.infcx { @@ -803,7 +804,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { .closure_kind(closure_def_id, self.tcx.global_tcx()), } } - ref t => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", t), + _ => span_bug!(span, "unexpected type for fn in mem_categorization: {:?}", ty), }; let closure_expr_def_id = self.tcx.hir().local_def_id(fn_node_id); @@ -1064,7 +1065,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let bk = ty::BorrowKind::from_mutbl(mutbl); BorrowedPtr(bk, r) } - ref ty => bug!("unexpected type in cat_deref: {:?}", ty) + _ => bug!("unexpected type in cat_deref: {:?}", base_cmt.ty) }; let ret = cmt_ { hir_id: node.hir_id(), @@ -1279,11 +1280,12 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) } Def::StructCtor(_, CtorKind::Fn) | Def::SelfCtor(..) => { - match self.pat_ty_unadjusted(&pat)?.sty { + let ty = self.pat_ty_unadjusted(&pat)?; + match ty.sty { ty::Adt(adt_def, _) => { (cmt, adt_def.non_enum_variant().fields.len()) } - ref ty => { + _ => { span_bug!(pat.span, "tuple struct pattern unexpected type {:?}", ty); } @@ -1334,9 +1336,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { PatKind::Tuple(ref subpats, ddpos) => { // (p1, ..., pN) - let expected_len = match self.pat_ty_unadjusted(&pat)?.sty { + let ty = self.pat_ty_unadjusted(&pat)?; + let expected_len = match ty.sty { ty::Tuple(ref tys) => tys.len(), - ref ty => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), + _ => span_bug!(pat.span, "tuple pattern unexpected type {:?}", ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(expected_len, ddpos) { let subpat_ty = self.pat_ty_adjusted(&subpat)?; // see (*2) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 5debb11902988..d13562d7b29c3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -847,10 +847,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => vec![ArgKind::empty()], }; - let expected = match expected_trait_ref.skip_binder().substs.type_at(1).sty { + let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); + let expected = match expected_ty.sty { ty::Tuple(ref tys) => tys.iter() .map(|t| ArgKind::from_expected_ty(t, Some(span))).collect(), - ref sty => vec![ArgKind::Arg("_".to_owned(), sty.to_string())], + _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], }; if found.len() == expected.len() { @@ -1640,10 +1641,10 @@ impl ArgKind { ty::Tuple(ref tys) => ArgKind::Tuple( span, tys.iter() - .map(|ty| ("_".to_owned(), ty.sty.to_string())) + .map(|ty| ("_".to_owned(), ty.to_string())) .collect::>() ), - _ => ArgKind::Arg("_".to_owned(), t.sty.to_string()), + _ => ArgKind::Arg("_".to_owned(), t.to_string()), } } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index a16d6fea74c0b..5a605e6d625d0 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -351,10 +351,8 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { let tcx = relation.tcx(); - let a_sty = &a.sty; - let b_sty = &b.sty; - debug!("super_relate_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty); - match (a_sty, b_sty) { + debug!("super_relate_tys: a={:?} b={:?}", a, b); + match (&a.sty, &b.sty) { (&ty::Infer(_), _) | (_, &ty::Infer(_)) => { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 671a0fc2d5d7a..f4185c9201540 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -81,7 +81,7 @@ impl BoundRegion { /// N.B., if you change this, you'll probably want to change the corresponding /// AST structure in `libsyntax/ast.rs` as well. -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. Bool, @@ -377,9 +377,10 @@ impl<'tcx> ClosureSubsts<'tcx> { /// /// If you have an inference context, use `infcx.closure_sig()`. pub fn closure_sig(self, def_id: DefId, tcx: TyCtxt<'_, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { - match self.closure_sig_ty(def_id, tcx).sty { + let ty = self.closure_sig_ty(def_id, tcx); + match ty.sty { ty::FnPtr(sig) => sig, - ref t => bug!("closure_sig_ty is not a fn-ptr: {:?}", t), + _ => bug!("closure_sig_ty is not a fn-ptr: {:?}", ty), } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 7f8d2d7c42706..fb4aa6872dc4a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1107,9 +1107,9 @@ define_print! { } define_print! { - ('tcx) ty::TyKind<'tcx>, (self, f, cx) { + ('tcx) ty::TyS<'tcx>, (self, f, cx) { display { - match *self { + match self.sty { Bool => write!(f, "bool"), Char => write!(f, "char"), Int(t) => write!(f, "{}", t.ty_to_string()), @@ -1345,16 +1345,8 @@ define_print! { } } } - } -} - -define_print! { - ('tcx) ty::TyS<'tcx>, (self, f, cx) { - display { - self.sty.print(f, cx) - } debug { - self.sty.print_display(f, cx) + self.print_display(f, cx) } } } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 201b1684fb9b2..5b798b8e3ffef 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -481,8 +481,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { }, "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { - let sty = &arg_tys[0].sty; - match float_type_width(sty) { + match float_type_width(arg_tys[0]) { Some(_width) => match name { "fadd_fast" => self.fadd_fast(args[0].immediate(), args[1].immediate()), @@ -496,7 +495,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { span_invalid_monomorphization_error( tcx.sess, span, &format!("invalid monomorphization of `{}` intrinsic: \ - expected basic float type, found `{}`", name, sty)); + expected basic float type, found `{}`", name, arg_tys[0])); return; } } @@ -1406,8 +1405,8 @@ fn generic_simd_intrinsic( require!(false, "expected element type `{}` of second argument `{}` \ to be a pointer to the element type `{}` of the first \ argument `{}`, found `{}` != `*_ {}`", - arg_tys[1].simd_type(tcx).sty, arg_tys[1], in_elem, in_ty, - arg_tys[1].simd_type(tcx).sty, in_elem); + arg_tys[1].simd_type(tcx), arg_tys[1], in_elem, in_ty, + arg_tys[1].simd_type(tcx), in_elem); unreachable!(); } }; @@ -1421,7 +1420,7 @@ fn generic_simd_intrinsic( _ => { require!(false, "expected element type `{}` of third argument `{}` \ to be a signed integer type", - arg_tys[2].simd_type(tcx).sty, arg_tys[2]); + arg_tys[2].simd_type(tcx), arg_tys[2]); } } @@ -1506,8 +1505,8 @@ fn generic_simd_intrinsic( require!(false, "expected element type `{}` of second argument `{}` \ to be a pointer to the element type `{}` of the first \ argument `{}`, found `{}` != `*mut {}`", - arg_tys[1].simd_type(tcx).sty, arg_tys[1], in_elem, in_ty, - arg_tys[1].simd_type(tcx).sty, in_elem); + arg_tys[1].simd_type(tcx), arg_tys[1], in_elem, in_ty, + arg_tys[1].simd_type(tcx), in_elem); unreachable!(); } }; @@ -1521,7 +1520,7 @@ fn generic_simd_intrinsic( _ => { require!(false, "expected element type `{}` of third argument `{}` \ to be a signed integer type", - arg_tys[2].simd_type(tcx).sty, arg_tys[2]); + arg_tys[2].simd_type(tcx), arg_tys[2]); } } @@ -1842,10 +1841,10 @@ fn int_type_width_signed(ty: Ty, cx: &CodegenCx) -> Option<(u64, bool)> { } } -// Returns the width of a float TypeVariant +// Returns the width of a float Ty // Returns None if the type is not a float -fn float_type_width<'tcx>(sty: &ty::TyKind<'tcx>) -> Option { - match *sty { +fn float_type_width(ty: Ty) -> Option { + match ty.sty { ty::Float(t) => Some(t.bit_width() as u64), _ => None, } diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 56d4342e6e161..af8b88ffbc7bc 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -53,7 +53,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let field_ty = c.ty.builtin_index().unwrap(); let fields = match c.ty.sty { ty::Array(_, n) => n.unwrap_usize(bx.tcx()), - ref other => bug!("invalid simd shuffle type: {}", other), + _ => bug!("invalid simd shuffle type: {}", c.ty), }; let values: Result, ErrorHandled> = (0..fields).map(|field| { let field = const_field( diff --git a/src/librustc_codegen_ssa/traits/type_.rs b/src/librustc_codegen_ssa/traits/type_.rs index 2ec0c8e5a75cc..4f50d8b781c30 100644 --- a/src/librustc_codegen_ssa/traits/type_.rs +++ b/src/librustc_codegen_ssa/traits/type_.rs @@ -148,7 +148,7 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { match tail.sty { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, - _ => bug!("unexpected unsized tail: {:?}", tail.sty), + _ => bug!("unexpected unsized tail: {:?}", tail), } } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index b070031756798..a7e705039eb66 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1786,7 +1786,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // (https://github.com/rust-lang/rfcs/pull/1546) bug!( "End-user description not implemented for field access on `{:?}`", - ty.sty + ty ); } } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 8d64c9e9ada89..706bb9735feee 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -940,7 +940,8 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, let user_provided_types = cx.tables.user_provided_types(); let user_provided_type = user_provided_types.get(expr.hir_id).map(|u_ty| *u_ty); debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); - match cx.tables().node_id_to_type(expr.hir_id).sty { + let ty = cx.tables().node_id_to_type(expr.hir_id); + match ty.sty { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. ty::Adt(adt_def, substs) => { @@ -953,7 +954,7 @@ fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, base: None, } } - ref sty => bug!("unexpected sty: {:?}", sty), + _ => bug!("unexpected ty: {:?}", ty), } } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 7d48cdc1d8aef..fd2f59afda0e6 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -484,11 +484,11 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Error => { // Avoid ICE return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; } - ref sty => + _ => span_bug!( pat.span, "unexpanded type for vector pattern: {:?}", - sty), + ty), } } @@ -509,7 +509,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Error => { // Avoid ICE (#50577) return Pattern { span: pat.span, ty, kind: Box::new(PatternKind::Wild) }; } - ref sty => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", sty), + _ => span_bug!(pat.span, "unexpected type for tuple pattern: {:?}", ty), } } @@ -563,7 +563,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } _ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT {:?}", - ty.sty), + ty), }; let variant_def = adt_def.variant_of_def(def); @@ -699,7 +699,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Error => { // Avoid ICE (#50585) return PatternKind::Wild; } - _ => bug!("inappropriate type for def: {:?}", ty.sty), + _ => bug!("inappropriate type for def: {:?}", ty), }; PatternKind::Variant { adt_def, diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs index cb4a72387fa16..9cdf996ac0b6b 100644 --- a/src/librustc_mir/hair/util.rs +++ b/src/librustc_mir/hair/util.rs @@ -16,7 +16,8 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { let user_provided_types = self.tables().user_provided_types(); let mut user_ty = *user_provided_types.get(hir_id)?; debug!("user_subts_applied_to_ty_of_hir_id: user_ty={:?}", user_ty); - match &self.tables().node_id_to_type(hir_id).sty { + let ty = self.tables().node_id_to_type(hir_id); + match ty.sty { ty::Adt(adt_def, ..) => { if let UserType::TypeOf(ref mut did, _) = &mut user_ty.value { *did = adt_def.did; @@ -24,8 +25,11 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> { Some(user_ty) } ty::FnDef(..) => Some(user_ty), - sty => - bug!("sty: {:?} should not have user provided type {:?} recorded ", sty, user_ty), + _ => bug!( + "ty: {:?} should not have user provided type {:?} recorded ", + ty, + user_ty + ), } } } diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index c3b71be8354da..96f2f610d37ac 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -90,7 +90,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let fn_ptr = self.memory.create_fn_alloc(instance?).with_default_tag(); self.write_scalar(Scalar::Ptr(fn_ptr.into()), dest)?; } - ref other => bug!("reify fn pointer on {:?}", other), + _ => bug!("reify fn pointer on {:?}", src.layout.ty), } } @@ -101,7 +101,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> // No change to value self.write_immediate(*src, dest)?; } - ref other => bug!("fn to unsafe fn cast on {:?}", other), + _ => bug!("fn to unsafe fn cast on {:?}", dest.layout.ty), } } @@ -120,7 +120,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let val = Immediate::Scalar(Scalar::Ptr(fn_ptr.into()).into()); self.write_immediate(val, dest)?; } - ref other => bug!("closure fn pointer on {:?}", other), + _ => bug!("closure fn pointer on {:?}", src.layout.ty), } } } diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 5e3335f4c7219..34858baa9ba97 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -349,7 +349,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> use rustc_apfloat::ieee::{Single, Double}; use rustc_apfloat::Float; - trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty.sty); + trace!("Running unary op {:?}: {:?} ({:?})", un_op, val, layout.ty); match layout.ty.sty { ty::Bool => { diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index f3a948a6ca3e7..1512016355acd 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -349,7 +349,7 @@ where ty::Ref(_, _, mutbl) => Some(mutbl), ty::Adt(def, _) if def.is_box() => Some(hir::MutMutable), ty::RawPtr(_) => None, - _ => bug!("Unexpected pointer type {}", val.layout.ty.sty), + _ => bug!("Unexpected pointer type {}", val.layout.ty), }; place.mplace.ptr = M::tag_dereference(self, place, mutbl)?; Ok(place) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index e713ab17c3af5..ad21e0d339303 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -825,7 +825,7 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, match tail.sty { ty::Foreign(..) => false, ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, - _ => bug!("unexpected unsized tail: {:?}", tail.sty), + _ => bug!("unexpected unsized tail: {:?}", tail), } }; if type_has_metadata(inner_source) { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 61674070fbcb2..173a851a2f524 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -935,7 +935,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`). fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>) -> ty::ExistentialTraitRef<'tcx> { - assert_eq!(trait_ref.self_ty().sty, TRAIT_OBJECT_DUMMY_SELF); + if trait_ref.self_ty().sty != TRAIT_OBJECT_DUMMY_SELF { + bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref); + } ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref) } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 141b8222b1f33..22b33e1d2f613 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -88,7 +88,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // See the examples in `run-pass/match-defbm*.rs`. let mut pat_adjustments = vec![]; while let ty::Ref(_, inner_ty, inner_mutability) = exp_ty.sty { - debug!("inspecting {:?} with type {:?}", exp_ty, exp_ty.sty); + debug!("inspecting {:?}", exp_ty); debug!("current discriminant is Ref, inserting implicit deref"); // Preserve the reference type. We'll need it later during HAIR lowering. @@ -869,7 +869,7 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); subpats.len() < variant.fields.len() && ddpos.is_some() { let substs = match pat_ty.sty { ty::Adt(_, substs) => substs, - ref ty => bug!("unexpected pattern type {:?}", ty), + _ => bug!("unexpected pattern type {:?}", pat_ty), }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c94713980d8c0..48296e8e441c6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3889,7 +3889,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty::Adt(adt, substs) => { Some((adt.variant_of_def(def), adt.did, substs)) } - _ => bug!("unexpected type: {:?}", ty.sty) + _ => bug!("unexpected type: {:?}", ty) } } Def::Struct(..) | Def::Union(..) | Def::TyAlias(..) | @@ -5231,8 +5231,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.node); let sp = ty.span; let ty = AstConv::ast_ty_to_ty(self, ty); - debug!("suggest_missing_return_type: return type sty {:?}", ty.sty); - debug!("suggest_missing_return_type: expected type sty {:?}", ty.sty); + debug!("suggest_missing_return_type: return type {:?}", ty); + debug!("suggest_missing_return_type: expected type {:?}", ty); if ty.sty == expected.sty { err.span_label(sp, format!("expected `{}` because of return type", expected)); diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index ffd7c2114e5ab..6eb333d4d761d 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -94,19 +94,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ); // Extract the type of the closure. - let (closure_def_id, substs) = match self.node_ty(closure_hir_id).sty { + let ty = self.node_ty(closure_hir_id); + let (closure_def_id, substs) = match ty.sty { ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs)), ty::Generator(def_id, substs, _) => (def_id, UpvarSubsts::Generator(substs)), ty::Error => { // #51714: skip analysis when we have already encountered type errors return; } - ref t => { + _ => { span_bug!( span, "type of closure expr {:?} is not a closure {:?}", closure_node_id, - t + ty ); } }; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 6cae8d6fc5b94..efbc4aef5f235 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -600,7 +600,7 @@ fn check_existential_types<'a, 'fcx, 'gcx, 'tcx>( span: Span, ty: Ty<'tcx>, ) -> Vec> { - trace!("check_existential_types: {:?}, {:?}", ty, ty.sty); + trace!("check_existential_types: {:?}", ty); let mut substituted_predicates = Vec::new(); ty.fold_with(&mut ty::fold::BottomUpFolder { tcx: fcx.tcx, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 238b087fe32f8..3e4e3459fd722 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -479,7 +479,7 @@ impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> { instantiated_ty.fold_with(&mut BottomUpFolder { tcx: self.tcx().global_tcx(), fldop: |ty| { - trace!("checking type {:?}: {:#?}", ty, ty.sty); + trace!("checking type {:?}", ty); // find a type parameter if let ty::Param(..) = ty.sty { // look it up in the substitution list From d695d7d6234552790fae541204c4ea024b02bf82 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 20:10:47 +0200 Subject: [PATCH 10/68] rustc: implement fmt::{Debug,Display} on Ty instead of TyS. --- src/librustc/util/ppaux.rs | 2 +- src/librustc_mir/util/graphviz.rs | 2 +- src/librustc_privacy/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fb4aa6872dc4a..85204320cf0ea 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1107,7 +1107,7 @@ define_print! { } define_print! { - ('tcx) ty::TyS<'tcx>, (self, f, cx) { + ('tcx) ty::Ty<'tcx>, (self, f, cx) { display { match self.sty { Bool => write!(f, "bool"), diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index b68898f713021..e7cc3ba0c4d72 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -138,7 +138,7 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>, write!(w, "{:?}: {}", Place::Local(arg), escape(&mir.local_decls[arg].ty))?; } - write!(w, ") -> {}", escape(mir.return_ty()))?; + write!(w, ") -> {}", escape(&mir.return_ty()))?; write!(w, r#"
"#)?; for local in mir.vars_and_temps_iter() { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index dcbb9ff4a7576..9004f4c35e6b5 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -137,7 +137,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> ty::FnDef(def_id, ..) | ty::Closure(def_id, ..) | ty::Generator(def_id, ..) => { - if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + if self.def_id_visitor.visit_def_id(def_id, "type", &ty) { return true; } if self.def_id_visitor.shallow() { From 6dc5fbc901bae38fad49f567285bcff40e86b35e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 17:40:23 +0200 Subject: [PATCH 11/68] rustc: tie the 'tcx between Print and PrintCx in ty::print. --- .../infer/outlives/free_region_map.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 4 +- src/librustc/ty/print.rs | 16 ++- src/librustc/ty/structural_impls.rs | 20 +++ src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 4 +- src/librustc/util/ppaux.rs | 135 ++++++++---------- 9 files changed, 97 insertions(+), 90 deletions(-) diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs index a6703c9d679da..219399c06275d 100644 --- a/src/librustc/infer/outlives/free_region_map.rs +++ b/src/librustc/infer/outlives/free_region_map.rs @@ -91,7 +91,7 @@ impl_stable_hash_for!(struct FreeRegionMap<'tcx> { impl<'a, 'tcx> Lift<'tcx> for FreeRegionMap<'a> { type Lifted = FreeRegionMap<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option> { - self.relation.maybe_map(|&fr| fr.lift_to_tcx(tcx)) + self.relation.maybe_map(|&fr| tcx.lift(&fr)) .map(|relation| FreeRegionMap { relation }) } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 812ce2a7d7895..a6e9e7147adb3 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2377,7 +2377,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { let variant_def = &adt_def.variants[variant]; - ppaux::parameterized(fmt, substs, variant_def.did, &[])?; + ppaux::parameterized(fmt, variant_def.did, substs)?; match variant_def.ctor_kind { CtorKind::Const => Ok(()), diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index bc43fedef0f34..fd0c8170510c9 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -174,7 +174,7 @@ impl<'tcx> InstanceDef<'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ppaux::parameterized(f, self.substs, self.def_id(), &[])?; + ppaux::parameterized(f, self.def_id(), self.substs)?; match self.def { InstanceDef::Item(_) => Ok(()), InstanceDef::VtableShim(_) => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a41d50895ab21..291b4c7cf8640 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -973,7 +973,7 @@ impl<'a, 'gcx, 'tcx> Generics { } /// Bounds on generics. -#[derive(Clone, Default)] +#[derive(Clone, Default, Debug)] pub struct GenericPredicates<'tcx> { pub parent: Option, pub predicates: Vec<(Predicate<'tcx>, Span)>, @@ -1475,7 +1475,7 @@ impl<'tcx> Predicate<'tcx> { /// `[[], [U:Bar]]`. Now if there were some particular reference /// like `Foo`, then the `InstantiatedPredicates` would be `[[], /// [usize:Bar]]`. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct InstantiatedPredicates<'tcx> { pub predicates: Vec>, } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 617e3183f576e..64998ad66eb3d 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -56,32 +56,36 @@ impl PrintCx<'a, 'gcx, 'tcx> { } pub trait Print<'tcx> { - fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result; - fn print_to_string(&self, cx: &mut PrintCx<'_, '_, '_>) -> String { + fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result; + fn print_to_string(&self, cx: &mut PrintCx<'_, '_, 'tcx>) -> String { let mut result = String::new(); let _ = self.print(&mut result, cx); result } - fn print_display(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result { + fn print_display( + &self, + f: &mut F, + cx: &mut PrintCx<'_, '_, 'tcx>, + ) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = false; let result = self.print(f, cx); cx.is_debug = old_debug; result } - fn print_display_to_string(&self, cx: &mut PrintCx<'_, '_, '_>) -> String { + fn print_display_to_string(&self, cx: &mut PrintCx<'_, '_, 'tcx>) -> String { let mut result = String::new(); let _ = self.print_display(&mut result, cx); result } - fn print_debug(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result { + fn print_debug(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = true; let result = self.print(f, cx); cx.is_debug = old_debug; result } - fn print_debug_to_string(&self, cx: &mut PrintCx<'_, '_, '_>) -> String { + fn print_debug_to_string(&self, cx: &mut PrintCx<'_, '_, 'tcx>) -> String { let mut result = String::new(); let _ = self.print_debug(&mut result, cx); result diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 28f5a65374d98..688eb39635f17 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -47,7 +47,10 @@ CloneTypeFoldableAndLiftImpls! { // really meant to be folded. In general, we can only fold a fully // general `Region`. ::ty::BoundRegion, + ::ty::Placeholder<::ty::BoundRegion>, ::ty::ClosureKind, + ::ty::FreeRegion, + ::ty::InferTy, ::ty::IntVarValue, ::ty::ParamTy, ::ty::UniverseIndex, @@ -472,6 +475,13 @@ impl<'a, 'tcx> Lift<'tcx> for ty::InstanceDef<'a> { } } +BraceStructLiftImpl! { + impl<'a, 'tcx> Lift<'tcx> for ty::TypeAndMut<'a> { + type Lifted = ty::TypeAndMut<'tcx>; + ty, mutbl + } +} + BraceStructLiftImpl! { impl<'a, 'tcx> Lift<'tcx> for ty::Instance<'a> { type Lifted = ty::Instance<'tcx>; @@ -486,6 +496,16 @@ BraceStructLiftImpl! { } } +// FIXME(eddyb) this is like what `CloneTypeFoldableAndLiftImpls!` +// generates, except that macro *also* generates a foldable impl, +// which we don't want (with it we'd risk bypassing `fold_region`). +impl<'tcx> Lift<'tcx> for ty::RegionKind { + type Lifted = ty::RegionKind; + fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + Some(self.clone()) + } +} + BraceStructLiftImpl! { impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> { type Lifted = ty::Const<'tcx>; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f4185c9201540..1b9008b9344fe 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -608,7 +608,7 @@ impl<'tcx> List> { #[inline] pub fn projection_bounds<'a>(&'a self) -> - impl Iterator> + 'a { + impl Iterator> + Clone + 'a { self.iter().filter_map(|predicate| { match *predicate { ExistentialPredicate::Projection(p) => Some(p), diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 64e7af815b4bf..889e498cf3ee1 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -122,8 +122,8 @@ impl<'a, 'tcx> Lift<'tcx> for Kind<'a> { fn lift_to_tcx<'cx, 'gcx>(&self, tcx: TyCtxt<'cx, 'gcx, 'tcx>) -> Option { match self.unpack() { - UnpackedKind::Lifetime(a) => a.lift_to_tcx(tcx).map(|a| a.into()), - UnpackedKind::Type(a) => a.lift_to_tcx(tcx).map(|a| a.into()), + UnpackedKind::Lifetime(a) => tcx.lift(&a).map(|a| a.into()), + UnpackedKind::Type(a) => tcx.lift(&a).map(|a| a.into()), } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 85204320cf0ea..b65fe7cc78125 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,7 @@ use hir::def_id::DefId; use hir::map::definitions::DefPathData; use middle::region; -use ty::subst::{self, Subst}; +use ty::subst::{Subst, Substs}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; @@ -13,6 +13,7 @@ use ty::print::{PrintCx, Print}; use std::cell::Cell; use std::fmt; +use std::iter; use std::usize; use rustc_target::spec::abi::Abi; @@ -182,7 +183,9 @@ impl RegionHighlightMode { macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(|mut cx| $with(self, f, &mut cx)) + PrintCx::with(|mut cx| { + $with(&cx.tcx.lift(self).expect("could not lift for printing"), f, &mut cx) + }) } }; } @@ -215,7 +218,7 @@ macro_rules! gen_print_impl { fn print( &$self, $f: &mut F, - $cx: &mut PrintCx<'_, '_, '_>, + $cx: &mut PrintCx<'_, '_, 'tcx>, ) -> fmt::Result { if $cx.is_debug $dbg else $disp @@ -227,7 +230,7 @@ macro_rules! gen_print_impl { fn print( &$self, $f: &mut F, - $cx: &mut PrintCx<'_, '_, '_>, + $cx: &mut PrintCx<'_, '_, 'tcx>, ) -> fmt::Result { if $cx.is_debug $dbg else $disp @@ -285,9 +288,9 @@ macro_rules! print { impl PrintCx<'a, 'gcx, 'tcx> { fn fn_sig(&mut self, f: &mut F, - inputs: &[Ty<'_>], + inputs: &[Ty<'tcx>], variadic: bool, - output: Ty<'_>) + output: Ty<'tcx>) -> fmt::Result { write!(f, "(")?; let mut inputs = inputs.iter(); @@ -308,12 +311,13 @@ impl PrintCx<'a, 'gcx, 'tcx> { Ok(()) } - fn parameterized(&mut self, - f: &mut F, - substs: &subst::Substs<'_>, - did: DefId, - projections: &[ty::ProjectionPredicate<'_>]) - -> fmt::Result { + fn parameterized( + &mut self, + f: &mut F, + did: DefId, + substs: &Substs<'tcx>, + projections: impl Iterator> + Clone, + ) -> fmt::Result { let key = self.tcx.def_key(did); let verbose = self.is_verbose; @@ -409,7 +413,6 @@ impl PrintCx<'a, 'gcx, 'tcx> { *has_default.unwrap_or(&false) }; if has_default { - let substs = self.tcx.lift(&substs).expect("could not lift for printing"); let types = substs.types().rev().skip(child_types); for ((def_id, has_default), actual) in type_params.zip(types) { if !has_default { @@ -426,10 +429,12 @@ impl PrintCx<'a, 'gcx, 'tcx> { print!(f, self, write("{}", self.tcx.item_path_str(path_def_id)))?; let fn_trait_kind = self.tcx.lang_items().fn_trait_kind(path_def_id); - if !verbose && fn_trait_kind.is_some() && projections.len() == 1 { - let projection_ty = projections[0].ty; + if !verbose && fn_trait_kind.is_some() { if let Tuple(ref args) = substs.type_at(1).sty { - return self.fn_sig(f, args, false, projection_ty); + let mut projections = projections.clone(); + if let (Some(proj), None) = (projections.next(), projections.next()) { + return self.fn_sig(f, args, false, proj.ty); + } } } @@ -488,7 +493,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { start_or_continue(f, "<", ", ")?; print!(f, self, write("{}=", - self.tcx.associated_item(projection.projection_ty.item_def_id).ident), + self.tcx.associated_item(projection.item_def_id).ident), print_display(projection.ty))?; } @@ -520,7 +525,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { Ok(()) } - fn in_binder(&mut self, f: &mut F, value: ty::Binder) -> fmt::Result + fn in_binder(&mut self, f: &mut F, value: &ty::Binder) -> fmt::Result where T: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write { fn name_by_region_index(index: usize) -> InternedString { @@ -537,7 +542,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { // 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_late_bound_region_info(value); } let mut empty = true; @@ -552,7 +557,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { let old_region_index = self.region_index; let mut region_index = old_region_index; - let new_value = self.tcx.replace_late_bound_regions(&value, |br| { + let new_value = self.tcx.replace_late_bound_regions(value, |br| { let _ = start_or_continue(f, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { @@ -594,16 +599,15 @@ impl PrintCx<'a, 'gcx, 'tcx> { } } -pub fn parameterized(f: &mut F, - substs: &subst::Substs<'_>, - did: DefId, - projections: &[ty::ProjectionPredicate<'_>]) - -> fmt::Result { - PrintCx::with(|mut cx| cx.parameterized(f, substs, did, projections)) +pub fn parameterized(f: &mut F, did: DefId, substs: &Substs<'_>) -> fmt::Result { + PrintCx::with(|mut cx| { + let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); + cx.parameterized(f, did, substs, iter::empty()) + }) } impl<'a, 'tcx, T: Print<'tcx>> Print<'tcx> for &'a T { - fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, '_>) -> fmt::Result { + fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result { (*self).print(f, cx) } } @@ -618,16 +622,13 @@ define_print! { let mut first = true; if let Some(principal) = self.principal() { - let principal = cx.tcx - .lift(&principal) - .expect("could not lift for printing") - .with_self_ty(tcx, dummy_self); - let projections = self.projection_bounds().map(|p| { - cx.tcx.lift(&p) - .expect("could not lift for printing") - .with_self_ty(cx.tcx, dummy_self) - }).collect::>(); - cx.parameterized(f, principal.substs, principal.def_id, &projections)?; + let principal = principal.with_self_ty(cx.tcx, dummy_self); + cx.parameterized( + f, + principal.def_id, + principal.substs, + self.projection_bounds(), + )?; first = false; } @@ -744,15 +745,15 @@ define_print! { define_print! { ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) { display { - cx.parameterized(f, self.substs, self.def_id, &[]) - } - debug { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let trait_ref = *cx.tcx.lift(&ty::Binder::bind(*self)) - .expect("could not lift for printing") - .with_self_ty(cx.tcx, dummy_self).skip_binder(); - cx.parameterized(f, trait_ref.substs, trait_ref.def_id, &[]) + let trait_ref = *ty::Binder::bind(*self) + .with_self_ty(cx.tcx, dummy_self) + .skip_binder(); + cx.parameterized(f, trait_ref.def_id, trait_ref.substs, iter::empty()) + } + debug { + self.print_display(f, cx) } } } @@ -946,22 +947,6 @@ define_print! { } } -define_print! { - ('tcx) ty::GenericPredicates<'tcx>, (self, f, cx) { - debug { - write!(f, "GenericPredicates({:?})", self.predicates) - } - } -} - -define_print! { - ('tcx) ty::InstantiatedPredicates<'tcx>, (self, f, cx) { - debug { - write!(f, "InstantiatedPredicates({:?})", self.predicates) - } - } -} - define_print! { ('tcx) ty::FnSig<'tcx>, (self, f, cx) { display { @@ -1081,8 +1066,7 @@ define_print_multi! { ] (self, f, cx) { display { - cx.in_binder(f, cx.tcx.lift(self) - .expect("could not lift for printing")) + cx.in_binder(f, self) } } } @@ -1090,7 +1074,7 @@ define_print_multi! { define_print! { ('tcx) ty::TraitRef<'tcx>, (self, f, cx) { display { - cx.parameterized(f, self.substs, self.def_id, &[]) + cx.parameterized(f, self.def_id, self.substs, iter::empty()) } debug { // when printing out the debug representation, we don't need @@ -1100,7 +1084,7 @@ define_print! { write("<"), print(self.self_ty()), write(" as "))?; - cx.parameterized(f, self.substs, self.def_id, &[])?; + cx.parameterized(f, self.def_id, self.substs, iter::empty())?; write!(f, ">") } } @@ -1149,11 +1133,9 @@ define_print! { write!(f, ")") } FnDef(def_id, substs) => { - let substs = cx.tcx.lift(&substs) - .expect("could not lift for printing"); let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); print!(f, cx, print(sig), write(" {{"))?; - cx.parameterized(f, substs, def_id, &[])?; + cx.parameterized(f, def_id, substs, iter::empty())?; write!(f, "}}") } FnPtr(ref bare_fn) => { @@ -1175,7 +1157,7 @@ define_print! { ty::BoundTyKind::Param(p) => write!(f, "{}", p), } } - Adt(def, substs) => cx.parameterized(f, substs, def.did, &[]), + Adt(def, substs) => cx.parameterized(f, def.did, substs, iter::empty()), Dynamic(data, r) => { let r = r.print_to_string(cx); if !r.is_empty() { @@ -1189,7 +1171,7 @@ define_print! { Ok(()) } } - Foreign(def_id) => parameterized(f, subst::Substs::empty(), def_id, &[]), + Foreign(def_id) => cx.parameterized(f, def_id, Substs::empty(), iter::empty()), Projection(ref data) => data.print(f, cx), UnnormalizedProjection(ref data) => { write!(f, "Unnormalized(")?; @@ -1220,8 +1202,6 @@ define_print! { } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let substs = cx.tcx.lift(&substs) - .expect("could not lift for printing"); let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs); let mut first = true; @@ -1288,8 +1268,7 @@ define_print! { print!(f, cx, write(" "), print(witness), write("]")) }, GeneratorWitness(types) => { - cx.in_binder(f, cx.tcx.lift(&types) - .expect("could not lift for printing")) + cx.in_binder(f, &types) } Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); @@ -1362,8 +1341,12 @@ define_print! { } } -define_print! { - ('tcx, T: Print<'tcx> + fmt::Debug, U: Print<'tcx> + fmt::Debug) ty::OutlivesPredicate, +// Similar problem to `Binder`, can't define a generic impl. +define_print_multi! { + [ + ('tcx) ty::OutlivesPredicate, ty::Region<'tcx>>, + ('tcx) ty::OutlivesPredicate, ty::Region<'tcx>> + ] (self, f, cx) { display { print!(f, cx, print(self.0), write(" : "), print(self.1)) @@ -1451,7 +1434,7 @@ define_print! { } ty::Predicate::ConstEvaluatable(def_id, substs) => { write!(f, "the constant `")?; - cx.parameterized(f, substs, def_id, &[])?; + cx.parameterized(f, def_id, substs, iter::empty())?; write!(f, "` can be evaluated") } } From a5e719fdcd9b0d40ad474e0cb04b6c019ceb1f26 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 8 Dec 2018 01:13:23 +0200 Subject: [PATCH 12/68] rustc: use define_print! to implement fmt::{Display,Debug} for Kind. --- src/librustc/ty/subst.rs | 19 ------------------- src/librustc/util/ppaux.rs | 19 ++++++++++++++++++- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 889e498cf3ee1..b0234df96e1b9 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -11,7 +11,6 @@ use smallvec::SmallVec; use core::intrinsics; use std::cmp::Ordering; -use std::fmt; use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; @@ -99,24 +98,6 @@ impl<'tcx> Kind<'tcx> { } } -impl<'tcx> fmt::Debug for Kind<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.unpack() { - UnpackedKind::Lifetime(lt) => write!(f, "{:?}", lt), - UnpackedKind::Type(ty) => write!(f, "{:?}", ty), - } - } -} - -impl<'tcx> fmt::Display for Kind<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.unpack() { - UnpackedKind::Lifetime(lt) => write!(f, "{}", lt), - UnpackedKind::Type(ty) => write!(f, "{}", ty), - } - } -} - impl<'a, 'tcx> Lift<'tcx> for Kind<'a> { type Lifted = Kind<'tcx>; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index b65fe7cc78125..aa66d99eea002 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,7 @@ use hir::def_id::DefId; use hir::map::definitions::DefPathData; use middle::region; -use ty::subst::{Subst, Substs}; +use ty::subst::{Kind, Subst, Substs, UnpackedKind}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; @@ -1460,3 +1460,20 @@ define_print! { } } } + +define_print! { + ('tcx) Kind<'tcx>, (self, f, cx) { + display { + match self.unpack() { + UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), + UnpackedKind::Type(ty) => print!(f, cx, print(ty)), + } + } + debug { + match self.unpack() { + UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), + UnpackedKind::Type(ty) => print!(f, cx, print(ty)), + } + } + } +} From f7d55939db470177da844b88ffb56202730ac83c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 8 Dec 2018 11:26:34 +0200 Subject: [PATCH 13/68] rustc: rewrite PrintCx::parameterized to be much simpler and more general. --- src/librustc/ty/sty.rs | 2 +- src/librustc/util/ppaux.rs | 312 ++++++++++++++----------------------- 2 files changed, 117 insertions(+), 197 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 1b9008b9344fe..f4185c9201540 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -608,7 +608,7 @@ impl<'tcx> List> { #[inline] pub fn projection_bounds<'a>(&'a self) -> - impl Iterator> + Clone + 'a { + impl Iterator> + 'a { self.iter().filter_map(|predicate| { match *predicate { ExistentialPredicate::Projection(p) => Some(p), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index aa66d99eea002..dc18b3e9aa9a4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,7 +8,7 @@ use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; -use ty::{self, Ty, TypeFoldable, GenericParamCount, GenericParamDefKind}; +use ty::{self, Ty, TypeFoldable}; use ty::print::{PrintCx, Print}; use std::cell::Cell; @@ -314,215 +314,125 @@ impl PrintCx<'a, 'gcx, 'tcx> { fn parameterized( &mut self, f: &mut F, - did: DefId, + mut def_id: DefId, substs: &Substs<'tcx>, - projections: impl Iterator> + Clone, + projections: impl Iterator>, ) -> fmt::Result { - let key = self.tcx.def_key(did); - - let verbose = self.is_verbose; - let mut num_supplied_defaults = 0; - let has_self; - let mut own_counts: GenericParamCount = Default::default(); - let mut is_value_path = false; - let mut item_name = Some(key.disambiguated_data.data.as_interned_str()); - let mut path_def_id = did; - { - // Unfortunately, some kinds of items (e.g., closures) don't have - // generics. So walk back up the find the closest parent that DOES - // have them. - let mut item_def_id = did; - loop { - let key = self.tcx.def_key(item_def_id); - match key.disambiguated_data.data { - DefPathData::AssocTypeInTrait(_) | - DefPathData::AssocTypeInImpl(_) | - DefPathData::AssocExistentialInImpl(_) | - DefPathData::Trait(_) | - DefPathData::TraitAlias(_) | - DefPathData::Impl | - DefPathData::TypeNs(_) => { - break; - } - DefPathData::ValueNs(_) | - DefPathData::EnumVariant(_) => { - is_value_path = true; - break; - } - DefPathData::CrateRoot | - DefPathData::Misc | - DefPathData::Module(_) | - DefPathData::MacroDef(_) | - DefPathData::ClosureExpr | - DefPathData::TypeParam(_) | - DefPathData::LifetimeParam(_) | - DefPathData::Field(_) | - DefPathData::StructCtor | - DefPathData::AnonConst | - DefPathData::ImplTrait | - DefPathData::GlobalMetaData(_) => { - // if we're making a symbol for something, there ought - // to be a value or type-def or something in there - // *somewhere* - item_def_id.index = key.parent.unwrap_or_else(|| { - bug!("finding type for {:?}, encountered def-id {:?} with no \ - parent", did, item_def_id); - }); - } - } + let mut key = self.tcx.def_key(def_id); + let is_value_ns = match key.disambiguated_data.data { + DefPathData::ValueNs(_) | + DefPathData::EnumVariant(_) => true, + + // Skip `StructCtor` so that `Struct::` will be printed, + // instead of the less pretty `Struct::{{constructor}}`. + DefPathData::StructCtor => { + def_id.index = key.parent.unwrap(); + key = self.tcx.def_key(def_id); + true } - let mut generics = self.tcx.generics_of(item_def_id); - let child_own_counts = generics.own_counts(); - has_self = generics.has_self; - - let mut child_types = 0; - if let Some(def_id) = generics.parent { - // Methods. - assert!(is_value_path); - child_types = child_own_counts.types; - generics = self.tcx.generics_of(def_id); - own_counts = generics.own_counts(); - - if has_self { - print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?; - } - path_def_id = def_id; - } else { - item_name = None; - - if is_value_path { - // Functions. - assert_eq!(has_self, false); - } else { - // Types and traits. - own_counts = child_own_counts; - } - } + _ => false, + }; - if !verbose { - let mut type_params = - generics.params.iter().rev().filter_map(|param| match param.kind { - GenericParamDefKind::Lifetime => None, - GenericParamDefKind::Type { has_default, .. } => { - Some((param.def_id, has_default)) - } - }).peekable(); - let has_default = { - let has_default = type_params.peek().map(|(_, has_default)| has_default); - *has_default.unwrap_or(&false) - }; - if has_default { - let types = substs.types().rev().skip(child_types); - for ((def_id, has_default), actual) in type_params.zip(types) { - if !has_default { - break; - } - if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { - break; - } - num_supplied_defaults += 1; - } - } + let generics = self.tcx.generics_of(def_id); + + if let Some(parent_def_id) = generics.parent { + assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id }); + + let parent_generics = self.tcx.generics_of(parent_def_id); + let parent_has_own_self = + parent_generics.has_self && parent_generics.parent_count == 0; + if parent_has_own_self { + print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?; } - } - print!(f, self, write("{}", self.tcx.item_path_str(path_def_id)))?; - let fn_trait_kind = self.tcx.lang_items().fn_trait_kind(path_def_id); - - if !verbose && fn_trait_kind.is_some() { - if let Tuple(ref args) = substs.type_at(1).sty { - let mut projections = projections.clone(); - if let (Some(proj), None) = (projections.next(), projections.next()) { - return self.fn_sig(f, args, false, proj.ty); - } + self.parameterized(f, parent_def_id, substs, iter::empty())?; + if parent_has_own_self { + write!(f, ">")?; } + + write!(f, "::{}", key.disambiguated_data.data.as_interned_str())?; + } else { + print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?; } - let empty = Cell::new(true); - let start_or_continue = |f: &mut F, start: &str, cont: &str| { - if empty.get() { - empty.set(false); + let mut empty = true; + let mut start_or_continue = |f: &mut F, start: &str, cont: &str| { + if empty { + empty = false; write!(f, "{}", start) } else { write!(f, "{}", cont) } }; - let print_regions = |f: &mut F, start: &str, skip, count| { - // Don't print any regions if they're all erased. - let regions = || substs.regions().skip(skip).take(count); - if regions().all(|r: ty::Region<'_>| *r == ty::ReErased) { - return Ok(()); + let start = if is_value_ns { "::<" } else { "<" }; + + let has_own_self = generics.has_self && generics.parent_count == 0; + let params = &generics.params[has_own_self as usize..]; + + // Don't print any regions if they're all erased. + let print_regions = params.iter().any(|param| { + match substs[param.index as usize].unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, } + }); + + // Don't print args that are the defaults of their respective parameters. + let num_supplied_defaults = if self.is_verbose { + 0 + } else { + params.iter().rev().take_while(|param| { + match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default && substs[param.index as usize] == Kind::from( + self.tcx.type_of(param.def_id).subst(self.tcx, substs) + ) + } + } + }).count() + }; - for region in regions() { - let region: ty::Region<'_> = region; - start_or_continue(f, start, ", ")?; - if verbose { - write!(f, "{:?}", region)?; - } else { - let s = region.to_string(); - if s.is_empty() { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - write!(f, "'_")?; + for param in ¶ms[..params.len() - num_supplied_defaults] { + match substs[param.index as usize].unpack() { + UnpackedKind::Lifetime(region) => { + if !print_regions { + continue; + } + start_or_continue(f, start, ", ")?; + if self.is_verbose { + write!(f, "{:?}", region)?; } else { - write!(f, "{}", s)?; + let s = region.to_string(); + if s.is_empty() { + // This happens when the value of the region + // parameter is not easily serialized. This may be + // because the user omitted it in the first place, + // or because it refers to some block in the code, + // etc. I'm not sure how best to serialize this. + write!(f, "'_")?; + } else { + write!(f, "{}", s)?; + } } } + UnpackedKind::Type(ty) => { + start_or_continue(f, start, ", ")?; + ty.print_display(f, self)?; + } } - - Ok(()) - }; - - print_regions(f, "<", 0, own_counts.lifetimes)?; - - let tps = substs.types() - .take(own_counts.types - num_supplied_defaults) - .skip(has_self as usize); - - for ty in tps { - start_or_continue(f, "<", ", ")?; - ty.print_display(f, self)?; } for projection in projections { - start_or_continue(f, "<", ", ")?; + start_or_continue(f, start, ", ")?; print!(f, self, write("{}=", self.tcx.associated_item(projection.item_def_id).ident), print_display(projection.ty))?; } - start_or_continue(f, "", ">")?; - - // For values, also print their name and type parameters. - if is_value_path { - empty.set(true); - - if has_self { - write!(f, ">")?; - } - - if let Some(item_name) = item_name { - write!(f, "::{}", item_name)?; - } - - print_regions(f, "::<", own_counts.lifetimes, usize::MAX)?; - - // FIXME: consider being smart with defaults here too - for ty in substs.types().skip(own_counts.types) { - start_or_continue(f, "::<", ", ")?; - ty.print_display(f, self)?; - } - - start_or_continue(f, "", ">")?; - } - - Ok(()) + start_or_continue(f, "", ">") } fn in_binder(&mut self, f: &mut F, value: &ty::Binder) -> fmt::Result @@ -616,19 +526,34 @@ define_print! { ('tcx) &'tcx ty::List>, (self, f, cx) { display { // Generate the main trait ref, including associated types. - - // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); let mut first = true; if let Some(principal) = self.principal() { - let principal = principal.with_self_ty(cx.tcx, dummy_self); - cx.parameterized( - f, - principal.def_id, - principal.substs, - self.projection_bounds(), - )?; + let mut resugared_principal = false; + + // Special-case `Fn(...) -> ...` and resugar it. + if !cx.is_verbose && cx.tcx.lang_items().fn_trait_kind(principal.def_id).is_some() { + if let Tuple(ref args) = principal.substs.type_at(0).sty { + let mut projections = self.projection_bounds(); + if let (Some(proj), None) = (projections.next(), projections.next()) { + print!(f, cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?; + cx.fn_sig(f, args, false, proj.ty)?; + resugared_principal = true; + } + } + } + + if !resugared_principal { + // Use a type that can't appear in defaults of type parameters. + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); + let principal = principal.with_self_ty(cx.tcx, dummy_self); + cx.parameterized( + f, + principal.def_id, + principal.substs, + self.projection_bounds(), + )?; + } first = false; } @@ -1393,12 +1318,7 @@ define_print! { define_print! { ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) { display { - // FIXME(tschottdorf): use something like - // parameterized(f, self.substs, self.item_def_id, &[]) - // (which currently ICEs). - let trait_ref = self.trait_ref(cx.tcx); - let item_name = cx.tcx.associated_item(self.item_def_id).ident; - print!(f, cx, print_debug(trait_ref), write("::{}", item_name)) + cx.parameterized(f, self.item_def_id, self.substs, iter::empty()) } } } From 54faa670de7e8841c4e6aa433ec67d17fa11373d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Dec 2018 17:54:18 +0200 Subject: [PATCH 14/68] rustc: support impl's in PrintCx::parameterized. --- src/librustc/util/ppaux.rs | 16 ++++++++++++++++ src/test/ui/hygiene/impl_items.rs | 2 +- src/test/ui/hygiene/impl_items.stderr | 4 ++-- src/test/ui/issues/issue-22638.rs | 2 +- src/test/ui/issues/issue-22638.stderr | 4 ++-- src/test/ui/issues/issue-24322.stderr | 2 +- src/test/ui/issues/issue-29124.rs | 2 +- src/test/ui/issues/issue-29124.stderr | 2 +- src/test/ui/issues/issue-39559-2.stderr | 4 ++-- .../privacy/associated-item-privacy-inherent.rs | 6 +++--- .../associated-item-privacy-inherent.stderr | 6 +++--- .../ui/qualified/qualified-path-params.stderr | 2 +- 12 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index dc18b3e9aa9a4..55d24c99506a6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -352,6 +352,22 @@ impl PrintCx<'a, 'gcx, 'tcx> { write!(f, "::{}", key.disambiguated_data.data.as_interned_str())?; } else { + // Try to print `impl`s more like how you'd refer to their associated items. + if let DefPathData::Impl = key.disambiguated_data.data { + if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { + // HACK(eddyb) this is in lieu of more specific disambiguation. + print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?; + + let trait_ref = trait_ref.subst(self.tcx, substs); + print!(f, self, print_debug(trait_ref))?; + } else { + let self_ty = self.tcx.type_of(def_id).subst(self.tcx, substs); + // FIXME(eddyb) omit the <> where possible. + print!(f, self, write("<"), print(self_ty), write(">"))?; + } + return Ok(()); + } + print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?; } diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs index 37794c6e0773c..d628573d51707 100644 --- a/src/test/ui/hygiene/impl_items.rs +++ b/src/test/ui/hygiene/impl_items.rs @@ -9,7 +9,7 @@ mod foo { } pub macro m() { - let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private + let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {::f}` is private } } diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr index cb3705e5513cc..487d9059cf97b 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -1,7 +1,7 @@ -error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private +error: type `for<'r> fn(&'r foo::S) {::f}` is private --> $DIR/impl_items.rs:12:23 | -LL | let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private +LL | let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {::f}` is private | ^ ... LL | foo::m!(); diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs index fab24404eba7d..ff58c7aaced03 100644 --- a/src/test/ui/issues/issue-22638.rs +++ b/src/test/ui/issues/issue-22638.rs @@ -50,7 +50,7 @@ struct D (Box); impl D { pub fn matches(&self, f: &F) { - //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure + //~^ ERROR reached the type-length limit while instantiating `::matches::<[closure let &D(ref a) = self; a.matches(f) } diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr index ba7d5f070170d..6d23c896f594f 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -1,8 +1,8 @@ -error: reached the type-length limit while instantiating `D::matches::$CLOSURE` +error: reached the type-length limit while instantiating `::matches::$CLOSURE` --> $DIR/issue-22638.rs:52:5 | LL | / pub fn matches(&self, f: &F) { -LL | | //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure +LL | | //~^ ERROR reached the type-length limit while instantiating `::matches::<[closure LL | | let &D(ref a) = self; LL | | a.matches(f) LL | | } diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr index b42854387518e..14b10dbe978a5 100644 --- a/src/test/ui/issues/issue-24322.stderr +++ b/src/test/ui/issues/issue-24322.stderr @@ -5,7 +5,7 @@ LL | let x: &fn(&B) -> u32 = &B::func; //~ ERROR mismatched types | ^^^^^^^^ expected fn pointer, found fn item | = note: expected type `&for<'r> fn(&'r B) -> u32` - found type `&for<'r> fn(&'r B) -> u32 {B::func}` + found type `&for<'r> fn(&'r B) -> u32 {::func}` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/issues/issue-29124.rs index 1cd3f84f7a227..8062045a6c058 100644 --- a/src/test/ui/issues/issue-29124.rs +++ b/src/test/ui/issues/issue-29124.rs @@ -13,7 +13,7 @@ fn func() -> Ret { fn main() { Obj::func.x(); - //~^ ERROR no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope + //~^ ERROR no method named `x` found for type `fn() -> Ret {::func}` in the current scope func.x(); //~^ ERROR no method named `x` found for type `fn() -> Ret {func}` in the current scope } diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr index 3beb728978884..67f188e0588e2 100644 --- a/src/test/ui/issues/issue-29124.stderr +++ b/src/test/ui/issues/issue-29124.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope +error[E0599]: no method named `x` found for type `fn() -> Ret {::func}` in the current scope --> $DIR/issue-29124.rs:15:15 | LL | Obj::func.x(); diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr index 700dbe3647497..ca2f2a5ba2845 100644 --- a/src/test/ui/issues/issue-39559-2.stderr +++ b/src/test/ui/issues/issue-39559-2.stderr @@ -8,7 +8,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-39559-2.rs:14:24 | LL | let array: [usize; Dim3::dim()] - | ^^^^^^^^^^^ calling non-const function `::dim` + | ^^^^^^^^^^^ calling non-const function `::dim` error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-39559-2.rs:17:15 @@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-39559-2.rs:17:15 | LL | = [0; Dim3::dim()]; - | ^^^^^^^^^^^ calling non-const function `::dim` + | ^^^^^^^^^^^ calling non-const function `::dim` error: aborting due to 4 previous errors diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.rs b/src/test/ui/privacy/associated-item-privacy-inherent.rs index c3ae920238f18..b6fd22fa669e0 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.rs +++ b/src/test/ui/privacy/associated-item-privacy-inherent.rs @@ -11,11 +11,11 @@ mod priv_nominal { pub macro mac() { let value = Pub::method; - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private + //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private value; - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private + //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private Pub.method(); - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private + //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private Pub::CONST; //~^ ERROR associated constant `CONST` is private // let _: Pub::AssocTy; diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr index 6471a7914e103..69be9d2cea6df 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.stderr +++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr @@ -1,4 +1,4 @@ -error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private +error: type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private --> $DIR/associated-item-privacy-inherent.rs:13:21 | LL | let value = Pub::method; @@ -7,7 +7,7 @@ LL | let value = Pub::method; LL | priv_nominal::mac!(); | --------------------- in this macro invocation -error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private +error: type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private --> $DIR/associated-item-privacy-inherent.rs:15:9 | LL | value; @@ -16,7 +16,7 @@ LL | value; LL | priv_nominal::mac!(); | --------------------- in this macro invocation -error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private +error: type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private --> $DIR/associated-item-privacy-inherent.rs:17:13 | LL | Pub.method(); diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr index 18fca2e304696..8a7edb6015eed 100644 --- a/src/test/ui/qualified/qualified-path-params.stderr +++ b/src/test/ui/qualified/qualified-path-params.stderr @@ -11,7 +11,7 @@ LL | 0 ..= ::A::f:: => {} //~ ERROR only char and numeric t | ^^^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types | = note: start type: {integer} - = note: end type: fn() {S::f::} + = note: end type: fn() {::f::} error: aborting due to 2 previous errors From 89d4f6b6690d27c1403f402352d8a277bf0d1145 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Dec 2018 21:05:22 +0200 Subject: [PATCH 15/68] rustc: rewrite ty::item_path to be more functional than mutation-oriented. --- src/librustc/ty/item_path.rs | 237 +++++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 65 ++++-- 2 files changed, 172 insertions(+), 130 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index f5c502810e569..d11b3c8d85f76 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -65,10 +65,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { RootMode::Local } }); - let mut buffer = LocalPathBuffer::new(mode); - debug!("item_path_str: buffer={:?} def_id={:?}", buffer, def_id); - self.push_item_path(&mut buffer, def_id); - buffer.into_string() + let mut printer = LocalPathPrinter::new(mode); + debug!("item_path_str: printer={:?} def_id={:?}", printer, def_id); + self.print_item_path(&mut printer, def_id) } /// Returns a string identifying this local node-id. @@ -79,23 +78,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this def-id. This string is /// suitable for user output. It always begins with a crate identifier. pub fn absolute_item_path_str(self, def_id: DefId) -> String { - let mut buffer = LocalPathBuffer::new(RootMode::Absolute); - debug!("absolute_item_path_str: buffer={:?} def_id={:?}", buffer, def_id); - self.push_item_path(&mut buffer, def_id); - buffer.into_string() + let mut printer = LocalPathPrinter::new(RootMode::Absolute); + debug!("absolute_item_path_str: printer={:?} def_id={:?}", printer, def_id); + self.print_item_path(&mut printer, def_id) } /// Returns the "path" to a particular crate. This can proceed in - /// various ways, depending on the `root_mode` of the `buffer`. + /// various ways, depending on the `root_mode` of the `printer`. /// (See `RootMode` enum for more details.) - pub fn push_krate_path(self, buffer: &mut T, cnum: CrateNum) - where T: ItemPathBuffer + Debug + fn print_krate_path

( + self, + printer: &mut P, + cnum: CrateNum, + ) -> P::Path + where P: ItemPathPrinter + Debug { debug!( - "push_krate_path: buffer={:?} cnum={:?} LOCAL_CRATE={:?}", - buffer, cnum, LOCAL_CRATE + "print_krate_path: printer={:?} cnum={:?} LOCAL_CRATE={:?}", + printer, cnum, LOCAL_CRATE ); - match *buffer.root_mode() { + match printer.root_mode() { RootMode::Local => { // In local mode, when we encounter a crate other than // LOCAL_CRATE, execution proceeds in one of two ways: @@ -117,56 +119,59 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { span, .. }) if !span.is_dummy() => { - debug!("push_krate_path: def_id={:?}", def_id); - self.push_item_path(buffer, def_id); + debug!("print_krate_path: def_id={:?}", def_id); + self.print_item_path(printer, def_id) } _ => { let name = self.crate_name(cnum).as_str(); - debug!("push_krate_path: name={:?}", name); - buffer.push(&name); + debug!("print_krate_path: name={:?}", name); + printer.path_crate(Some(&name)) } - } } else if self.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - buffer.push(&keywords::Crate.name().as_str()) + printer.path_crate(Some(&keywords::Crate.name().as_str())) + } else { + printer.path_crate(None) } + } else { + printer.path_crate(None) } } RootMode::Absolute => { // In absolute mode, just write the crate name // unconditionally. let name = self.original_crate_name(cnum).as_str(); - debug!("push_krate_path: original_name={:?}", name); - buffer.push(&name); + debug!("print_krate_path: original_name={:?}", name); + printer.path_crate(Some(&name)) } } } - /// If possible, this pushes a global path resolving to `external_def_id` that is visible + /// If possible, this returns a global path resolving to `external_def_id` that is visible /// from at least one local module and returns true. If the crate defining `external_def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - pub fn try_push_visible_item_path( + fn try_print_visible_item_path

( self, - buffer: &mut T, + printer: &mut P, external_def_id: DefId, - ) -> bool - where T: ItemPathBuffer + Debug + ) -> Option + where P: ItemPathPrinter + Debug { debug!( - "try_push_visible_item_path: buffer={:?} external_def_id={:?}", - buffer, external_def_id + "try_print_visible_item_path: printer={:?} external_def_id={:?}", + printer, external_def_id ); let visible_parent_map = self.visible_parent_map(LOCAL_CRATE); let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); loop { debug!( - "try_push_visible_item_path: cur_def={:?} cur_path={:?} CRATE_DEF_INDEX={:?}", + "try_print_visible_item_path: cur_def={:?} cur_path={:?} CRATE_DEF_INDEX={:?}", cur_def, cur_path, CRATE_DEF_INDEX, ); - // If `cur_def` is a direct or injected extern crate, push the path to the crate - // followed by the path to the item within the crate and return. + // If `cur_def` is a direct or injected extern crate, return the path to the crate + // followed by the path to the item within the crate. if cur_def.index == CRATE_DEF_INDEX { match *self.extern_crate(cur_def) { Some(ExternCrate { @@ -175,26 +180,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { span, .. }) => { - debug!("try_push_visible_item_path: def_id={:?}", def_id); - if !span.is_dummy() { - self.push_item_path(buffer, def_id); + debug!("try_print_visible_item_path: def_id={:?}", def_id); + let path = if !span.is_dummy() { + self.print_item_path(printer, def_id) } else { - buffer.push(&self.crate_name(cur_def.krate).as_str()); - } - cur_path.iter().rev().for_each(|segment| buffer.push(&segment)); - return true; + printer.path_crate(Some( + &self.crate_name(cur_def.krate).as_str(), + )) + }; + return Some(cur_path.iter().rev().fold(path, |path, segment| { + printer.path_append(path, &segment) + })); } None => { - buffer.push(&self.crate_name(cur_def.krate).as_str()); - cur_path.iter().rev().for_each(|segment| buffer.push(&segment)); - return true; + let path = printer.path_crate(Some( + &self.crate_name(cur_def.krate).as_str(), + )); + return Some(cur_path.iter().rev().fold(path, |path, segment| { + printer.path_append(path, &segment) + })); } _ => {}, } } let mut cur_def_key = self.def_key(cur_def); - debug!("try_push_visible_item_path: cur_def_key={:?}", cur_def_key); + debug!("try_print_visible_item_path: cur_def_key={:?}", cur_def_key); // For a UnitStruct or TupleStruct we want the name of its parent rather than . if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { @@ -211,7 +222,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let data = cur_def_key.disambiguated_data.data; debug!( - "try_push_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}", + "try_print_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}", data, visible_parent, actual_parent, ); let symbol = match data { @@ -268,39 +279,44 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }) }, }; - debug!("try_push_visible_item_path: symbol={:?}", symbol); + debug!("try_print_visible_item_path: symbol={:?}", symbol); cur_path.push(symbol); - match visible_parent { - Some(def) => cur_def = def, - None => return false, - }; + cur_def = visible_parent?; } } - pub fn push_item_path(self, buffer: &mut T, def_id: DefId) - where T: ItemPathBuffer + Debug + pub fn print_item_path

( + self, + printer: &mut P, + def_id: DefId, + ) -> P::Path + where P: ItemPathPrinter + Debug { debug!( - "push_item_path: buffer={:?} def_id={:?}", - buffer, def_id + "print_item_path: printer={:?} def_id={:?}", + printer, def_id ); - match *buffer.root_mode() { - RootMode::Local if !def_id.is_local() => - if self.try_push_visible_item_path(buffer, def_id) { return }, + match printer.root_mode() { + RootMode::Local if !def_id.is_local() => { + match self.try_print_visible_item_path(printer, def_id) { + Some(path) => return path, + None => {} + } + } _ => {} } let key = self.def_key(def_id); - debug!("push_item_path: key={:?}", key); + debug!("print_item_path: key={:?}", key); match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); - self.push_krate_path(buffer, def_id.krate); + self.print_krate_path(printer, def_id.krate) } DefPathData::Impl => { - self.push_impl_path(buffer, def_id); + self.print_impl_path(printer, def_id) } // Unclear if there is any value in distinguishing these. @@ -324,26 +340,26 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::ClosureExpr | data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { - let parent_def_id = self.parent_def_id(def_id).unwrap(); - self.push_item_path(buffer, parent_def_id); - buffer.push(&data.as_interned_str().as_symbol().as_str()); + let parent_did = self.parent_def_id(def_id).unwrap(); + let path = self.print_item_path(printer, parent_did); + printer.path_append(path, &data.as_interned_str().as_symbol().as_str()) }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.parent_def_id(def_id).unwrap(); - self.push_item_path(buffer, parent_def_id); + self.print_item_path(printer, parent_def_id) } } } - fn push_impl_path( + fn print_impl_path

( self, - buffer: &mut T, + printer: &mut P, impl_def_id: DefId, - ) - where T: ItemPathBuffer + Debug + ) -> P::Path + where P: ItemPathPrinter + Debug { - debug!("push_impl_path: buffer={:?} impl_def_id={:?}", buffer, impl_def_id); + debug!("print_impl_path: printer={:?} impl_def_id={:?}", printer, impl_def_id); let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); // Always use types for non-local impls, where types are always @@ -355,7 +371,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; if !use_types { - return self.push_impl_path_fallback(buffer, impl_def_id); + return self.print_impl_path_fallback(printer, impl_def_id); } // Decide whether to print the parent path for the impl. @@ -379,13 +395,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - self.push_item_path(buffer, parent_def_id); + let path = self.print_item_path(printer, parent_def_id); if let Some(trait_ref) = impl_trait_ref { - buffer.push(&format!("", trait_ref, self_ty)); + return printer.path_append(path, &format!("", trait_ref, self_ty)); } else { - buffer.push(&format!("", self_ty)); + return printer.path_append(path, &format!("", self_ty)); } - return; } // Otherwise, try to give a good form that would be valid language @@ -393,8 +408,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(trait_ref) = impl_trait_ref { // Trait impls. - buffer.push(&format!("<{} as {}>", self_ty, trait_ref)); - return; + return printer.path_impl(&format!("<{} as {}>", self_ty, trait_ref)); } // Inherent impls. Try to print `Foo::bar` for an inherent @@ -402,14 +416,15 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // anything other than a simple path. match self_ty.sty { ty::Adt(adt_def, substs) => { + // FIXME(eddyb) always print without <> here. if substs.types().next().is_none() { // ignore regions - self.push_item_path(buffer, adt_def.did); + self.print_item_path(printer, adt_def.did) } else { - buffer.push(&format!("<{}>", self_ty)); + printer.path_impl(&format!("<{}>", self_ty)) } } - ty::Foreign(did) => self.push_item_path(buffer, did), + ty::Foreign(did) => self.print_item_path(printer, did), ty::Bool | ty::Char | @@ -417,31 +432,31 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::Uint(_) | ty::Float(_) | ty::Str => { - buffer.push(&self_ty.to_string()); + printer.path_impl(&self_ty.to_string()) } _ => { - buffer.push(&format!("<{}>", self_ty)); + printer.path_impl(&format!("<{}>", self_ty)) } } } - fn push_impl_path_fallback( + fn print_impl_path_fallback

( self, - buffer: &mut T, + printer: &mut P, impl_def_id: DefId, - ) - where T: ItemPathBuffer + Debug + ) -> P::Path + where P: ItemPathPrinter + Debug { // If no type info is available, fall back to // pretty printing some span information. This should // only occur very early in the compiler pipeline. let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); - self.push_item_path(buffer, parent_def_id); + let path = self.print_item_path(printer, parent_def_id); let node_id = self.hir().as_local_node_id(impl_def_id).unwrap(); let item = self.hir().expect_item(node_id); let span_str = self.sess.source_map().span_to_string(item.span); - buffer.push(&format!("", span_str)); + printer.path_append(path, &format!("", span_str)) } /// Returns the def-id of `def_id`'s parent in the def tree. If @@ -504,12 +519,17 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { /// Unifying Trait for different kinds of item paths we might /// construct. The basic interface is that components get pushed: the /// instance can also customize how we handle the root of a crate. -pub trait ItemPathBuffer { - fn root_mode(&self) -> &RootMode; - fn push(&mut self, text: &str); +pub trait ItemPathPrinter { + type Path; + + fn root_mode(&self) -> RootMode; + + fn path_crate(&self, name: Option<&str>) -> Self::Path; + fn path_impl(&self, text: &str) -> Self::Path; + fn path_append(&self, path: Self::Path, text: &str) -> Self::Path; } -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] pub enum RootMode { /// Try to make a path relative to the local crate. In /// particular, local paths have no prefix, and if the path comes @@ -523,33 +543,36 @@ pub enum RootMode { } #[derive(Debug)] -struct LocalPathBuffer { +struct LocalPathPrinter { root_mode: RootMode, - str: String, } -impl LocalPathBuffer { - fn new(root_mode: RootMode) -> LocalPathBuffer { - LocalPathBuffer { +impl LocalPathPrinter { + fn new(root_mode: RootMode) -> LocalPathPrinter { + LocalPathPrinter { root_mode, - str: String::new(), } } - - fn into_string(self) -> String { - self.str - } } -impl ItemPathBuffer for LocalPathBuffer { - fn root_mode(&self) -> &RootMode { - &self.root_mode +impl ItemPathPrinter for LocalPathPrinter { + type Path = String; + + fn root_mode(&self) -> RootMode { + self.root_mode } - fn push(&mut self, text: &str) { - if !self.str.is_empty() { - self.str.push_str("::"); + fn path_crate(&self, name: Option<&str>) -> Self::Path { + name.unwrap_or("").to_string() + } + fn path_impl(&self, text: &str) -> Self::Path { + text.to_string() + } + fn path_append(&self, mut path: Self::Path, text: &str) -> Self::Path { + if !path.is_empty() { + path.push_str("::"); } - self.str.push_str(text); + path.push_str(text); + path } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 7aa06c6124c66..8af4926c0133c 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -92,7 +92,7 @@ use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::item_path::{self, ItemPathBuffer, RootMode}; +use rustc::ty::item_path::{self, ItemPathPrinter, RootMode}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -221,11 +221,9 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - let mut buffer = SymbolPathBuffer::new(); item_path::with_forced_absolute_paths(|| { - tcx.push_item_path(&mut buffer, def_id); - }); - buffer.into_interned() + tcx.push_item_path(&mut SymbolPath, def_id).into_interned() + }) } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { @@ -317,7 +315,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs); - let mut buf = SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)); + let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id)); if instance.is_vtable_shim() { buf.push("{{vtable-shim}}"); @@ -340,14 +338,14 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance // To be able to work on all platforms and get *some* reasonable output, we // use C++ name-mangling. #[derive(Debug)] -struct SymbolPathBuffer { +struct SymbolPath { result: String, temp_buf: String, } -impl SymbolPathBuffer { +impl SymbolPath { fn new() -> Self { - let mut result = SymbolPathBuffer { + let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), }; @@ -356,7 +354,7 @@ impl SymbolPathBuffer { } fn from_interned(symbol: ty::SymbolName) -> Self { - let mut result = SymbolPathBuffer { + let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), }; @@ -370,19 +368,6 @@ impl SymbolPathBuffer { } } - fn finish(mut self, hash: u64) -> String { - // E = end name-sequence - let _ = write!(self.result, "17h{:016x}E", hash); - self.result - } -} - -impl ItemPathBuffer for SymbolPathBuffer { - fn root_mode(&self) -> &RootMode { - const ABSOLUTE: &RootMode = &RootMode::Absolute; - ABSOLUTE - } - fn push(&mut self, text: &str) { self.temp_buf.clear(); let need_underscore = sanitize(&mut self.temp_buf, text); @@ -396,6 +381,40 @@ impl ItemPathBuffer for SymbolPathBuffer { } self.result.push_str(&self.temp_buf); } + + fn finish(mut self, hash: u64) -> String { + // E = end name-sequence + let _ = write!(self.result, "17h{:016x}E", hash); + self.result + } +} + +#[derive(Debug)] +struct SymbolPathPrinter; + +impl ItemPathPrinter for SymbolPathPrinter { + type Path = SymbolPath; + + fn root_mode(&self) ->RootMode { + RootMode::Absolute + } + + fn path_crate(&self, name: Option<&str>) -> Self::Path { + let mut path = SymbolPath::new(); + if let Some(name) = name { + path.push(name); + } + path + } + fn path_impl(&self, text: &str) -> Self::Path { + let mut path = SymbolPath::new(); + path.push(text); + path + } + fn path_append(&self, mut path: Self::Path, text: &str) -> Self::Path { + path.push(text); + path + } } // Name sanitation. LLVM will happily accept identifiers with weird names, but From 1913272b1c30c6001ea0ab3ce9e19a41532e5e4d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Dec 2018 12:59:08 +0200 Subject: [PATCH 16/68] rustc: remove ty::item_path::RootMode by moving local logic into the printer. --- src/librustc/ty/item_path.rs | 545 +++++++++------------ src/librustc/ty/print.rs | 26 +- src/librustc_codegen_utils/symbol_names.rs | 23 +- src/librustdoc/clean/mod.rs | 33 +- 4 files changed, 274 insertions(+), 353 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index d11b3c8d85f76..4813a969e58e5 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -1,12 +1,12 @@ use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, DefIdTree, Ty, TyCtxt}; +use ty::print::PrintCx; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; -use syntax::symbol::{keywords, LocalInternedString, Symbol}; +use syntax::symbol::{keywords, Symbol}; use std::cell::Cell; -use std::fmt::Debug; thread_local! { static FORCE_ABSOLUTE: Cell = Cell::new(false); @@ -58,16 +58,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// suitable for user output. It is relative to the current crate /// root, unless with_forced_absolute_paths was used. pub fn item_path_str(self, def_id: DefId) -> String { - let mode = FORCE_ABSOLUTE.with(|force| { - if force.get() { - RootMode::Absolute - } else { - RootMode::Local - } - }); - let mut printer = LocalPathPrinter::new(mode); - debug!("item_path_str: printer={:?} def_id={:?}", printer, def_id); - self.print_item_path(&mut printer, def_id) + debug!("item_path_str: def_id={:?}", def_id); + let mut cx = PrintCx::new(self); + if FORCE_ABSOLUTE.with(|force| force.get()) { + AbsolutePathPrinter::print_item_path(&mut cx, def_id) + } else { + LocalPathPrinter::print_item_path(&mut cx, def_id) + } } /// Returns a string identifying this local node-id. @@ -78,245 +75,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this def-id. This string is /// suitable for user output. It always begins with a crate identifier. pub fn absolute_item_path_str(self, def_id: DefId) -> String { - let mut printer = LocalPathPrinter::new(RootMode::Absolute); - debug!("absolute_item_path_str: printer={:?} def_id={:?}", printer, def_id); - self.print_item_path(&mut printer, def_id) - } - - /// Returns the "path" to a particular crate. This can proceed in - /// various ways, depending on the `root_mode` of the `printer`. - /// (See `RootMode` enum for more details.) - fn print_krate_path

( - self, - printer: &mut P, - cnum: CrateNum, - ) -> P::Path - where P: ItemPathPrinter + Debug - { - debug!( - "print_krate_path: printer={:?} cnum={:?} LOCAL_CRATE={:?}", - printer, cnum, LOCAL_CRATE - ); - match printer.root_mode() { - RootMode::Local => { - // In local mode, when we encounter a crate other than - // LOCAL_CRATE, execution proceeds in one of two ways: - // - // 1. for a direct dependency, where user added an - // `extern crate` manually, we put the `extern - // crate` as the parent. So you wind up with - // something relative to the current crate. - // 2. for an extern inferred from a path or an indirect crate, - // where there is no explicit `extern crate`, we just prepend - // the crate name. - // - // Returns `None` for the local crate. - if cnum != LOCAL_CRATE { - match *self.extern_crate(cnum.as_def_id()) { - Some(ExternCrate { - src: ExternCrateSource::Extern(def_id), - direct: true, - span, - .. - }) if !span.is_dummy() => { - debug!("print_krate_path: def_id={:?}", def_id); - self.print_item_path(printer, def_id) - } - _ => { - let name = self.crate_name(cnum).as_str(); - debug!("print_krate_path: name={:?}", name); - printer.path_crate(Some(&name)) - } - } else if self.sess.rust_2018() { - // We add the `crate::` keyword on Rust 2018, only when desired. - if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - printer.path_crate(Some(&keywords::Crate.name().as_str())) - } else { - printer.path_crate(None) - } - } else { - printer.path_crate(None) - } - } - RootMode::Absolute => { - // In absolute mode, just write the crate name - // unconditionally. - let name = self.original_crate_name(cnum).as_str(); - debug!("print_krate_path: original_name={:?}", name); - printer.path_crate(Some(&name)) - } - } - } - - /// If possible, this returns a global path resolving to `external_def_id` that is visible - /// from at least one local module and returns true. If the crate defining `external_def_id` is - /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_item_path

( - self, - printer: &mut P, - external_def_id: DefId, - ) -> Option - where P: ItemPathPrinter + Debug - { - debug!( - "try_print_visible_item_path: printer={:?} external_def_id={:?}", - printer, external_def_id - ); - let visible_parent_map = self.visible_parent_map(LOCAL_CRATE); - - let (mut cur_def, mut cur_path) = (external_def_id, Vec::::new()); - loop { - debug!( - "try_print_visible_item_path: cur_def={:?} cur_path={:?} CRATE_DEF_INDEX={:?}", - cur_def, cur_path, CRATE_DEF_INDEX, - ); - // If `cur_def` is a direct or injected extern crate, return the path to the crate - // followed by the path to the item within the crate. - if cur_def.index == CRATE_DEF_INDEX { - match *self.extern_crate(cur_def) { - Some(ExternCrate { - src: ExternCrateSource::Extern(def_id), - direct: true, - span, - .. - }) => { - debug!("try_print_visible_item_path: def_id={:?}", def_id); - let path = if !span.is_dummy() { - self.print_item_path(printer, def_id) - } else { - printer.path_crate(Some( - &self.crate_name(cur_def.krate).as_str(), - )) - }; - return Some(cur_path.iter().rev().fold(path, |path, segment| { - printer.path_append(path, &segment) - })); - } - None => { - let path = printer.path_crate(Some( - &self.crate_name(cur_def.krate).as_str(), - )); - return Some(cur_path.iter().rev().fold(path, |path, segment| { - printer.path_append(path, &segment) - })); - } - _ => {}, - } - } - - let mut cur_def_key = self.def_key(cur_def); - debug!("try_print_visible_item_path: cur_def_key={:?}", cur_def_key); - - // For a UnitStruct or TupleStruct we want the name of its parent rather than . - if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { - let parent = DefId { - krate: cur_def.krate, - index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), - }; - - cur_def_key = self.def_key(parent); - } - - let visible_parent = visible_parent_map.get(&cur_def).cloned(); - let actual_parent = self.parent(cur_def); - - let data = cur_def_key.disambiguated_data.data; - debug!( - "try_print_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}", - data, visible_parent, actual_parent, - ); - let symbol = match data { - // In order to output a path that could actually be imported (valid and visible), - // we need to handle re-exports correctly. - // - // For example, take `std::os::unix::process::CommandExt`, this trait is actually - // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). - // - // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is - // private so the "true" path to `CommandExt` isn't accessible. - // - // In this case, the `visible_parent_map` will look something like this: - // - // (child) -> (parent) - // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` - // `std::sys::unix::ext::process` -> `std::sys::unix::ext` - // `std::sys::unix::ext` -> `std::os` - // - // This is correct, as the visible parent of `std::sys::unix::ext` is in fact - // `std::os`. - // - // When printing the path to `CommandExt` and looking at the `cur_def_key` that - // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go - // to the parent - resulting in a mangled path like - // `std::os::ext::process::CommandExt`. - // - // Instead, we must detect that there was a re-export and instead print `unix` - // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To - // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with - // the visible parent (`std::os`). If these do not match, then we iterate over - // the children of the visible parent (as was done when computing - // `visible_parent_map`), looking for the specific child we currently have and then - // have access to the re-exported name. - DefPathData::Module(actual_name) | - DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { - visible_parent - .and_then(|parent| { - self.item_children(parent) - .iter() - .find(|child| child.def.def_id() == cur_def) - .map(|child| child.ident.as_str()) - }) - .unwrap_or_else(|| actual_name.as_str()) - }, - _ => { - data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { - // Re-exported `extern crate` (#43189). - if let DefPathData::CrateRoot = data { - self.original_crate_name(cur_def.krate).as_str() - } else { - Symbol::intern("").as_str() - } - }) - }, - }; - debug!("try_print_visible_item_path: symbol={:?}", symbol); - cur_path.push(symbol); - - cur_def = visible_parent?; - } + debug!("absolute_item_path_str: def_id={:?}", def_id); + let mut cx = PrintCx::new(self); + AbsolutePathPrinter::print_item_path(&mut cx, def_id) } +} - pub fn print_item_path

( - self, - printer: &mut P, - def_id: DefId, - ) -> P::Path - where P: ItemPathPrinter + Debug +impl PrintCx<'a, 'gcx, 'tcx> { + pub fn default_print_item_path

(&mut self, def_id: DefId) -> P::Path + where P: ItemPathPrinter { - debug!( - "print_item_path: printer={:?} def_id={:?}", - printer, def_id - ); - match printer.root_mode() { - RootMode::Local if !def_id.is_local() => { - match self.try_print_visible_item_path(printer, def_id) { - Some(path) => return path, - None => {} - } - } - _ => {} - } - - let key = self.def_key(def_id); - debug!("print_item_path: key={:?}", key); + debug!("default_print_item_path: def_id={:?}", def_id); + let key = self.tcx.def_key(def_id); + debug!("default_print_item_path: key={:?}", key); match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); - self.print_krate_path(printer, def_id.krate) + P::path_crate(self, def_id.krate) } DefPathData::Impl => { - self.print_impl_path(printer, def_id) + self.default_print_impl_path::

(def_id) } // Unclear if there is any value in distinguishing these. @@ -340,27 +119,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::ClosureExpr | data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { - let parent_did = self.parent_def_id(def_id).unwrap(); - let path = self.print_item_path(printer, parent_did); - printer.path_append(path, &data.as_interned_str().as_symbol().as_str()) + let parent_did = self.tcx.parent_def_id(def_id).unwrap(); + let path = P::print_item_path(self, parent_did); + P::path_append(path, &data.as_interned_str().as_symbol().as_str()) }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` - let parent_def_id = self.parent_def_id(def_id).unwrap(); - self.print_item_path(printer, parent_def_id) + let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); + P::print_item_path(self, parent_def_id) } } } - fn print_impl_path

( - self, - printer: &mut P, - impl_def_id: DefId, - ) -> P::Path - where P: ItemPathPrinter + Debug + fn default_print_impl_path

(&mut self, impl_def_id: DefId) -> P::Path + where P: ItemPathPrinter { - debug!("print_impl_path: printer={:?} impl_def_id={:?}", printer, impl_def_id); - let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); + debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); + let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); // Always use types for non-local impls, where types are always // available, and filename/line-number is mostly uninteresting. @@ -371,7 +146,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; if !use_types { - return self.print_impl_path_fallback(printer, impl_def_id); + return self.default_print_impl_path_fallback::

(impl_def_id); } // Decide whether to print the parent path for the impl. @@ -379,27 +154,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // users may find it useful. Currently, we omit the parent if // the impl is either in the same module as the self-type or // as the trait. - let self_ty = self.type_of(impl_def_id); + let self_ty = self.tcx.type_of(impl_def_id); let in_self_mod = match characteristic_def_id_of_type(self_ty) { None => false, - Some(ty_def_id) => self.parent_def_id(ty_def_id) == Some(parent_def_id), + Some(ty_def_id) => self.tcx.parent_def_id(ty_def_id) == Some(parent_def_id), }; - let impl_trait_ref = self.impl_trait_ref(impl_def_id); + let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); let in_trait_mod = match impl_trait_ref { None => false, - Some(trait_ref) => self.parent_def_id(trait_ref.def_id) == Some(parent_def_id), + Some(trait_ref) => self.tcx.parent_def_id(trait_ref.def_id) == Some(parent_def_id), }; if !in_self_mod && !in_trait_mod { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - let path = self.print_item_path(printer, parent_def_id); + let path = P::print_item_path(self, parent_def_id); if let Some(trait_ref) = impl_trait_ref { - return printer.path_append(path, &format!("", trait_ref, self_ty)); + return P::path_append(path, &format!("", trait_ref, self_ty)); } else { - return printer.path_append(path, &format!("", self_ty)); + return P::path_append(path, &format!("", self_ty)); } } @@ -408,7 +183,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(trait_ref) = impl_trait_ref { // Trait impls. - return printer.path_impl(&format!("<{} as {}>", self_ty, trait_ref)); + return P::path_impl(&format!("<{} as {}>", self_ty, trait_ref)); } // Inherent impls. Try to print `Foo::bar` for an inherent @@ -418,13 +193,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::Adt(adt_def, substs) => { // FIXME(eddyb) always print without <> here. if substs.types().next().is_none() { // ignore regions - self.print_item_path(printer, adt_def.did) + P::print_item_path(self, adt_def.did) } else { - printer.path_impl(&format!("<{}>", self_ty)) + P::path_impl(&format!("<{}>", self_ty)) } } - ty::Foreign(did) => self.print_item_path(printer, did), + ty::Foreign(did) => P::print_item_path(self, did), ty::Bool | ty::Char | @@ -432,33 +207,32 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::Uint(_) | ty::Float(_) | ty::Str => { - printer.path_impl(&self_ty.to_string()) + P::path_impl(&self_ty.to_string()) } _ => { - printer.path_impl(&format!("<{}>", self_ty)) + P::path_impl(&format!("<{}>", self_ty)) } } } - fn print_impl_path_fallback

( - self, - printer: &mut P, - impl_def_id: DefId, - ) -> P::Path - where P: ItemPathPrinter + Debug + fn default_print_impl_path_fallback

(&mut self, impl_def_id: DefId) -> P::Path + where P: ItemPathPrinter { // If no type info is available, fall back to // pretty printing some span information. This should // only occur very early in the compiler pipeline. - let parent_def_id = self.parent_def_id(impl_def_id).unwrap(); - let path = self.print_item_path(printer, parent_def_id); - let node_id = self.hir().as_local_node_id(impl_def_id).unwrap(); - let item = self.hir().expect_item(node_id); - let span_str = self.sess.source_map().span_to_string(item.span); - printer.path_append(path, &format!("", span_str)) + // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` + let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); + let path = P::print_item_path(self, parent_def_id); + let node_id = self.tcx.hir().as_local_node_id(impl_def_id).unwrap(); + let item = self.tcx.hir().expect_item(node_id); + let span_str = self.tcx.sess.source_map().span_to_string(item.span); + P::path_append(path, &format!("", span_str)) } +} +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns the def-id of `def_id`'s parent in the def tree. If /// this returns `None`, then `def_id` represents a crate root or /// inlined root. @@ -517,58 +291,205 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } /// Unifying Trait for different kinds of item paths we might -/// construct. The basic interface is that components get pushed: the -/// instance can also customize how we handle the root of a crate. -pub trait ItemPathPrinter { +/// construct. The basic interface is that components get appended. +pub trait ItemPathPrinter: Sized { type Path; - fn root_mode(&self) -> RootMode; + fn print_item_path(cx: &mut PrintCx<'_, '_, '_>, def_id: DefId) -> Self::Path { + cx.default_print_item_path::(def_id) + } - fn path_crate(&self, name: Option<&str>) -> Self::Path; - fn path_impl(&self, text: &str) -> Self::Path; - fn path_append(&self, path: Self::Path, text: &str) -> Self::Path; + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path; + fn path_impl(text: &str) -> Self::Path; + fn path_append(path: Self::Path, text: &str) -> Self::Path; } -#[derive(Copy, Clone, Debug)] -pub enum RootMode { - /// Try to make a path relative to the local crate. In - /// particular, local paths have no prefix, and if the path comes - /// from an extern crate, start with the path to the `extern - /// crate` declaration. - Local, - - /// Always prepend the crate name to the path, forming an absolute - /// path from within a given set of crates. - Absolute, -} +struct AbsolutePathPrinter; + +impl ItemPathPrinter for AbsolutePathPrinter { + type Path = String; -#[derive(Debug)] -struct LocalPathPrinter { - root_mode: RootMode, + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + cx.tcx.original_crate_name(cnum).to_string() + } + fn path_impl(text: &str) -> Self::Path { + text.to_string() + } + fn path_append(mut path: Self::Path, text: &str) -> Self::Path { + if !path.is_empty() { + path.push_str("::"); + } + path.push_str(text); + path + } } +struct LocalPathPrinter; + impl LocalPathPrinter { - fn new(root_mode: RootMode) -> LocalPathPrinter { - LocalPathPrinter { - root_mode, + /// If possible, this returns a global path resolving to `def_id` that is visible + /// from at least one local module and returns true. If the crate defining `def_id` is + /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. + fn try_print_visible_item_path( + cx: &mut PrintCx<'_, '_, '_>, + def_id: DefId, + ) -> Option<::Path> { + debug!("try_print_visible_item_path: def_id={:?}", def_id); + + // If `def_id` is a direct or injected extern crate, return the + // path to the crate followed by the path to the item within the crate. + if def_id.index == CRATE_DEF_INDEX { + let cnum = def_id.krate; + + if cnum == LOCAL_CRATE { + return Some(Self::path_crate(cx, cnum)); + } + + // In local mode, when we encounter a crate other than + // LOCAL_CRATE, execution proceeds in one of two ways: + // + // 1. for a direct dependency, where user added an + // `extern crate` manually, we put the `extern + // crate` as the parent. So you wind up with + // something relative to the current crate. + // 2. for an extern inferred from a path or an indirect crate, + // where there is no explicit `extern crate`, we just prepend + // the crate name. + match *cx.tcx.extern_crate(def_id) { + Some(ExternCrate { + src: ExternCrateSource::Extern(def_id), + direct: true, + span, + .. + }) => { + debug!("try_print_visible_item_path: def_id={:?}", def_id); + let path = if !span.is_dummy() { + Self::print_item_path(cx, def_id) + } else { + Self::path_crate(cx, cnum) + }; + return Some(path); + } + None => { + return Some(Self::path_crate(cx, cnum)); + } + _ => {}, + } } + + if def_id.is_local() { + return None; + } + + let visible_parent_map = cx.tcx.visible_parent_map(LOCAL_CRATE); + + let mut cur_def_key = cx.tcx.def_key(def_id); + debug!("try_print_visible_item_path: cur_def_key={:?}", cur_def_key); + + // For a UnitStruct or TupleStruct we want the name of its parent rather than . + if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { + let parent = DefId { + krate: def_id.krate, + index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), + }; + + cur_def_key = cx.tcx.def_key(parent); + } + + let visible_parent = visible_parent_map.get(&def_id).cloned()?; + let path = Self::try_print_visible_item_path(cx, visible_parent)?; + let actual_parent = cx.tcx.parent(def_id); + + let data = cur_def_key.disambiguated_data.data; + debug!( + "try_print_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}", + data, visible_parent, actual_parent, + ); + + let symbol = match data { + // In order to output a path that could actually be imported (valid and visible), + // we need to handle re-exports correctly. + // + // For example, take `std::os::unix::process::CommandExt`, this trait is actually + // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). + // + // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is + // private so the "true" path to `CommandExt` isn't accessible. + // + // In this case, the `visible_parent_map` will look something like this: + // + // (child) -> (parent) + // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` + // `std::sys::unix::ext::process` -> `std::sys::unix::ext` + // `std::sys::unix::ext` -> `std::os` + // + // This is correct, as the visible parent of `std::sys::unix::ext` is in fact + // `std::os`. + // + // When printing the path to `CommandExt` and looking at the `cur_def_key` that + // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go + // to the parent - resulting in a mangled path like + // `std::os::ext::process::CommandExt`. + // + // Instead, we must detect that there was a re-export and instead print `unix` + // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To + // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with + // the visible parent (`std::os`). If these do not match, then we iterate over + // the children of the visible parent (as was done when computing + // `visible_parent_map`), looking for the specific child we currently have and then + // have access to the re-exported name. + DefPathData::Module(actual_name) | + DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { + visible_parent + .and_then(|parent| { + self.item_children(parent) + .iter() + .find(|child| child.def.def_id() == cur_def) + .map(|child| child.ident.as_str()) + }) + .unwrap_or_else(|| actual_name.as_str()) + } + _ => { + data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { + // Re-exported `extern crate` (#43189). + if let DefPathData::CrateRoot = data { + cx.tcx.original_crate_name(def_id.krate).as_str() + } else { + Symbol::intern("").as_str() + } + }) + }, + }; + debug!("try_print_visible_item_path: symbol={:?}", symbol); + Some(Self::path_append(path, &symbol)) } } impl ItemPathPrinter for LocalPathPrinter { type Path = String; - fn root_mode(&self) -> RootMode { - self.root_mode + fn print_item_path(cx: &mut PrintCx<'_, '_, '_>, def_id: DefId) -> Self::Path { + Self::try_print_visible_item_path(cx, def_id) + .unwrap_or_else(|| cx.default_print_item_path::(def_id)) } - fn path_crate(&self, name: Option<&str>) -> Self::Path { - name.unwrap_or("").to_string() + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + if cnum == LOCAL_CRATE { + if cx.tcx.sess.rust_2018() { + // We add the `crate::` keyword on Rust 2018, only when desired. + if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + return keywords::Crate.name().to_string(); + } + } + String::new() + } else { + cx.tcx.crate_name(cnum).to_string() + } } - fn path_impl(&self, text: &str) -> Self::Path { + fn path_impl(text: &str) -> Self::Path { text.to_string() } - fn path_append(&self, mut path: Self::Path, text: &str) -> Self::Path { + fn path_append(mut path: Self::Path, text: &str) -> Self::Path { if !path.is_empty() { path.push_str("::"); } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 64998ad66eb3d..46e0debadac6c 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -22,7 +22,7 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } pub struct PrintCx<'a, 'gcx, 'tcx> { - pub(crate) tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub(crate) is_debug: bool, pub(crate) is_verbose: bool, pub(crate) identify_regions: bool, @@ -32,18 +32,20 @@ pub struct PrintCx<'a, 'gcx, 'tcx> { } impl PrintCx<'a, 'gcx, 'tcx> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { + PrintCx { + tcx, + is_debug: false, + is_verbose: tcx.sess.verbose(), + identify_regions: tcx.sess.opts.debugging_opts.identify_regions, + used_region_names: None, + region_index: 0, + binder_depth: 0, + } + } + pub(crate) fn with(f: impl FnOnce(PrintCx<'_, '_, '_>) -> R) -> R { - ty::tls::with(|tcx| { - f(PrintCx { - tcx, - is_debug: false, - is_verbose: tcx.sess.verbose(), - identify_regions: tcx.sess.opts.debugging_opts.identify_regions, - used_region_names: None, - region_index: 0, - binder_depth: 0, - }) - }) + ty::tls::with(|tcx| f(PrintCx::new(tcx))) } pub(crate) fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) where T: TypeFoldable<'tcx> diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 8af4926c0133c..c8fe517621ab5 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -87,12 +87,13 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use rustc::hir::def_id::{DefId, LOCAL_CRATE}; +use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::item_path::{self, ItemPathPrinter, RootMode}; +use rustc::ty::item_path::{self, ItemPathPrinter}; +use rustc::ty::print::PrintCx; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -222,7 +223,8 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { item_path::with_forced_absolute_paths(|| { - tcx.push_item_path(&mut SymbolPath, def_id).into_interned() + let mut cx = PrintCx::new(tcx); + SymbolPathPrinter::print_item_path(&mut cx, def_id).into_interned() }) } @@ -389,29 +391,22 @@ impl SymbolPath { } } -#[derive(Debug)] struct SymbolPathPrinter; impl ItemPathPrinter for SymbolPathPrinter { type Path = SymbolPath; - fn root_mode(&self) ->RootMode { - RootMode::Absolute - } - - fn path_crate(&self, name: Option<&str>) -> Self::Path { + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { let mut path = SymbolPath::new(); - if let Some(name) = name { - path.push(name); - } + path.push(&cx.tcx.original_crate_name(cnum).as_str()); path } - fn path_impl(&self, text: &str) -> Self::Path { + fn path_impl(text: &str) -> Self::Path { let mut path = SymbolPath::new(); path.push(text); path } - fn path_append(&self, mut path: Self::Path, text: &str) -> Self::Path { + fn path_append(mut path: Self::Path, text: &str) -> Self::Path { path.push(text); path } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ec51a17768b90..7e355a440791b 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4045,30 +4045,33 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { pub fn get_path_for_type(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path where F: Fn(DefId) -> Def { - #[derive(Debug)] - struct AbsolutePathBuffer { - names: Vec, - } + use rustc::ty::item_path::ItemPathPrinter; + use rustc::ty::print::PrintCx; - impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer { - fn root_mode(&self) -> &ty::item_path::RootMode { - const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute; - ABSOLUTE - } + struct AbsolutePathPrinter; + + impl ItemPathPrinter for AbsolutePathPrinter { + type Path = Vec; - fn push(&mut self, text: &str) { - self.names.push(text.to_owned()); + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + vec![cx.tcx.original_crate_name(cnum).to_string()] + } + fn path_impl(text: &str) -> Self::Path { + vec![text.to_string()] + } + fn path_append(mut path: Self::Path, text: &str) -> Self::Path { + path.push(text.to_string()); + path } } - let mut apb = AbsolutePathBuffer { names: vec![] }; - - tcx.push_item_path(&mut apb, def_id); + let mut cx = PrintCx::new(tcx); + let names = AbsolutePathPrinter::print_item_path(&mut cx, def_id); hir::Path { span: DUMMY_SP, def: def_ctor(def_id), - segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment { + segments: hir::HirVec::from_vec(names.iter().map(|s| hir::PathSegment { ident: ast::Ident::from_str(&s), id: None, def: None, From 0e8adf998286993c0c6ea3dd61e00fcddfeedcf8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Dec 2018 17:36:24 +0200 Subject: [PATCH 17/68] rustc: always rely on '_ to be not printed by ty::Region itself. --- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc/ty/structural_impls.rs | 1 + src/librustc/util/ppaux.rs | 127 ++++++++---------- src/test/ui/issues/issue-17905-2.stderr | 4 +- .../escape-argument-callee.stderr | 2 +- ...pagate-approximated-fail-no-postdom.stderr | 4 +- ...ail-to-approximate-longer-no-bounds.stderr | 4 +- ...-to-approximate-longer-wrong-bounds.stderr | 4 +- 8 files changed, 69 insertions(+), 79 deletions(-) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index e5ed16e755860..4746802b8e28a 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -411,7 +411,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option< w.push('<'); w.push_str(&substs.iter() .map(|k| k.to_string()) - .filter(|k| &k[..] != "'_") + .filter(|k| !k.is_empty()) .collect::>().join(", ")); w.push('>'); } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 688eb39635f17..e8f5d9306f6be 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -53,6 +53,7 @@ CloneTypeFoldableAndLiftImpls! { ::ty::InferTy, ::ty::IntVarValue, ::ty::ParamTy, + ::ty::RegionVid, ::ty::UniverseIndex, ::ty::Variance, ::syntax_pos::Span, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 55d24c99506a6..66caf0319fadb 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -119,17 +119,6 @@ impl RegionHighlightMode { Self::highlighting_region(&ty::ReVar(vid), number, op) } - /// Returns true if any placeholders are highlighted. - fn any_region_vids_highlighted(&self) -> bool { - Self::get() - .highlight_regions - .iter() - .any(|h| match h { - Some((ty::ReVar(_), _)) => true, - _ => false, - }) - } - /// Returns `Some(n)` with the number to use for the given region, /// if any. fn region_highlighted(&self, region: ty::Region<'_>) -> Option { @@ -163,17 +152,6 @@ impl RegionHighlightMode { ) } - /// Returns true if any placeholders are highlighted. - pub fn any_placeholders_highlighted(&self) -> bool { - Self::get() - .highlight_regions - .iter() - .any(|h| match h { - Some((ty::RePlaceholder(_), _)) => true, - _ => false, - }) - } - /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option { self.region_highlighted(&ty::RePlaceholder(p)) @@ -420,7 +398,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { if self.is_verbose { write!(f, "{:?}", region)?; } else { - let s = region.to_string(); + let s = region.print_display_to_string(self); if s.is_empty() { // This happens when the value of the region // parameter is not easily serialized. This may be @@ -714,19 +692,20 @@ define_print! { return self.print_debug(f, cx); } - if let Some((region, counter)) = RegionHighlightMode::get().highlight_bound_region { - if *self == region { - return match *self { - BrNamed(_, name) => write!(f, "{}", name), - BrAnon(_) | BrFresh(_) | BrEnv => write!(f, "'{}", counter) - }; + if let BrNamed(_, name) = *self { + if name != "" && name != "'_" { + return write!(f, "{}", name); } } - match *self { - BrNamed(_, name) => write!(f, "{}", name), - BrAnon(_) | BrFresh(_) | BrEnv => Ok(()) + let highlight = RegionHighlightMode::get(); + if let Some((region, counter)) = highlight.highlight_bound_region { + if *self == region { + return write!(f, "'{}", counter); + } } + + Ok(()) } debug { return match *self { @@ -751,12 +730,10 @@ define_print! { let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.placeholder_highlight(*self) { - write!(f, "'{}", counter) - } else if highlight.any_placeholders_highlighted() { - write!(f, "'_") - } else { - write!(f, "{}", self.name) + return write!(f, "'{}", counter); } + + write!(f, "{}", self.name) } } } @@ -779,7 +756,11 @@ define_print! { // `explain_region()` or `note_and_explain_region()`. match *self { ty::ReEarlyBound(ref data) => { - write!(f, "{}", data.name) + if data.name != "'_" { + write!(f, "{}", data.name) + } else { + Ok(()) + } } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { @@ -806,14 +787,11 @@ define_print! { ), } } + ty::ReVar(region_vid) if cx.identify_regions => { + write!(f, "{:?}", region_vid) + } ty::ReVar(region_vid) => { - if RegionHighlightMode::get().any_region_vids_highlighted() { - write!(f, "{:?}", region_vid) - } else if cx.identify_regions { - write!(f, "'{}rv", region_vid.index()) - } else { - Ok(()) - } + write!(f, "{}", region_vid) } ty::ReScope(_) | ty::ReErased => Ok(()), @@ -926,15 +904,30 @@ impl fmt::Debug for ty::FloatVid { } } -impl fmt::Debug for ty::RegionVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if let Some(counter) = RegionHighlightMode::get().region_highlighted(&ty::ReVar(*self)) { - return write!(f, "'{:?}", counter); - } else if RegionHighlightMode::get().any_region_vids_highlighted() { - return write!(f, "'_"); +define_print! { + () ty::RegionVid, (self, f, cx) { + display { + if cx.is_verbose { + return self.print_debug(f, cx); + } + + let highlight = RegionHighlightMode::get(); + if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { + return write!(f, "'{:?}", counter); + } + + Ok(()) } + debug { + // HACK(eddyb) this is duplicated from `display` printing, + // to keep NLL borrowck working even with `-Zverbose`. + let highlight = RegionHighlightMode::get(); + if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { + return write!(f, "'{:?}", counter); + } - write!(f, "'_#{}r", self.index()) + write!(f, "'_#{}r", self.index()) + } } } @@ -942,16 +935,15 @@ define_print! { () ty::InferTy, (self, f, cx) { display { if cx.is_verbose { - print!(f, cx, print_debug(self)) - } else { - match *self { - ty::TyVar(_) => write!(f, "_"), - ty::IntVar(_) => write!(f, "{}", "{integer}"), - ty::FloatVar(_) => write!(f, "{}", "{float}"), - ty::FreshTy(v) => write!(f, "FreshTy({})", v), - ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), - ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) - } + return self.print_debug(f, cx); + } + match *self { + ty::TyVar(_) => write!(f, "_"), + ty::IntVar(_) => write!(f, "{}", "{integer}"), + ty::FloatVar(_) => write!(f, "{}", "{float}"), + ty::FreshTy(v) => write!(f, "FreshTy({})", v), + ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), + ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) } } debug { @@ -1049,12 +1041,9 @@ define_print! { } Ref(r, ty, mutbl) => { write!(f, "&")?; - let s = r.print_to_string(cx); - if s != "'_" { - write!(f, "{}", s)?; - if !s.is_empty() { - write!(f, " ")?; - } + let s = r.print_display_to_string(cx); + if !s.is_empty() { + write!(f, "{} ", s)?; } ty::TypeAndMut { ty, mutbl }.print(f, cx) } @@ -1100,7 +1089,7 @@ define_print! { } Adt(def, substs) => cx.parameterized(f, def.did, substs, iter::empty()), Dynamic(data, r) => { - let r = r.print_to_string(cx); + let r = r.print_display_to_string(cx); if !r.is_empty() { write!(f, "(")?; } diff --git a/src/test/ui/issues/issue-17905-2.stderr b/src/test/ui/issues/issue-17905-2.stderr index 39e5f8ffc9f99..2cb2d5c20d8c4 100644 --- a/src/test/ui/issues/issue-17905-2.stderr +++ b/src/test/ui/issues/issue-17905-2.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched method receiver LL | fn say(self: &Pair<&str, isize>) { | ^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Pair<&'_ str, _>` + = note: expected type `Pair<&str, _>` found type `Pair<&str, _>` note: the anonymous lifetime #2 defined on the method body at 8:5... --> $DIR/issue-17905-2.rs:8:5 @@ -27,7 +27,7 @@ error[E0308]: mismatched method receiver LL | fn say(self: &Pair<&str, isize>) { | ^^^^^^^^^^^^^^^^^^ lifetime mismatch | - = note: expected type `Pair<&'_ str, _>` + = note: expected type `Pair<&str, _>` found type `Pair<&str, _>` note: the lifetime '_ as defined on the impl at 5:5... --> $DIR/issue-17905-2.rs:5:5 diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 8e407070342cf..46de13dbbbd9b 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -16,7 +16,7 @@ LL | let mut closure = expect_sig(|p, y| *p = y); | - - ^^^^^^ assignment requires that `'1` must outlive `'2` | | | | | has type `&'1 i32` - | has type `&mut &'2 i32` + | has type `&'_#2r mut &'2 i32` note: No external requirements --> $DIR/escape-argument-callee.rs:20:1 diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 55e4573e60bbb..899e1b8ac56ff 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -20,9 +20,9 @@ error: lifetime may not live long enough --> $DIR/propagate-approximated-fail-no-postdom.rs:46:13 | LL | |_outlives1, _outlives2, _outlives3, x, y| { - | ---------- ---------- has type `std::cell::Cell<&'2 &u32>` + | ---------- ---------- has type `std::cell::Cell<&'2 &'_#3r u32>` | | - | has type `std::cell::Cell<&&'1 u32>` + | has type `std::cell::Cell<&'_#1r &'1 u32>` ... LL | demand_y(x, y, p) //~ ERROR | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 93eb93bdc0638..c64a6ab1f0d7b 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -20,9 +20,9 @@ error: lifetime may not live long enough --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:37:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - | --------- - has type `&std::cell::Cell<&'1 u32>` + | --------- - has type `&'_#7r std::cell::Cell<&'1 u32>` | | - | has type `&std::cell::Cell<&'2 &u32>` + | has type `&'_#5r std::cell::Cell<&'2 &'_#1r u32>` LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index c7809de88b922..c170518ad35e6 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -20,9 +20,9 @@ error: lifetime may not live long enough --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:41:9 | LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - | ---------- ---------- has type `&std::cell::Cell<&'2 &u32>` + | ---------- ---------- has type `&'_#8r std::cell::Cell<&'2 &'_#2r u32>` | | - | has type `&std::cell::Cell<&'1 &u32>` + | has type `&'_#6r std::cell::Cell<&'1 &'_#1r u32>` LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` From a5dcd6da7e54555067837b2f45d8f8fe94167b53 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Dec 2018 09:47:45 +0200 Subject: [PATCH 18/68] rustc: add a ty::RegionKind::display_outputs_anything method to avoid printing to a string. --- src/librustc/ty/print.rs | 15 ---- src/librustc/util/ppaux.rs | 142 +++++++++++++++++++++++++++++++------ 2 files changed, 120 insertions(+), 37 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 46e0debadac6c..fb062695fc095 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -59,11 +59,6 @@ impl PrintCx<'a, 'gcx, 'tcx> { pub trait Print<'tcx> { fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result; - fn print_to_string(&self, cx: &mut PrintCx<'_, '_, 'tcx>) -> String { - let mut result = String::new(); - let _ = self.print(&mut result, cx); - result - } fn print_display( &self, f: &mut F, @@ -75,11 +70,6 @@ pub trait Print<'tcx> { cx.is_debug = old_debug; result } - fn print_display_to_string(&self, cx: &mut PrintCx<'_, '_, 'tcx>) -> String { - let mut result = String::new(); - let _ = self.print_display(&mut result, cx); - result - } fn print_debug(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result { let old_debug = cx.is_debug; cx.is_debug = true; @@ -87,9 +77,4 @@ pub trait Print<'tcx> { cx.is_debug = old_debug; result } - fn print_debug_to_string(&self, cx: &mut PrintCx<'_, '_, 'tcx>) -> String { - let mut result = String::new(); - let _ = self.print_debug(&mut result, cx); - result - } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 66caf0319fadb..e5216c84d0e7e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -395,20 +395,15 @@ impl PrintCx<'a, 'gcx, 'tcx> { continue; } start_or_continue(f, start, ", ")?; - if self.is_verbose { - write!(f, "{:?}", region)?; + if !region.display_outputs_anything(self) { + // This happens when the value of the region + // parameter is not easily serialized. This may be + // because the user omitted it in the first place, + // or because it refers to some block in the code, + // etc. I'm not sure how best to serialize this. + write!(f, "'_")?; } else { - let s = region.print_display_to_string(self); - if s.is_empty() { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - write!(f, "'_")?; - } else { - write!(f, "{}", s)?; - } + region.print_display(f, self)?; } } UnpackedKind::Type(ty) => { @@ -721,6 +716,32 @@ define_print! { } } +// HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`) +// +// NB: this must be kept in sync with the printing logic above. +impl ty::BoundRegion { + fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + if cx.is_verbose { + return true; + } + + if let BrNamed(_, name) = *self { + if name != "" && name != "'_" { + return true; + } + } + + let highlight = RegionHighlightMode::get(); + if let Some((region, _)) = highlight.highlight_bound_region { + if *self == region { + return true; + } + } + + false + } +} + define_print! { () ty::PlaceholderRegion, (self, f, cx) { display { @@ -738,6 +759,24 @@ define_print! { } } +// HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`) +// +// NB: this must be kept in sync with the printing logic above. +impl ty::PlaceholderRegion { + fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + if cx.is_verbose { + return true; + } + + let highlight = RegionHighlightMode::get(); + if highlight.placeholder_highlight(*self).is_some() { + return true; + } + + self.name.display_outputs_anything(cx) + } +} + define_print! { () ty::RegionKind, (self, f, cx) { display { @@ -845,6 +884,49 @@ define_print! { } } +// HACK(eddyb) Trying to print a lifetime might not print anything, which +// may need special handling in the caller (of `ty::RegionKind::print`). +// To avoid printing to a temporary string, the `display_outputs_anything` +// method can instead be used to determine this, ahead of time. +// +// NB: this must be kept in sync with the printing logic above. +impl ty::RegionKind { + fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + if cx.is_verbose { + return true; + } + + if RegionHighlightMode::get().region_highlighted(self).is_some() { + return true; + } + + match *self { + ty::ReEarlyBound(ref data) => { + data.name != "" && data.name != "'_" + } + + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { + br.display_outputs_anything(cx) + } + + ty::RePlaceholder(p) => p.display_outputs_anything(cx), + + ty::ReScope(_) | + ty::ReVar(_) if cx.identify_regions => true, + + ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx), + + ty::ReScope(_) | + ty::ReErased => false, + + ty::ReStatic | + ty::ReEmpty | + ty::ReClosureBound(_) => true, + } + } +} + define_print! { () ty::FreeRegion, (self, f, cx) { debug { @@ -931,6 +1013,24 @@ define_print! { } } +// HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`) +// +// NB: this must be kept in sync with the printing logic above. +impl ty::RegionVid { + fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + if cx.is_verbose { + return true; + } + + let highlight = RegionHighlightMode::get(); + if highlight.region_highlighted(&ty::ReVar(*self)).is_some() { + return true; + } + + false + } +} + define_print! { () ty::InferTy, (self, f, cx) { display { @@ -1041,9 +1141,8 @@ define_print! { } Ref(r, ty, mutbl) => { write!(f, "&")?; - let s = r.print_display_to_string(cx); - if !s.is_empty() { - write!(f, "{} ", s)?; + if r.display_outputs_anything(cx) { + print!(f, cx, print_display(r), write(" "))?; } ty::TypeAndMut { ty, mutbl }.print(f, cx) } @@ -1089,17 +1188,16 @@ define_print! { } Adt(def, substs) => cx.parameterized(f, def.did, substs, iter::empty()), Dynamic(data, r) => { - let r = r.print_display_to_string(cx); - if !r.is_empty() { + let print_r = r.display_outputs_anything(cx); + if print_r { write!(f, "(")?; } write!(f, "dyn ")?; data.print(f, cx)?; - if !r.is_empty() { - write!(f, " + {})", r) - } else { - Ok(()) + if print_r { + print!(f, cx, write(" + "), print_display(r), write(")"))?; } + Ok(()) } Foreign(def_id) => cx.parameterized(f, def_id, Substs::empty(), iter::empty()), Projection(ref data) => data.print(f, cx), From b3073f442eeab2f9262ca9c251809aa666a36bd2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Dec 2018 16:10:22 +0200 Subject: [PATCH 19/68] rustc: move the formatter into ty::print::PrintCx. --- src/librustc/lib.rs | 1 + src/librustc/mir/mod.rs | 4 +- src/librustc/ty/item_path.rs | 130 ++--- src/librustc/ty/print.rs | 44 +- src/librustc/util/ppaux.rs | 618 ++++++++++----------- src/librustc_codegen_utils/lib.rs | 1 + src/librustc_codegen_utils/symbol_names.rs | 15 +- src/librustdoc/clean/mod.rs | 15 +- src/librustdoc/lib.rs | 1 + 9 files changed, 424 insertions(+), 405 deletions(-) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 7ecec0b9a69ac..c41ede91a0e55 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -30,6 +30,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(core_intrinsics)] diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a6e9e7147adb3..eb2d4846eec72 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2341,7 +2341,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; // When printing regions, add trailing space if necessary. - ty::print::PrintCx::with(|cx| { + ty::print::PrintCx::with(ty::print::FmtPrinter { fmt }, |cx| { let region = if cx.is_verbose || cx.identify_regions { let mut region = region.to_string(); if region.len() > 0 { @@ -2352,7 +2352,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { // Do not even print 'static String::new() }; - write!(fmt, "&{}{}{:?}", region, kind_str, place) + write!(cx.printer.fmt, "&{}{}{:?}", region, kind_str, place) }) } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 4813a969e58e5..dbaafc5527621 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -59,11 +59,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// root, unless with_forced_absolute_paths was used. pub fn item_path_str(self, def_id: DefId) -> String { debug!("item_path_str: def_id={:?}", def_id); - let mut cx = PrintCx::new(self); if FORCE_ABSOLUTE.with(|force| force.get()) { - AbsolutePathPrinter::print_item_path(&mut cx, def_id) + PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id) } else { - LocalPathPrinter::print_item_path(&mut cx, def_id) + PrintCx::new(self, LocalPathPrinter).print_item_path(def_id) } } @@ -76,26 +75,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// suitable for user output. It always begins with a crate identifier. pub fn absolute_item_path_str(self, def_id: DefId) -> String { debug!("absolute_item_path_str: def_id={:?}", def_id); - let mut cx = PrintCx::new(self); - AbsolutePathPrinter::print_item_path(&mut cx, def_id) + PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id) } } -impl PrintCx<'a, 'gcx, 'tcx> { - pub fn default_print_item_path

(&mut self, def_id: DefId) -> P::Path - where P: ItemPathPrinter - { +impl PrintCx<'a, 'gcx, 'tcx, P> { + pub fn default_print_item_path(&mut self, def_id: DefId) -> P::Path { debug!("default_print_item_path: def_id={:?}", def_id); let key = self.tcx.def_key(def_id); debug!("default_print_item_path: key={:?}", key); match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); - P::path_crate(self, def_id.krate) + self.path_crate(def_id.krate) } DefPathData::Impl => { - self.default_print_impl_path::

(def_id) + self.default_print_impl_path(def_id) } // Unclear if there is any value in distinguishing these. @@ -120,20 +116,18 @@ impl PrintCx<'a, 'gcx, 'tcx> { data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { let parent_did = self.tcx.parent_def_id(def_id).unwrap(); - let path = P::print_item_path(self, parent_did); - P::path_append(path, &data.as_interned_str().as_symbol().as_str()) + let path = self.print_item_path(parent_did); + self.path_append(path, &data.as_interned_str().as_symbol().as_str()) }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); - P::print_item_path(self, parent_def_id) + self.print_item_path(parent_def_id) } } } - fn default_print_impl_path

(&mut self, impl_def_id: DefId) -> P::Path - where P: ItemPathPrinter - { + fn default_print_impl_path(&mut self, impl_def_id: DefId) -> P::Path { debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); @@ -146,7 +140,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { }; if !use_types { - return self.default_print_impl_path_fallback::

(impl_def_id); + return self.default_print_impl_path_fallback(impl_def_id); } // Decide whether to print the parent path for the impl. @@ -170,11 +164,11 @@ impl PrintCx<'a, 'gcx, 'tcx> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - let path = P::print_item_path(self, parent_def_id); + let path = self.print_item_path(parent_def_id); if let Some(trait_ref) = impl_trait_ref { - return P::path_append(path, &format!("", trait_ref, self_ty)); + return self.path_append(path, &format!("", trait_ref, self_ty)); } else { - return P::path_append(path, &format!("", self_ty)); + return self.path_append(path, &format!("", self_ty)); } } @@ -183,7 +177,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { if let Some(trait_ref) = impl_trait_ref { // Trait impls. - return P::path_impl(&format!("<{} as {}>", self_ty, trait_ref)); + return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref)); } // Inherent impls. Try to print `Foo::bar` for an inherent @@ -193,13 +187,13 @@ impl PrintCx<'a, 'gcx, 'tcx> { ty::Adt(adt_def, substs) => { // FIXME(eddyb) always print without <> here. if substs.types().next().is_none() { // ignore regions - P::print_item_path(self, adt_def.did) + self.print_item_path(adt_def.did) } else { - P::path_impl(&format!("<{}>", self_ty)) + self.path_impl(&format!("<{}>", self_ty)) } } - ty::Foreign(did) => P::print_item_path(self, did), + ty::Foreign(did) => self.print_item_path(did), ty::Bool | ty::Char | @@ -207,28 +201,26 @@ impl PrintCx<'a, 'gcx, 'tcx> { ty::Uint(_) | ty::Float(_) | ty::Str => { - P::path_impl(&self_ty.to_string()) + self.path_impl(&self_ty.to_string()) } _ => { - P::path_impl(&format!("<{}>", self_ty)) + self.path_impl(&format!("<{}>", self_ty)) } } } - fn default_print_impl_path_fallback

(&mut self, impl_def_id: DefId) -> P::Path - where P: ItemPathPrinter - { + fn default_print_impl_path_fallback(&mut self, impl_def_id: DefId) -> P::Path { // If no type info is available, fall back to // pretty printing some span information. This should // only occur very early in the compiler pipeline. // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); - let path = P::print_item_path(self, parent_def_id); + let path = self.print_item_path(parent_def_id); let node_id = self.tcx.hir().as_local_node_id(impl_def_id).unwrap(); let item = self.tcx.hir().expect_item(node_id); let span_str = self.tcx.sess.source_map().span_to_string(item.span); - P::path_append(path, &format!("", span_str)) + self.path_append(path, &format!("", span_str)) } } @@ -295,13 +287,17 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { pub trait ItemPathPrinter: Sized { type Path; - fn print_item_path(cx: &mut PrintCx<'_, '_, '_>, def_id: DefId) -> Self::Path { - cx.default_print_item_path::(def_id) + fn print_item_path(self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId) -> Self::Path { + self.default_print_item_path(def_id) } - fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path; - fn path_impl(text: &str) -> Self::Path; - fn path_append(path: Self::Path, text: &str) -> Self::Path; + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + path: Self::Path, + text: &str, + ) -> Self::Path; } struct AbsolutePathPrinter; @@ -309,13 +305,17 @@ struct AbsolutePathPrinter; impl ItemPathPrinter for AbsolutePathPrinter { type Path = String; - fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { - cx.tcx.original_crate_name(cnum).to_string() + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + self.tcx.original_crate_name(cnum).to_string() } - fn path_impl(text: &str) -> Self::Path { + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { text.to_string() } - fn path_append(mut path: Self::Path, text: &str) -> Self::Path { + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + mut path: Self::Path, + text: &str, + ) -> Self::Path { if !path.is_empty() { path.push_str("::"); } @@ -331,7 +331,7 @@ impl LocalPathPrinter { /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_item_path( - cx: &mut PrintCx<'_, '_, '_>, + self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId, ) -> Option<::Path> { debug!("try_print_visible_item_path: def_id={:?}", def_id); @@ -342,7 +342,7 @@ impl LocalPathPrinter { let cnum = def_id.krate; if cnum == LOCAL_CRATE { - return Some(Self::path_crate(cx, cnum)); + return Some(self.path_crate(cnum)); } // In local mode, when we encounter a crate other than @@ -355,7 +355,7 @@ impl LocalPathPrinter { // 2. for an extern inferred from a path or an indirect crate, // where there is no explicit `extern crate`, we just prepend // the crate name. - match *cx.tcx.extern_crate(def_id) { + match *self.tcx.extern_crate(def_id) { Some(ExternCrate { src: ExternCrateSource::Extern(def_id), direct: true, @@ -364,14 +364,14 @@ impl LocalPathPrinter { }) => { debug!("try_print_visible_item_path: def_id={:?}", def_id); let path = if !span.is_dummy() { - Self::print_item_path(cx, def_id) + self.print_item_path(def_id) } else { - Self::path_crate(cx, cnum) + self.path_crate(cnum) }; return Some(path); } None => { - return Some(Self::path_crate(cx, cnum)); + return Some(self.path_crate(cnum)); } _ => {}, } @@ -381,9 +381,9 @@ impl LocalPathPrinter { return None; } - let visible_parent_map = cx.tcx.visible_parent_map(LOCAL_CRATE); + let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); - let mut cur_def_key = cx.tcx.def_key(def_id); + let mut cur_def_key = self.tcx.def_key(def_id); debug!("try_print_visible_item_path: cur_def_key={:?}", cur_def_key); // For a UnitStruct or TupleStruct we want the name of its parent rather than . @@ -393,12 +393,12 @@ impl LocalPathPrinter { index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), }; - cur_def_key = cx.tcx.def_key(parent); + cur_def_key = self.tcx.def_key(parent); } let visible_parent = visible_parent_map.get(&def_id).cloned()?; - let path = Self::try_print_visible_item_path(cx, visible_parent)?; - let actual_parent = cx.tcx.parent(def_id); + let path = self.try_print_visible_item_path(visible_parent)?; + let actual_parent = self.tcx.parent(def_id); let data = cur_def_key.disambiguated_data.data; debug!( @@ -442,7 +442,7 @@ impl LocalPathPrinter { DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { visible_parent .and_then(|parent| { - self.item_children(parent) + self.tcx.item_children(parent) .iter() .find(|child| child.def.def_id() == cur_def) .map(|child| child.ident.as_str()) @@ -453,7 +453,7 @@ impl LocalPathPrinter { data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { // Re-exported `extern crate` (#43189). if let DefPathData::CrateRoot = data { - cx.tcx.original_crate_name(def_id.krate).as_str() + self.tcx.original_crate_name(def_id.krate).as_str() } else { Symbol::intern("").as_str() } @@ -461,21 +461,21 @@ impl LocalPathPrinter { }, }; debug!("try_print_visible_item_path: symbol={:?}", symbol); - Some(Self::path_append(path, &symbol)) + Some(self.path_append(path, &symbol)) } } impl ItemPathPrinter for LocalPathPrinter { type Path = String; - fn print_item_path(cx: &mut PrintCx<'_, '_, '_>, def_id: DefId) -> Self::Path { - Self::try_print_visible_item_path(cx, def_id) - .unwrap_or_else(|| cx.default_print_item_path::(def_id)) + fn print_item_path(self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId) -> Self::Path { + self.try_print_visible_item_path(def_id) + .unwrap_or_else(|| self.default_print_item_path(def_id)) } - fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { if cnum == LOCAL_CRATE { - if cx.tcx.sess.rust_2018() { + if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { return keywords::Crate.name().to_string(); @@ -483,13 +483,17 @@ impl ItemPathPrinter for LocalPathPrinter { } String::new() } else { - cx.tcx.crate_name(cnum).to_string() + self.tcx.crate_name(cnum).to_string() } } - fn path_impl(text: &str) -> Self::Path { + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { text.to_string() } - fn path_append(mut path: Self::Path, text: &str) -> Self::Path { + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + mut path: Self::Path, + text: &str, + ) -> Self::Path { if !path.is_empty() { path.push_str("::"); } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index fb062695fc095..df96cb55663be 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -4,6 +4,7 @@ use rustc_data_structures::fx::FxHashSet; use syntax::symbol::InternedString; use std::fmt; +use std::ops::Deref; // FIXME(eddyb) this module uses `pub(crate)` for things used only // from `ppaux` - when that is removed, they can be re-privatized. @@ -21,8 +22,9 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } } -pub struct PrintCx<'a, 'gcx, 'tcx> { +pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub printer: P, pub(crate) is_debug: bool, pub(crate) is_verbose: bool, pub(crate) identify_regions: bool, @@ -31,10 +33,20 @@ pub struct PrintCx<'a, 'gcx, 'tcx> { pub(crate) binder_depth: usize, } -impl PrintCx<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Self { +// HACK(eddyb) this is solely for `self: &mut PrintCx`, e.g. to +// implement traits on the printer and call the methods on the context. +impl

Deref for PrintCx<'_, '_, '_, P> { + type Target = P; + fn deref(&self) -> &P { + &self.printer + } +} + +impl

PrintCx<'a, 'gcx, 'tcx, P> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, printer: P) -> Self { PrintCx { tcx, + printer, is_debug: false, is_verbose: tcx.sess.verbose(), identify_regions: tcx.sess.opts.debugging_opts.identify_regions, @@ -44,8 +56,8 @@ impl PrintCx<'a, 'gcx, 'tcx> { } } - pub(crate) fn with(f: impl FnOnce(PrintCx<'_, '_, '_>) -> R) -> R { - ty::tls::with(|tcx| f(PrintCx::new(tcx))) + pub(crate) fn with(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { + ty::tls::with(|tcx| f(PrintCx::new(tcx, printer))) } pub(crate) fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) where T: TypeFoldable<'tcx> @@ -57,24 +69,26 @@ impl PrintCx<'a, 'gcx, 'tcx> { } } -pub trait Print<'tcx> { - fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result; - fn print_display( - &self, - f: &mut F, - cx: &mut PrintCx<'_, '_, 'tcx>, - ) -> fmt::Result { +pub trait Print<'tcx, P> { + type Output; + + fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output; + fn print_display(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output { let old_debug = cx.is_debug; cx.is_debug = false; - let result = self.print(f, cx); + let result = self.print(cx); cx.is_debug = old_debug; result } - fn print_debug(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result { + fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output { let old_debug = cx.is_debug; cx.is_debug = true; - let result = self.print(f, cx); + let result = self.print(cx); cx.is_debug = old_debug; result } } + +pub struct FmtPrinter { + pub fmt: F, +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index e5216c84d0e7e..94cf91f2547a4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TypeFoldable}; -use ty::print::{PrintCx, Print}; +use ty::print::{FmtPrinter, PrintCx, Print}; use std::cell::Cell; use std::fmt; @@ -161,8 +161,8 @@ impl RegionHighlightMode { macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(|mut cx| { - $with(&cx.tcx.lift(self).expect("could not lift for printing"), f, &mut cx) + PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { + $with(&cx.tcx.lift(self).expect("could not lift for printing"), &mut cx) }) } }; @@ -191,25 +191,19 @@ macro_rules! gen_display_debug { ( $generic:tt $target:ty, $t:ident no ) => {}; } macro_rules! gen_print_impl { - ( ($($x:tt)+) $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { - impl<$($x)+> Print<'tcx> for $target { - fn print( - &$self, - $f: &mut F, - $cx: &mut PrintCx<'_, '_, 'tcx>, - ) -> fmt::Result { + ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { + impl<$($x)+, F: fmt::Write> Print<'tcx, FmtPrinter> for $target { + type Output = fmt::Result; + fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter>) -> fmt::Result { if $cx.is_debug $dbg else $disp } } }; - ( () $target:ty, ($self:ident, $f:ident, $cx:ident) $disp:block $dbg:block ) => { - impl Print<'tcx> for $target { - fn print( - &$self, - $f: &mut F, - $cx: &mut PrintCx<'_, '_, 'tcx>, - ) -> fmt::Result { + ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { + impl Print<'tcx, FmtPrinter> for $target { + type Output = fmt::Result; + fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter>) -> fmt::Result { if $cx.is_debug $dbg else $disp } @@ -238,9 +232,9 @@ macro_rules! define_print { } yes $dbg } }; ( $generic:tt $target:ty, - ($self:ident, $f:ident, $cx:ident) { display $disp:block } ) => { - gen_print_impl! { $generic $target, ($self, $f, $cx) yes $disp no { - write!($f, "{:?}", $self) + ($self:ident, $cx:ident) { display $disp:block } ) => { + gen_print_impl! { $generic $target, ($self, $cx) yes $disp no { + write!($cx.printer.fmt, "{:?}", $self) } } }; } @@ -250,48 +244,47 @@ macro_rules! define_print_multi { }; } macro_rules! print_inner { - ( $f:expr, $cx:expr, write ($($data:expr),+) ) => { - write!($f, $($data),+) + ( $cx:expr, write ($($data:expr),+) ) => { + write!($cx.printer.fmt, $($data),+) }; - ( $f:expr, $cx:expr, $kind:ident ($data:expr) ) => { - $data.$kind($f, $cx) + ( $cx:expr, $kind:ident ($data:expr) ) => { + $data.$kind($cx) }; } macro_rules! print { - ( $f:expr, $cx:expr $(, $kind:ident $data:tt)+ ) => { - Ok(())$(.and_then(|_| print_inner!($f, $cx, $kind $data)))+ + ( $cx:expr $(, $kind:ident $data:tt)+ ) => { + Ok(())$(.and_then(|_| print_inner!($cx, $kind $data)))+ }; } -impl PrintCx<'a, 'gcx, 'tcx> { - fn fn_sig(&mut self, - f: &mut F, - inputs: &[Ty<'tcx>], - variadic: bool, - output: Ty<'tcx>) - -> fmt::Result { - write!(f, "(")?; +impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { + fn fn_sig( + &mut self, + inputs: &[Ty<'tcx>], + variadic: bool, + output: Ty<'tcx>, + ) -> fmt::Result { + print!(self, write("("))?; let mut inputs = inputs.iter(); if let Some(&ty) = inputs.next() { - print!(f, self, print_display(ty))?; + print!(self, print_display(ty))?; for &ty in inputs { - print!(f, self, write(", "), print_display(ty))?; + print!(self, write(", "), print_display(ty))?; } if variadic { - write!(f, ", ...")?; + print!(self, write(", ..."))?; } } - write!(f, ")")?; + print!(self, write(")"))?; if !output.is_unit() { - print!(f, self, write(" -> "), print_display(output))?; + print!(self, write(" -> "), print_display(output))?; } Ok(()) } - fn parameterized( + fn parameterized( &mut self, - f: &mut F, mut def_id: DefId, substs: &Substs<'tcx>, projections: impl Iterator>, @@ -321,41 +314,41 @@ impl PrintCx<'a, 'gcx, 'tcx> { let parent_has_own_self = parent_generics.has_self && parent_generics.parent_count == 0; if parent_has_own_self { - print!(f, self, write("<"), print_display(substs.type_at(0)), write(" as "))?; + print!(self, write("<"), print_display(substs.type_at(0)), write(" as "))?; } - self.parameterized(f, parent_def_id, substs, iter::empty())?; + self.parameterized(parent_def_id, substs, iter::empty())?; if parent_has_own_self { - write!(f, ">")?; + print!(self, write(">"))?; } - write!(f, "::{}", key.disambiguated_data.data.as_interned_str())?; + print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?; } else { // Try to print `impl`s more like how you'd refer to their associated items. if let DefPathData::Impl = key.disambiguated_data.data { if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { // HACK(eddyb) this is in lieu of more specific disambiguation. - print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?; + print!(self, write("{}", self.tcx.item_path_str(def_id)))?; let trait_ref = trait_ref.subst(self.tcx, substs); - print!(f, self, print_debug(trait_ref))?; + print!(self, print_debug(trait_ref))?; } else { let self_ty = self.tcx.type_of(def_id).subst(self.tcx, substs); // FIXME(eddyb) omit the <> where possible. - print!(f, self, write("<"), print(self_ty), write(">"))?; + print!(self, write("<"), print(self_ty), write(">"))?; } return Ok(()); } - print!(f, self, write("{}", self.tcx.item_path_str(def_id)))?; + print!(self, write("{}", self.tcx.item_path_str(def_id)))?; } let mut empty = true; - let mut start_or_continue = |f: &mut F, start: &str, cont: &str| { + let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { if empty { empty = false; - write!(f, "{}", start) + print!(cx, write("{}", start)) } else { - write!(f, "{}", cont) + print!(cx, write("{}", cont)) } }; @@ -394,38 +387,38 @@ impl PrintCx<'a, 'gcx, 'tcx> { if !print_regions { continue; } - start_or_continue(f, start, ", ")?; + start_or_continue(self, start, ", ")?; if !region.display_outputs_anything(self) { // This happens when the value of the region // parameter is not easily serialized. This may be // because the user omitted it in the first place, // or because it refers to some block in the code, // etc. I'm not sure how best to serialize this. - write!(f, "'_")?; + print!(self, write("'_"))?; } else { - region.print_display(f, self)?; + region.print_display(self)?; } } UnpackedKind::Type(ty) => { - start_or_continue(f, start, ", ")?; - ty.print_display(f, self)?; + start_or_continue(self, start, ", ")?; + ty.print_display(self)?; } } } for projection in projections { - start_or_continue(f, start, ", ")?; - print!(f, self, + start_or_continue(self, start, ", ")?; + print!(self, write("{}=", self.tcx.associated_item(projection.item_def_id).ident), print_display(projection.ty))?; } - start_or_continue(f, "", ">") + start_or_continue(self, "", ">") } - fn in_binder(&mut self, f: &mut F, value: &ty::Binder) -> fmt::Result - where T: Print<'tcx> + TypeFoldable<'tcx>, F: fmt::Write + fn in_binder(&mut self, value: &ty::Binder) -> fmt::Result + where T: Print<'tcx, FmtPrinter, Output = fmt::Result> + TypeFoldable<'tcx> { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -445,22 +438,22 @@ impl PrintCx<'a, 'gcx, 'tcx> { } let mut empty = true; - let mut start_or_continue = |f: &mut F, start: &str, cont: &str| { + let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { if empty { empty = false; - write!(f, "{}", start) + print!(cx, write("{}", start)) } else { - write!(f, "{}", cont) + print!(cx, write("{}", cont)) } }; let old_region_index = self.region_index; let mut region_index = old_region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { - let _ = start_or_continue(f, "for<", ", "); + let _ = start_or_continue(self, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { - let _ = write!(f, "{}", name); + let _ = print!(self, write("{}", name)); br } ty::BrAnon(_) | @@ -473,18 +466,18 @@ impl PrintCx<'a, 'gcx, 'tcx> { break name; } }; - let _ = write!(f, "{}", name); + let _ = print!(self, write("{}", name)); ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name) } }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) }).0; - start_or_continue(f, "", "> ")?; + start_or_continue(self, "", "> ")?; // Push current state to gcx, and restore after writing new_value. self.binder_depth += 1; self.region_index = region_index; - let result = new_value.print_display(f, self); + let result = new_value.print_display(self); self.region_index = old_region_index; self.binder_depth -= 1; result @@ -499,20 +492,21 @@ impl PrintCx<'a, 'gcx, 'tcx> { } pub fn parameterized(f: &mut F, did: DefId, substs: &Substs<'_>) -> fmt::Result { - PrintCx::with(|mut cx| { + PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.parameterized(f, did, substs, iter::empty()) + cx.parameterized(did, substs, iter::empty()) }) } -impl<'a, 'tcx, T: Print<'tcx>> Print<'tcx> for &'a T { - fn print(&self, f: &mut F, cx: &mut PrintCx<'_, '_, 'tcx>) -> fmt::Result { - (*self).print(f, cx) +impl<'a, 'tcx, P, T: Print<'tcx, P>> Print<'tcx, P> for &'a T { + type Output = T::Output; + fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output { + (*self).print(cx) } } define_print! { - ('tcx) &'tcx ty::List>, (self, f, cx) { + ('tcx) &'tcx ty::List>, (self, cx) { display { // Generate the main trait ref, including associated types. let mut first = true; @@ -525,8 +519,8 @@ define_print! { if let Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - print!(f, cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?; - cx.fn_sig(f, args, false, proj.ty)?; + print!(cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?; + cx.fn_sig(args, false, proj.ty)?; resugared_principal = true; } } @@ -537,7 +531,6 @@ define_print! { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); let principal = principal.with_self_ty(cx.tcx, dummy_self); cx.parameterized( - f, principal.def_id, principal.substs, self.projection_bounds(), @@ -562,11 +555,11 @@ define_print! { for auto_trait in auto_traits { if !first { - write!(f, " + ")?; + print!(cx, write(" + "))?; } first = false; - write!(f, "{}", auto_trait)?; + print!(cx, write("{}", auto_trait))?; } Ok(()) @@ -590,16 +583,16 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(|cx| { - write!(f, "{}", cx.tcx.item_path_str(self.def_id)) + PrintCx::with(FmtPrinter { fmt: f }, |cx| { + print!(cx, write("{}", cx.tcx.item_path_str(self.def_id))) }) } } impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(|cx| { - write!(f, "{}", cx.tcx.item_path_str(self.did)) + PrintCx::with(FmtPrinter { fmt: f }, |cx| { + print!(cx, write("{}", cx.tcx.item_path_str(self.did))) }) } } @@ -614,12 +607,12 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "UpvarId({:?};`{}`;{:?})", - self.var_path.hir_id, - PrintCx::with(|cx| { - cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)) - }), - self.closure_expr_id) + PrintCx::with(FmtPrinter { fmt: f }, |cx| { + print!(cx, write("UpvarId({:?};`{}`;{:?})", + self.var_path.hir_id, + cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)), + self.closure_expr_id)) + }) } } @@ -631,25 +624,25 @@ impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { } define_print! { - ('tcx) &'tcx ty::List>, (self, f, cx) { + ('tcx) &'tcx ty::List>, (self, cx) { display { - write!(f, "{{")?; + print!(cx, write("{{"))?; let mut tys = self.iter(); if let Some(&ty) = tys.next() { - print!(f, cx, print(ty))?; + print!(cx, print(ty))?; for &ty in tys { - print!(f, cx, write(", "), print(ty))?; + print!(cx, write(", "), print(ty))?; } } - write!(f, "}}") + print!(cx, write("}}")) } } } define_print! { - ('tcx) ty::TypeAndMut<'tcx>, (self, f, cx) { + ('tcx) ty::TypeAndMut<'tcx>, (self, cx) { display { - print!(f, cx, + print!(cx, write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), print(self.ty)) } @@ -657,46 +650,46 @@ define_print! { } define_print! { - ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) { + ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) { display { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); let trait_ref = *ty::Binder::bind(*self) .with_self_ty(cx.tcx, dummy_self) .skip_binder(); - cx.parameterized(f, trait_ref.def_id, trait_ref.substs, iter::empty()) + cx.parameterized(trait_ref.def_id, trait_ref.substs, iter::empty()) } debug { - self.print_display(f, cx) + self.print_display(cx) } } } define_print! { - ('tcx) ty::adjustment::Adjustment<'tcx>, (self, f, cx) { + ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) { debug { - print!(f, cx, write("{:?} -> ", self.kind), print(self.target)) + print!(cx, write("{:?} -> ", self.kind), print(self.target)) } } } define_print! { - () ty::BoundRegion, (self, f, cx) { + () ty::BoundRegion, (self, cx) { display { if cx.is_verbose { - return self.print_debug(f, cx); + return self.print_debug(cx); } if let BrNamed(_, name) = *self { if name != "" && name != "'_" { - return write!(f, "{}", name); + return print!(cx, write("{}", name)); } } let highlight = RegionHighlightMode::get(); if let Some((region, counter)) = highlight.highlight_bound_region { if *self == region { - return write!(f, "'{}", counter); + return print!(cx, write("'{}", counter)); } } @@ -704,13 +697,13 @@ define_print! { } debug { return match *self { - BrAnon(n) => write!(f, "BrAnon({:?})", n), - BrFresh(n) => write!(f, "BrFresh({:?})", n), + BrAnon(n) => print!(cx, write("BrAnon({:?})", n)), + BrFresh(n) => print!(cx, write("BrFresh({:?})", n)), BrNamed(did, name) => { - write!(f, "BrNamed({:?}:{:?}, {})", - did.krate, did.index, name) + print!(cx, write("BrNamed({:?}:{:?}, {})", + did.krate, did.index, name)) } - BrEnv => write!(f, "BrEnv"), + BrEnv => print!(cx, write("BrEnv")), }; } } @@ -720,7 +713,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::BoundRegion { - fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { if cx.is_verbose { return true; } @@ -743,18 +736,18 @@ impl ty::BoundRegion { } define_print! { - () ty::PlaceholderRegion, (self, f, cx) { + () ty::PlaceholderRegion, (self, cx) { display { if cx.is_verbose { - return self.print_debug(f, cx); + return self.print_debug(cx); } let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.placeholder_highlight(*self) { - return write!(f, "'{}", counter); + return print!(cx, write("'{}", counter)); } - write!(f, "{}", self.name) + print!(cx, print_display(self.name)) } } } @@ -763,7 +756,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::PlaceholderRegion { - fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { if cx.is_verbose { return true; } @@ -778,15 +771,15 @@ impl ty::PlaceholderRegion { } define_print! { - () ty::RegionKind, (self, f, cx) { + () ty::RegionKind, (self, cx) { display { if cx.is_verbose { - return self.print_debug(f, cx); + return self.print_debug(cx); } // Watch out for region highlights. if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { - return write!(f, "'{:?}", n); + return print!(cx, write("'{:?}", n)); } // These printouts are concise. They do not contain all the information @@ -796,89 +789,88 @@ define_print! { match *self { ty::ReEarlyBound(ref data) => { if data.name != "'_" { - write!(f, "{}", data.name) + print!(cx, write("{}", data.name)) } else { Ok(()) } } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { - write!(f, "{}", br) + print!(cx, print_display(br)) } ty::RePlaceholder(p) => { - write!(f, "{}", p) + print!(cx, print_display(p)) } ty::ReScope(scope) if cx.identify_regions => { match scope.data { region::ScopeData::Node => - write!(f, "'{}s", scope.item_local_id().as_usize()), + print!(cx, write("'{}s", scope.item_local_id().as_usize())), region::ScopeData::CallSite => - write!(f, "'{}cs", scope.item_local_id().as_usize()), + print!(cx, write("'{}cs", scope.item_local_id().as_usize())), region::ScopeData::Arguments => - write!(f, "'{}as", scope.item_local_id().as_usize()), + print!(cx, write("'{}as", scope.item_local_id().as_usize())), region::ScopeData::Destruction => - write!(f, "'{}ds", scope.item_local_id().as_usize()), - region::ScopeData::Remainder(first_statement_index) => write!( - f, + print!(cx, write("'{}ds", scope.item_local_id().as_usize())), + region::ScopeData::Remainder(first_statement_index) => print!(cx, write( "'{}_{}rs", scope.item_local_id().as_usize(), first_statement_index.index() - ), + )), } } ty::ReVar(region_vid) if cx.identify_regions => { - write!(f, "{:?}", region_vid) + print!(cx, print_debug(region_vid)) } ty::ReVar(region_vid) => { - write!(f, "{}", region_vid) + print!(cx, print_display(region_vid)) } ty::ReScope(_) | ty::ReErased => Ok(()), - ty::ReStatic => write!(f, "'static"), - ty::ReEmpty => write!(f, "'"), + ty::ReStatic => print!(cx, write("'static")), + ty::ReEmpty => print!(cx, write("'")), // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => write!(f, "{:?}", vid), + ty::ReClosureBound(vid) => print!(cx, write("{:?}", vid)), } } debug { match *self { ty::ReEarlyBound(ref data) => { - write!(f, "ReEarlyBound({}, {})", + print!(cx, write("ReEarlyBound({}, {})", data.index, - data.name) + data.name)) } ty::ReClosureBound(ref vid) => { - write!(f, "ReClosureBound({:?})", - vid) + print!(cx, write("ReClosureBound({:?})", + vid)) } ty::ReLateBound(binder_id, ref bound_region) => { - write!(f, "ReLateBound({:?}, {:?})", + print!(cx, write("ReLateBound({:?}, {:?})", binder_id, - bound_region) + bound_region)) } - ty::ReFree(ref fr) => write!(f, "{:?}", fr), + ty::ReFree(ref fr) => print!(cx, write("{:?}", fr)), ty::ReScope(id) => { - write!(f, "ReScope({:?})", id) + print!(cx, write("ReScope({:?})", id)) } - ty::ReStatic => write!(f, "ReStatic"), + ty::ReStatic => print!(cx, write("ReStatic")), ty::ReVar(ref vid) => { - write!(f, "{:?}", vid) + print!(cx, write("{:?}", vid)) } ty::RePlaceholder(placeholder) => { - write!(f, "RePlaceholder({:?})", placeholder) + print!(cx, write("RePlaceholder({:?})", placeholder)) } - ty::ReEmpty => write!(f, "ReEmpty"), + ty::ReEmpty => print!(cx, write("ReEmpty")), - ty::ReErased => write!(f, "ReErased") + ty::ReErased => print!(cx, write("ReErased")) } } } @@ -891,7 +883,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::RegionKind { - fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { if cx.is_verbose { return true; } @@ -928,17 +920,17 @@ impl ty::RegionKind { } define_print! { - () ty::FreeRegion, (self, f, cx) { + () ty::FreeRegion, (self, cx) { debug { - write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) + print!(cx, write("ReFree({:?}, {:?})", self.scope, self.bound_region)) } } } define_print! { - () ty::Variance, (self, f, cx) { + () ty::Variance, (self, cx) { debug { - f.write_str(match *self { + cx.printer.fmt.write_str(match *self { ty::Covariant => "+", ty::Contravariant => "-", ty::Invariant => "o", @@ -949,21 +941,22 @@ define_print! { } define_print! { - ('tcx) ty::FnSig<'tcx>, (self, f, cx) { + ('tcx) ty::FnSig<'tcx>, (self, cx) { display { if self.unsafety == hir::Unsafety::Unsafe { - write!(f, "unsafe ")?; + print!(cx, write("unsafe "))?; } if self.abi != Abi::Rust { - write!(f, "extern {} ", self.abi)?; + print!(cx, write("extern {} ", self.abi))?; } - write!(f, "fn")?; - cx.fn_sig(f, self.inputs(), self.variadic, self.output()) + print!(cx, write("fn"))?; + cx.fn_sig(self.inputs(), self.variadic, self.output()) } debug { - write!(f, "({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output()) + print!(cx, write("({:?}; variadic: {})->{:?}", + self.inputs(), self.variadic, self.output())) } } } @@ -987,15 +980,15 @@ impl fmt::Debug for ty::FloatVid { } define_print! { - () ty::RegionVid, (self, f, cx) { + () ty::RegionVid, (self, cx) { display { if cx.is_verbose { - return self.print_debug(f, cx); + return self.print_debug(cx); } let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - return write!(f, "'{:?}", counter); + return print!(cx, write("'{:?}", counter)); } Ok(()) @@ -1005,10 +998,10 @@ define_print! { // to keep NLL borrowck working even with `-Zverbose`. let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - return write!(f, "'{:?}", counter); + return print!(cx, write("'{:?}", counter)); } - write!(f, "'_#{}r", self.index()) + print!(cx, write("'_#{}r", self.index())) } } } @@ -1017,7 +1010,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::RegionVid { - fn display_outputs_anything(&self, cx: &mut PrintCx<'_, '_, '_>) -> bool { + fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { + // HACK(eddyb) `pub(crate)` only for `ty::print`. + pub(crate) fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { if cx.is_verbose { return true; } @@ -1085,16 +991,17 @@ define_print_multi! { define_print! { ('tcx) ty::TraitRef<'tcx>, (self, cx) { display { - cx.parameterized(self.def_id, self.substs, Namespace::TypeNS, iter::empty()) + let _ = cx.print_def_path( + self.def_id, + Some(self.substs), + Namespace::TypeNS, + iter::empty(), + )?; + Ok(()) } debug { - print!(cx, - write("<"), - print(self.self_ty()), - write(" as "), - print_display(self), - write(">") - ) + let _ = cx.path_qualified(self.self_ty(), Some(*self))?; + Ok(()) } } } @@ -1140,7 +1047,12 @@ define_print! { FnDef(def_id, substs) => { let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); print!(cx, print(sig), write(" {{"))?; - cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?; + let _ = cx.print_def_path( + def_id, + Some(substs), + Namespace::ValueNS, + iter::empty(), + )?; print!(cx, write("}}")) } FnPtr(ref bare_fn) => { @@ -1163,7 +1075,13 @@ define_print! { } } Adt(def, substs) => { - cx.parameterized(def.did, substs, Namespace::TypeNS, iter::empty()) + let _ = cx.print_def_path( + def.did, + Some(substs), + Namespace::TypeNS, + iter::empty(), + )?; + Ok(()) } Dynamic(data, r) => { let print_r = r.display_outputs_anything(cx); @@ -1178,7 +1096,13 @@ define_print! { Ok(()) } Foreign(def_id) => { - cx.parameterized(def_id, Substs::empty(), Namespace::TypeNS, iter::empty()) + let _ = cx.print_def_path( + def_id, + None, + Namespace::TypeNS, + iter::empty(), + )?; + Ok(()) } Projection(ref data) => data.print(cx), UnnormalizedProjection(ref data) => { @@ -1198,7 +1122,7 @@ define_print! { if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { print!(cx, write("{}", name))?; let mut substs = substs.iter(); - // FIXME(eddyb) print this with `parameterized`. + // FIXME(eddyb) print this with `print_def_path`. if let Some(first) = substs.next() { print!(cx, write("::<"))?; print!(cx, write("{}", first))?; @@ -1404,7 +1328,13 @@ define_print! { define_print! { ('tcx) ty::ProjectionTy<'tcx>, (self, cx) { display { - cx.parameterized(self.item_def_id, self.substs, Namespace::TypeNS, iter::empty()) + let _ = cx.print_def_path( + self.item_def_id, + Some(self.substs), + Namespace::TypeNS, + iter::empty(), + )?; + Ok(()) } } } @@ -1432,16 +1362,33 @@ define_print! { ty::Predicate::Projection(ref predicate) => predicate.print(cx), ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { - print!(cx, write("the trait `{}` is object-safe", - cx.tcx.def_path_str(trait_def_id))) + print!(cx, write("the trait `"))?; + let _ = cx.print_def_path( + trait_def_id, + None, + Namespace::TypeNS, + iter::empty(), + )?; + print!(cx, write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - print!(cx, write("the closure `{}` implements the trait `{}`", - cx.tcx.def_path_str(closure_def_id), kind)) + print!(cx, write("the closure `"))?; + let _ = cx.print_def_path( + closure_def_id, + None, + Namespace::ValueNS, + iter::empty(), + )?; + print!(cx, write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { print!(cx, write("the constant `"))?; - cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?; + let _ = cx.print_def_path( + def_id, + Some(substs), + Namespace::ValueNS, + iter::empty(), + )?; print!(cx, write("` can be evaluated")) } } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 0d0da0da5c365..bb3b347b6a8fe 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -10,6 +10,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] #![feature(custom_attribute)] +#![feature(in_band_lifetimes)] #![feature(nll)] #![allow(unused_attributes)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 6fc838d1b22a2..9a96adeaf9434 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -93,7 +93,7 @@ use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::print::{PrintCx, Printer}; +use rustc::ty::print::{PrettyPath, PrettyPrinter, PrintCx, Printer}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -104,8 +104,9 @@ use rustc_mir::monomorphize::Instance; use syntax_pos::symbol::Symbol; -use std::fmt::Write; -use std::mem::discriminant; +use std::fmt::{self, Write}; +use std::iter; +use std::mem::{self, discriminant}; pub fn provide(providers: &mut Providers) { *providers = Providers { @@ -223,9 +224,9 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { ty::print::with_forced_absolute_paths(|| { - PrintCx::new(tcx, SymbolPathPrinter) - .print_def_path(def_id, None, Namespace::ValueNS) - .into_interned() + let mut cx = PrintCx::new(tcx, SymbolPath::new()); + let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); + cx.printer.into_interned() }) } @@ -321,7 +322,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id)); if instance.is_vtable_shim() { - buf.push("{{vtable-shim}}"); + let _ = buf.write_str("{{vtable-shim}}"); } buf.finish(hash) @@ -344,6 +345,12 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance struct SymbolPath { result: String, temp_buf: String, + + // When `true`, `finalize_pending_component` is a noop. + // This is needed when recursing into `path_qualified`, + // or `path_generic_args`, as any nested paths are + // logically within one component. + keep_within_component: bool, } impl SymbolPath { @@ -351,6 +358,7 @@ impl SymbolPath { let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), + keep_within_component: false, }; result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested result @@ -360,70 +368,105 @@ impl SymbolPath { let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), + keep_within_component: false, }; result.result.push_str(&symbol.as_str()); result } - fn into_interned(self) -> ty::SymbolName { + fn into_interned(mut self) -> ty::SymbolName { + self.finalize_pending_component(); ty::SymbolName { name: Symbol::intern(&self.result).as_interned_str(), } } - fn push(&mut self, text: &str) { - self.temp_buf.clear(); - let need_underscore = sanitize(&mut self.temp_buf, text); - let _ = write!( - self.result, - "{}", - self.temp_buf.len() + (need_underscore as usize) - ); - if need_underscore { - self.result.push('_'); + fn finalize_pending_component(&mut self) { + if !self.keep_within_component && !self.temp_buf.is_empty() { + let _ = write!(self.result, "{}{}", self.temp_buf.len(), self.temp_buf); + self.temp_buf.clear(); } - self.result.push_str(&self.temp_buf); } fn finish(mut self, hash: u64) -> String { + self.finalize_pending_component(); // E = end name-sequence let _ = write!(self.result, "17h{:016x}E", hash); self.result } } -struct SymbolPathPrinter; +// HACK(eddyb) this relies on using the `fmt` interface to get +// `PrettyPrinter` aka pretty printing of e.g. types in paths, +// symbol names should have their own printing machinery. +impl fmt::Write for SymbolPath { + fn write_str(&mut self, s: &str) -> fmt::Result { + sanitize(&mut self.temp_buf, s); + Ok(()) + } +} -impl Printer for SymbolPathPrinter { - type Path = SymbolPath; +impl Printer for SymbolPath { + type Path = Result; fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { - let mut path = SymbolPath::new(); - path.push(&self.tcx.original_crate_name(cnum).as_str()); - path + self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?; + Ok(PrettyPath { empty: false }) + } + fn path_qualified( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Self::Path { + let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); + let r = self.pretty_path_qualified(self_ty, trait_ref); + self.printer.keep_within_component = kept_within_component; + r } fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - let mut path = SymbolPath::new(); - path.push(text); - path + self.printer.write_str(text)?; + Ok(PrettyPath { empty: false }) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, + _: Self::Path, text: &str, ) -> Self::Path { - path.push(text); - path + self.printer.finalize_pending_component(); + self.printer.write_str(text)?; + Ok(PrettyPath { empty: false }) + } + fn path_generic_args( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + path: Self::Path, + params: &[ty::GenericParamDef], + substs: &'tcx Substs<'tcx>, + ns: Namespace, + projections: impl Iterator>, + ) -> Self::Path { + let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); + let r = self.pretty_path_generic_args(path, params, substs, ns, projections); + self.printer.keep_within_component = kept_within_component; + r } } +impl PrettyPrinter for SymbolPath {} + // Name sanitation. LLVM will happily accept identifiers with weird names, but // gas doesn't! // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $ -// -// returns true if an underscore must be added at the start -pub fn sanitize(result: &mut String, s: &str) -> bool { +fn sanitize(result: &mut String, s: &str) { for c in s.chars() { + if result.is_empty() { + match c { + 'a'..='z' | 'A'..='Z' | '_' => {} + _ => { + // Underscore-qualify anything that didn't start as an ident. + result.push('_'); + } + } + } match c { // Escape these with $ sequences '@' => result.push_str("$SP$"), @@ -455,7 +498,4 @@ pub fn sanitize(result: &mut String, s: &str) -> bool { } } - // Underscore-qualify anything that didn't start as an ident. - !result.is_empty() && result.as_bytes()[0] != '_' as u8 - && !(result.as_bytes()[0] as char).is_xid_start() } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 16f0bf46bead3..7bc966593a281 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -39,7 +39,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::default::Default; use std::{mem, slice, vec}; -use std::iter::{FromIterator, once}; +use std::iter::{self, FromIterator, once}; use std::rc::Rc; use std::str::FromStr; use std::cell::RefCell; @@ -4055,6 +4055,18 @@ where F: Fn(DefId) -> Def { fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { vec![self.tcx.original_crate_name(cnum).to_string()] } + fn path_qualified( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Self::Path { + // This shouldn't ever be needed, but just in case: + if let Some(trait_ref) = trait_ref { + vec![format!("{:?}", trait_ref)] + } else { + vec![format!("<{}>", self_ty)] + } + } fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { vec![text.to_string()] } @@ -4066,10 +4078,20 @@ where F: Fn(DefId) -> Def { path.push(text.to_string()); path } + fn path_generic_args( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + path: Self::Path, + _params: &[ty::GenericParamDef], + _substs: &'tcx Substs<'tcx>, + _ns: Namespace, + _projections: impl Iterator>, + ) -> Self::Path { + path + } } let names = PrintCx::new(tcx, AbsolutePathPrinter) - .print_def_path(def_id, None, Namespace::TypeNS); + .print_def_path(def_id, None, Namespace::TypeNS, iter::empty()); hir::Path { span: DUMMY_SP, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 3ec25e2219ed5..8f3567761b6e8 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -8,6 +8,7 @@ #![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(in_band_lifetimes)] #![feature(nll)] #![feature(set_stdio)] #![feature(slice_sort_by_cached_key)] diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 992527017fb7c..c712137e828f9 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -5,7 +5,7 @@ mod foo { pub struct Foo { x: u32 } impl Foo { - #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar + #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar) fn bar() { } } diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index c547262e52b72..9c7a6f771528e 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,7 +1,7 @@ -error: symbol-name(_ZN15impl1..foo..Foo3bar17hc487d6ec13fe9124E) +error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) --> $DIR/impl1.rs:8:9 | -LL | #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar +LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar | ^^^^^^^^^^^^^^^^^^^^ error: def-path(foo::Foo::bar) From 700f3f137d33cf3ae6687bff8c47dd9ff1897cee Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 21 Dec 2018 17:31:33 +0200 Subject: [PATCH 29/68] rustc: move <...>-less impl path special-case to pretty_path_qualified. --- src/librustc/ty/print.rs | 65 ++++++++++------------ src/librustc/util/ppaux.rs | 2 +- src/librustc_codegen_utils/symbol_names.rs | 18 ++++-- src/librustdoc/clean/mod.rs | 4 +- 4 files changed, 43 insertions(+), 46 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index bc2c2d9f78425..1664834bd602e 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -173,10 +173,9 @@ pub trait Printer: Sized { self: &mut PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, + ns: Namespace, ) -> Self::Path; #[must_use] - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; - #[must_use] fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, path: Self::Path, @@ -290,7 +289,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { parent_generics.has_self && parent_generics.parent_count == 0; if let (Some(substs), true) = (substs, parent_has_own_self) { let trait_ref = ty::TraitRef::new(parent_def_id, substs); - self.path_qualified(trait_ref.self_ty(), Some(trait_ref)) + self.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns) } else { self.print_def_path(parent_def_id, substs, ns, iter::empty()) } @@ -366,35 +365,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // Otherwise, try to give a good form that would be valid language // syntax. Preferably using associated item notation. - - if let Some(trait_ref) = impl_trait_ref { - // Trait impls. - return self.path_qualified(self_ty, Some(trait_ref)); - } - - // Inherent impls. Try to print `Foo::bar` for an inherent - // impl on `Foo`, but fallback to `::bar` if self-type is - // anything other than a simple path. - match self_ty.sty { - ty::Adt(adt_def, substs) => { - self.print_def_path(adt_def.did, Some(substs), ns, iter::empty()) - } - - ty::Foreign(did) => self.print_def_path(did, None, ns, iter::empty()), - - ty::Bool | - ty::Char | - ty::Int(_) | - ty::Uint(_) | - ty::Float(_) | - ty::Str => { - self.path_impl(&self_ty.to_string()) - } - - _ => { - self.path_qualified(self_ty, None) - } - } + self.path_qualified(self_ty, impl_trait_ref, ns) } } @@ -589,7 +560,30 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { &mut self, self_ty: Ty<'tcx>, trait_ref: Option>, + ns: Namespace, ) -> P::Path { + if trait_ref.is_none() { + // Inherent impls. Try to print `Foo::bar` for an inherent + // impl on `Foo`, but fallback to `::bar` if self-type is + // anything other than a simple path. + match self_ty.sty { + ty::Adt(adt_def, substs) => { + return self.print_def_path(adt_def.did, Some(substs), ns, iter::empty()); + } + ty::Foreign(did) => { + return self.print_def_path(did, None, ns, iter::empty()); + } + + ty::Bool | ty::Char | ty::Str | + ty::Int(_) | ty::Uint(_) | ty::Float(_) => { + self_ty.print_display(self)?; + return Ok(PrettyPath { empty: false }); + } + + _ => {} + } + } + write!(self.printer, "<")?; self_ty.print_display(self)?; if let Some(trait_ref) = trait_ref { @@ -778,12 +772,9 @@ impl Printer for FmtPrinter { self: &mut PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, + ns: Namespace, ) -> Self::Path { - self.pretty_path_qualified(self_ty, trait_ref) - } - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - write!(self.printer, "{}", text)?; - Ok(PrettyPath { empty: false }) + self.pretty_path_qualified(self_ty, trait_ref, ns) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 2ed6a036a4bd8..f241e6cf2a5e2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1000,7 +1000,7 @@ define_print! { Ok(()) } debug { - let _ = cx.path_qualified(self.self_ty(), Some(*self))?; + let _ = cx.path_qualified(self.self_ty(), Some(*self), Namespace::TypeNS)?; Ok(()) } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 9a96adeaf9434..84c78f7dd96bf 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -417,16 +417,24 @@ impl Printer for SymbolPath { self: &mut PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, + ns: Namespace, ) -> Self::Path { + // HACK(eddyb) avoid `keep_within_component` for the cases + // that print without `<...>` around `self_ty`. + match self_ty.sty { + ty::Adt(..) | ty::Foreign(_) | + ty::Bool | ty::Char | ty::Str | + ty::Int(_) | ty::Uint(_) | ty::Float(_) if trait_ref.is_none() => { + return self.pretty_path_qualified(self_ty, trait_ref, ns); + } + _ => {} + } + let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); - let r = self.pretty_path_qualified(self_ty, trait_ref); + let r = self.pretty_path_qualified(self_ty, trait_ref, ns); self.printer.keep_within_component = kept_within_component; r } - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - self.printer.write_str(text)?; - Ok(PrettyPath { empty: false }) - } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, _: Self::Path, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7bc966593a281..4c4ae38f2aaa9 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4059,6 +4059,7 @@ where F: Fn(DefId) -> Def { self: &mut PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, + _ns: Namespace, ) -> Self::Path { // This shouldn't ever be needed, but just in case: if let Some(trait_ref) = trait_ref { @@ -4067,9 +4068,6 @@ where F: Fn(DefId) -> Def { vec![format!("<{}>", self_ty)] } } - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - vec![text.to_string()] - } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, mut path: Self::Path, From 29614dade5689befe8513823314c2694a1446de0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 21 Dec 2018 20:08:01 +0200 Subject: [PATCH 30/68] rustc: move the `FORCE_IMPL_FILENAME_LINE` hack into `print_def_path`. --- src/librustc/ty/print.rs | 83 ++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 1664834bd602e..102010a3c10b4 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -162,8 +162,10 @@ pub trait Printer: Sized { impl_def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, + self_ty: Ty<'tcx>, + trait_ref: Option>, ) -> Self::Path { - self.default_print_impl_path(impl_def_id, substs, ns) + self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref) } #[must_use] @@ -272,7 +274,16 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } DefPathData::Impl => { - self.print_impl_path(def_id, substs, ns) + let mut self_ty = self.tcx.type_of(def_id); + if let Some(substs) = substs { + self_ty = self_ty.subst(self.tcx, substs); + } + + let mut impl_trait_ref = self.tcx.impl_trait_ref(def_id); + if let Some(substs) = substs { + impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); + } + self.print_impl_path(def_id, substs, ns, self_ty, impl_trait_ref) } _ => { @@ -322,30 +333,24 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { fn default_print_impl_path( &mut self, impl_def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + _substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, + self_ty: Ty<'tcx>, + impl_trait_ref: Option>, ) -> P::Path { - debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); - let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); + debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", + impl_def_id, self_ty, impl_trait_ref); // Decide whether to print the parent path for the impl. // Logically, since impls are global, it's never needed, but // users may find it useful. Currently, we omit the parent if // the impl is either in the same module as the self-type or // as the trait. - let mut self_ty = self.tcx.type_of(impl_def_id); - if let Some(substs) = substs { - self_ty = self_ty.subst(self.tcx, substs); - } + let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); let in_self_mod = match characteristic_def_id_of_type(self_ty) { None => false, Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id), }; - - let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); - if let Some(substs) = substs { - impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); - } let in_trait_mod = match impl_trait_ref { None => false, Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), @@ -699,7 +704,7 @@ impl Printer for FmtPrinter { ns: Namespace, projections: impl Iterator>, ) -> Self::Path { - // FIXME(eddyb) avoid querying `tcx.generics_of` + // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. let generics = substs.map(|_| self.tcx.generics_of(def_id)); if // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` @@ -717,35 +722,31 @@ impl Printer for FmtPrinter { } } - self.default_print_def_path(def_id, substs, ns, projections) - } - fn print_impl_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, - ) -> Self::Path { - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` - FORCE_ABSOLUTE.with(|force| force.get()) || - !impl_def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; + let key = self.tcx.def_key(def_id); + if let DefPathData::Impl = key.disambiguated_data.data { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = + // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` + FORCE_ABSOLUTE.with(|force| force.get()) || + !def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; - if !use_types { - // If no type info is available, fall back to - // pretty printing some span information. This should - // only occur very early in the compiler pipeline. - let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); - let path = self.print_def_path(parent_def_id, None, ns, iter::empty()); - let span = self.tcx.def_span(impl_def_id); - return self.path_append(path, &format!("", span)); + if !use_types { + // If no type info is available, fall back to + // pretty printing some span information. This should + // only occur very early in the compiler pipeline. + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let path = self.print_def_path(parent_def_id, None, ns, iter::empty()); + let span = self.tcx.def_span(def_id); + return self.path_append(path, &format!("", span)); + } } - self.default_print_impl_path(impl_def_id, substs, ns) + self.default_print_def_path(def_id, substs, ns, projections) } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { From cb5c37d7e66d96eac9aad7184a9b05bdc589b913 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 06:09:22 +0200 Subject: [PATCH 31/68] rustc: move `...::` printing into `pretty_path_qualified`. --- src/librustc/ty/print.rs | 39 +++++++++++++------- src/librustc/util/ppaux.rs | 2 +- src/librustc_codegen_utils/symbol_names.rs | 41 ++++++++++++++++++---- src/librustdoc/clean/mod.rs | 9 +++-- 4 files changed, 68 insertions(+), 23 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 102010a3c10b4..8399be54617ee 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -173,6 +173,7 @@ pub trait Printer: Sized { #[must_use] fn path_qualified( self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_prefix: Option, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, @@ -300,7 +301,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { parent_generics.has_self && parent_generics.parent_count == 0; if let (Some(substs), true) = (substs, parent_has_own_self) { let trait_ref = ty::TraitRef::new(parent_def_id, substs); - self.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns) + self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns) } else { self.print_def_path(parent_def_id, substs, ns, iter::empty()) } @@ -356,21 +357,18 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), }; - if !in_self_mod && !in_trait_mod { + let prefix_path = if !in_self_mod && !in_trait_mod { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - let path = self.print_def_path(parent_def_id, None, ns, iter::empty()); - if let Some(trait_ref) = impl_trait_ref { - return self.path_append(path, &format!("", trait_ref, self_ty)); - } else { - return self.path_append(path, &format!("", self_ty)); - } - } + Some(self.print_def_path(parent_def_id, None, ns, iter::empty())) + } else { + // Otherwise, try to give a good form that would be valid language + // syntax. Preferably using associated item notation. + None + }; - // Otherwise, try to give a good form that would be valid language - // syntax. Preferably using associated item notation. - self.path_qualified(self_ty, impl_trait_ref, ns) + self.path_qualified(prefix_path, self_ty, impl_trait_ref, ns) } } @@ -563,10 +561,24 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { pub fn pretty_path_qualified( &mut self, + impl_prefix: Option, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, ) -> P::Path { + if let Some(prefix) = impl_prefix { + // HACK(eddyb) going through `path_append` means symbol name + // computation gets to handle its equivalent of `::` correctly. + let _ = self.path_append(prefix, "")?; + return Ok(PrettyPath { empty: false }); + } + if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is @@ -771,11 +783,12 @@ impl Printer for FmtPrinter { } fn path_qualified( self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_prefix: Option, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, ) -> Self::Path { - self.pretty_path_qualified(self_ty, trait_ref, ns) + self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index f241e6cf2a5e2..e199a1fa63781 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1000,7 +1000,7 @@ define_print! { Ok(()) } debug { - let _ = cx.path_qualified(self.self_ty(), Some(*self), Namespace::TypeNS)?; + let _ = cx.path_qualified(None, self.self_ty(), Some(*self), Namespace::TypeNS)?; Ok(()) } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 84c78f7dd96bf..884af48434c6d 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -382,7 +382,7 @@ impl SymbolPath { } fn finalize_pending_component(&mut self) { - if !self.keep_within_component && !self.temp_buf.is_empty() { + if !self.temp_buf.is_empty() { let _ = write!(self.result, "{}{}", self.temp_buf.len(), self.temp_buf); self.temp_buf.clear(); } @@ -415,6 +415,7 @@ impl Printer for SymbolPath { } fn path_qualified( self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_prefix: Option, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, @@ -424,25 +425,51 @@ impl Printer for SymbolPath { match self_ty.sty { ty::Adt(..) | ty::Foreign(_) | ty::Bool | ty::Char | ty::Str | - ty::Int(_) | ty::Uint(_) | ty::Float(_) if trait_ref.is_none() => { - return self.pretty_path_qualified(self_ty, trait_ref, ns); + ty::Int(_) | ty::Uint(_) | ty::Float(_) + if impl_prefix.is_none() && trait_ref.is_none() => + { + return self.pretty_path_qualified(None, self_ty, trait_ref, ns); } _ => {} } + // HACK(eddyb) make sure to finalize the last component of the + // `impl` prefix, to avoid it fusing with the following text. + let impl_prefix = impl_prefix.map(|prefix| { + let mut prefix = self.path_append(prefix, "")?; + + // HACK(eddyb) also avoid an unnecessary `::`. + prefix.empty = true; + + Ok(prefix) + }); + let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); - let r = self.pretty_path_qualified(self_ty, trait_ref, ns); + let r = self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns); self.printer.keep_within_component = kept_within_component; r } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, - _: Self::Path, + path: Self::Path, text: &str, ) -> Self::Path { - self.printer.finalize_pending_component(); + let mut path = path?; + + if self.keep_within_component { + // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. + if !path.empty { + self.printer.write_str("::")?; + } else { + path.empty = text.is_empty(); + } + } else { + self.printer.finalize_pending_component(); + path.empty = false; + } + self.printer.write_str(text)?; - Ok(PrettyPath { empty: false }) + Ok(path) } fn path_generic_args( self: &mut PrintCx<'_, '_, 'tcx, Self>, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4c4ae38f2aaa9..cabd83a6164f3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4057,16 +4057,21 @@ where F: Fn(DefId) -> Def { } fn path_qualified( self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_prefix: Option, self_ty: Ty<'tcx>, trait_ref: Option>, _ns: Namespace, ) -> Self::Path { + let mut path = impl_prefix.unwrap_or(vec![]); + // This shouldn't ever be needed, but just in case: if let Some(trait_ref) = trait_ref { - vec![format!("{:?}", trait_ref)] + path.push(format!("{:?}", trait_ref)); } else { - vec![format!("<{}>", self_ty)] + path.push(format!("<{}>", self_ty)); } + + path } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, From 8bf427b14d700fb2d0d69cffde3b739435f07403 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 07:00:30 +0200 Subject: [PATCH 32/68] rustc: assert `ty::print::FORCE_ABSOLUTE` isn't needed anymore. --- src/librustc/infer/error_reporting/mod.rs | 67 ++++++++++++++++++++--- src/librustc/ty/print.rs | 14 ++--- 2 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 893a9286b678e..9442069635f82 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,7 +55,7 @@ use hir; use hir::def_id::DefId; use hir::Node; use middle::region; -use std::{cmp, fmt}; +use std::{cmp, fmt, iter}; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use traits::{ObligationCause, ObligationCauseCode}; @@ -445,20 +445,69 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { terr: &TypeError<'tcx>, sp: Span, ) { + use hir::def::Namespace; + use hir::def_id::CrateNum; + use ty::print::{PrintCx, Printer}; + use ty::subst::Substs; + + struct AbsolutePathPrinter; + + struct NonTrivialPath; + + impl Printer for AbsolutePathPrinter { + type Path = Result, NonTrivialPath>; + + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) + } + fn path_qualified<'tcx>( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + _impl_prefix: Option, + _self_ty: Ty<'tcx>, + _trait_ref: Option>, + _ns: Namespace, + ) -> Self::Path { + Err(NonTrivialPath) + } + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + path: Self::Path, + text: &str, + ) -> Self::Path { + let mut path = path?; + path.push(text.to_string()); + Ok(path) + } + fn path_generic_args<'tcx>( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + path: Self::Path, + _params: &[ty::GenericParamDef], + _substs: &'tcx Substs<'tcx>, + _ns: Namespace, + _projections: impl Iterator>, + ) -> Self::Path { + path + } + } + let report_path_match = |err: &mut DiagnosticBuilder<'_>, did1: DefId, did2: DefId| { // Only external crates, if either is from a local // module we could have false positives if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { - let exp_path = self.tcx.def_path_str(did1); - let found_path = self.tcx.def_path_str(did2); - // HACK(eddyb) switch form `with_forced_absolute_paths` - // to a custom implementation of `ty::print::Printer`. - let (exp_abs_path, found_abs_path) = ty::print::with_forced_absolute_paths(|| { - (self.tcx.def_path_str(did1), self.tcx.def_path_str(did2)) - }); + let abs_path = |def_id| { + PrintCx::new(self.tcx, AbsolutePathPrinter) + .print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) + }; + // We compare strings because DefPath can be different // for imported and non-imported crates - if exp_path == found_path || exp_abs_path == found_abs_path { + let same_path = || -> Result<_, NonTrivialPath> { + Ok( + self.tcx.def_path_str(did1) == self.tcx.def_path_str(did2) || + abs_path(did1)? == abs_path(did2)? + ) + }; + if same_path().unwrap_or(false) { let crate_name = self.tcx.crate_name(did1.krate); err.span_note( sp, diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 8399be54617ee..e3f95c01f570d 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -719,9 +719,9 @@ impl Printer for FmtPrinter { // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. let generics = substs.map(|_| self.tcx.generics_of(def_id)); - if // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` - !FORCE_ABSOLUTE.with(|force| force.get()) && - generics.as_ref().and_then(|g| g.parent).is_none() { + // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` + assert!(!FORCE_ABSOLUTE.with(|force| force.get())); + if generics.as_ref().and_then(|g| g.parent).is_none() { if let Some(path) = self.try_print_visible_def_path(def_id) { let path = if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; @@ -739,8 +739,6 @@ impl Printer for FmtPrinter { // Always use types for non-local impls, where types are always // available, and filename/line-number is mostly uninteresting. let use_types = - // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` - FORCE_ABSOLUTE.with(|force| force.get()) || !def_id.is_local() || { // Otherwise, use filename/line-number if forced. let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); @@ -763,10 +761,8 @@ impl Printer for FmtPrinter { fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` - if FORCE_ABSOLUTE.with(|force| force.get()) { - write!(self.printer, "{}", self.tcx.original_crate_name(cnum))?; - return Ok(PrettyPath { empty: false }); - } + assert!(!FORCE_ABSOLUTE.with(|force| force.get())); + if cnum == LOCAL_CRATE { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. From 534afff4dd78ff92c64e9d9c0f4b963ebe41f5f5 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 07:27:44 +0200 Subject: [PATCH 33/68] rustc: remove `ty::print::FORCE_ABSOLUTE` altogether. --- src/librustc/ty/print.rs | 39 +--------------------- src/librustc_codegen_utils/symbol_names.rs | 8 ++--- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index e3f95c01f570d..a003f8616760d 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -16,25 +16,10 @@ use std::iter; use std::ops::Deref; thread_local! { - static FORCE_ABSOLUTE: Cell = Cell::new(false); static FORCE_IMPL_FILENAME_LINE: Cell = Cell::new(false); static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); } -/// Enforces that def_path_str always returns an absolute path and -/// also enables "type-based" impl paths. This is used when building -/// symbols that contain types, where we want the crate name to be -/// part of the symbol. -pub fn with_forced_absolute_paths R, R>(f: F) -> R { - FORCE_ABSOLUTE.with(|force| { - let old = force.get(); - force.set(true); - let result = f(); - force.set(old); - result - }) -} - /// Force us to name impls with just the filename/line number. We /// normally try to use types. But at some points, notably while printing /// cycle errors, this can result in extra or suboptimal error output, @@ -222,24 +207,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Returns a string identifying this def-id. This string is - /// suitable for user output. It is relative to the current crate - /// root, unless with_forced_absolute_paths was used. - pub fn def_path_str_with_substs_and_ns( - self, - def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, - ) -> String { - debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); - let mut s = String::new(); - let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s }) - .print_def_path(def_id, substs, ns, iter::empty()); - s - } - - /// Returns a string identifying this def-id. This string is - /// suitable for user output. It is relative to the current crate - /// root, unless with_forced_absolute_paths was used. + /// suitable for user output. pub fn def_path_str(self, def_id: DefId) -> String { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); @@ -719,8 +687,6 @@ impl Printer for FmtPrinter { // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. let generics = substs.map(|_| self.tcx.generics_of(def_id)); - // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` - assert!(!FORCE_ABSOLUTE.with(|force| force.get())); if generics.as_ref().and_then(|g| g.parent).is_none() { if let Some(path) = self.try_print_visible_def_path(def_id) { let path = if let (Some(generics), Some(substs)) = (generics, substs) { @@ -760,9 +726,6 @@ impl Printer for FmtPrinter { } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { - // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` - assert!(!FORCE_ABSOLUTE.with(|force| force.get())); - if cnum == LOCAL_CRATE { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 884af48434c6d..ba57c00035b3f 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -223,11 +223,9 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - ty::print::with_forced_absolute_paths(|| { - let mut cx = PrintCx::new(tcx, SymbolPath::new()); - let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); - cx.printer.into_interned() - }) + let mut cx = PrintCx::new(tcx, SymbolPath::new()); + let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); + cx.printer.into_interned() } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { From a70ca27d6b91d55c2da22a3b36d45308fddc72c7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 10:08:30 +0200 Subject: [PATCH 34/68] rustc: replace node_path_str with uses of def_path_str. --- src/librustc/hir/map/mod.rs | 3 ++- src/librustc/ty/print.rs | 6 ------ src/librustc_driver/pretty.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 21 ++++++++++++++------- src/librustc_save_analysis/lib.rs | 22 +++++++++++++++------- 5 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index c3e4f0c05014c..b343cd6c41081 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1189,7 +1189,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { // the user-friendly path, otherwise fall back to stringifying DefPath. ::ty::tls::with_opt(|tcx| { if let Some(tcx) = tcx { - tcx.node_path_str(id) + let def_id = map.local_def_id(id); + tcx.def_path_str(def_id) } else if let Some(path) = map.def_path_from_id(id) { path.data.into_iter().map(|elem| { elem.data.to_string() diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index a003f8616760d..13b17c9a23829 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -216,12 +216,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .print_def_path(def_id, None, ns, iter::empty()); s } - - /// Returns a string identifying this local node-id. - // FIXME(eddyb) remove in favor of calling `def_path_str` directly. - pub fn node_path_str(self, id: ast::NodeId) -> String { - self.def_path_str(self.hir().local_def_id(id)) - } } impl PrintCx<'a, 'gcx, 'tcx, P> { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d980c5a3d29c3..b7a0b4c5d5643 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -489,7 +489,7 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { } fn node_path(&self, id: ast::NodeId) -> Option { - Some(self.tcx.node_path_str(id)) + Some(self.tcx.def_path_str(self.tcx.hir().local_def_id(id))) } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 0f4fbb37541df..cd727583217db 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -423,7 +423,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { vis: ast::Visibility, attrs: &'l [Attribute], ) { - let qualname = format!("::{}", self.tcx.node_path_str(id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(id))); if !self.span.filter_generated(ident.span) { let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt); @@ -464,7 +465,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ) { debug!("process_struct {:?} {:?}", item, item.span); let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); let kind = match item.node { ast::ItemKind::Struct(_, _) => DefKind::Struct, @@ -676,7 +678,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { methods: &'l [ast::TraitItem], ) { let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); let mut val = name.clone(); if !generics.params.is_empty() { val.push_str(&generic_params_to_string(&generics.params)); @@ -1087,7 +1090,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { ast::TraitItemKind::Type(ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); - let qualname = format!("::{}", self.tcx.node_path_str(trait_item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(trait_item.id))); if !self.span.filter_generated(trait_item.ident.span) { let span = self.span_from_span(trait_item.ident.span); @@ -1294,7 +1298,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc // only get called for the root module of a crate. assert_eq!(id, ast::CRATE_NODE_ID); - let qualname = format!("::{}", self.tcx.node_path_str(id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(id))); let cm = self.tcx.sess.source_map(); let filename = cm.span_to_filename(span); @@ -1383,7 +1388,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc self.nest_scope(item.id, |v| visit::walk_mod(v, m)); } Ty(ref ty, ref ty_params) => { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); let value = ty_to_string(&ty); if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); @@ -1412,7 +1418,8 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc self.process_generic_params(ty_params, &qualname, item.id); } Existential(ref _bounds, ref ty_params) => { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); // FIXME do something with _bounds let value = String::new(); if !self.span.filter_generated(item.ident.span) { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index a14454c2fa639..4bc268cec1d64 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -149,7 +149,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } pub fn get_extern_item_data(&self, item: &ast::ForeignItem) -> Option { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); match item.node { ast::ForeignItemKind::Fn(ref decl, ref generics) => { filter!(self.span_utils, item.ident.span); @@ -199,7 +200,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_item_data(&self, item: &ast::Item) -> Option { match item.node { ast::ItemKind::Fn(ref decl, .., ref generics, _) => { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { kind: DefKind::Function, @@ -217,7 +219,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { })) } ast::ItemKind::Static(ref typ, ..) => { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); filter!(self.span_utils, item.ident.span); @@ -240,7 +243,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { })) } ast::ItemKind::Const(ref typ, _) => { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); @@ -262,7 +266,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { })) } ast::ItemKind::Mod(ref m) => { - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); let cm = self.tcx.sess.source_map(); let filename = cm.span_to_filename(m.inner); @@ -289,7 +294,8 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ast::ItemKind::Enum(ref def, _) => { let name = item.ident.to_string(); - let qualname = format!("::{}", self.tcx.node_path_str(item.id)); + let qualname = format!("::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(item.id))); filter!(self.span_utils, item.ident.span); let variants_str = def.variants .iter() @@ -373,7 +379,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { pub fn get_field_data(&self, field: &ast::StructField, scope: NodeId) -> Option { if let Some(ident) = field.ident { let name = ident.to_string(); - let qualname = format!("::{}::{}", self.tcx.node_path_str(scope), ident); + let qualname = format!("::{}::{}", + self.tcx.def_path_str(self.tcx.hir().local_def_id(scope)), + ident); filter!(self.span_utils, ident.span); let def_id = self.tcx.hir().local_def_id(field.id); let typ = self.tcx.type_of(def_id).to_string(); From 8276e14037649b24fa7b88741995d2fb8f5572ff Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jan 2019 12:13:39 +0200 Subject: [PATCH 35/68] rustc: make ppaux' print macro use only one closure. --- src/librustc/util/ppaux.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index e199a1fa63781..e3734fe3dca97 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -252,8 +252,11 @@ macro_rules! print_inner { }; } macro_rules! print { - ( $cx:expr $(, $kind:ident $data:tt)+ ) => { - Ok(())$(.and_then(|_| print_inner!($cx, $kind $data)))+ + ( $cx:expr, $($kind:ident $data:tt),+ ) => { + (|| -> fmt::Result { + $(print_inner!($cx, $kind $data)?;)+ + Ok(()) + })() }; } From e3bce90a3afc21c830de0594225c1e6959ad60b3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jan 2019 13:05:05 +0200 Subject: [PATCH 36/68] rustc: rename ppaux' print macro to just p and make its cx input implicit. --- src/librustc/util/ppaux.rs | 340 ++++++++++++++++++++----------------- 1 file changed, 180 insertions(+), 160 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index e3734fe3dca97..baa3c2bc4f887 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -195,6 +195,7 @@ macro_rules! gen_print_impl { impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target { type Output = fmt::Result; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { + define_scoped_cx!($cx); if $cx.is_debug $dbg else $disp } @@ -204,6 +205,7 @@ macro_rules! gen_print_impl { impl Print<'tcx, P> for $target { type Output = fmt::Result; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { + define_scoped_cx!($cx); if $cx.is_debug $dbg else $disp } @@ -244,21 +246,29 @@ macro_rules! define_print_multi { }; } macro_rules! print_inner { - ( $cx:expr, write ($($data:expr),+) ) => { - write!($cx.printer, $($data),+) + (write ($($data:expr),+)) => { + write!(scoped_cx!().printer, $($data),+) }; - ( $cx:expr, $kind:ident ($data:expr) ) => { - $data.$kind($cx) + ($kind:ident ($data:expr)) => { + $data.$kind(scoped_cx!()) }; } -macro_rules! print { - ( $cx:expr, $($kind:ident $data:tt),+ ) => { +macro_rules! p { + ($($kind:ident $data:tt),+) => { (|| -> fmt::Result { - $(print_inner!($cx, $kind $data)?;)+ + $(print_inner!($kind $data)?;)+ Ok(()) })() }; } +macro_rules! define_scoped_cx { + ($cx:ident) => { + #[allow(unused_macros)] + macro_rules! scoped_cx { + () => ($cx) + } + }; +} impl PrintCx<'a, 'gcx, 'tcx, P> { fn fn_sig( @@ -267,20 +277,22 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { variadic: bool, output: Ty<'tcx>, ) -> fmt::Result { - print!(self, write("("))?; + define_scoped_cx!(self); + + p!(write("("))?; let mut inputs = inputs.iter(); if let Some(&ty) = inputs.next() { - print!(self, print_display(ty))?; + p!(print_display(ty))?; for &ty in inputs { - print!(self, write(", "), print_display(ty))?; + p!(write(", "), print_display(ty))?; } if variadic { - print!(self, write(", ..."))?; + p!(write(", ..."))?; } } - print!(self, write(")"))?; + p!(write(")"))?; if !output.is_unit() { - print!(self, write(" -> "), print_display(output))?; + p!(write(" -> "), print_display(output))?; } Ok(()) @@ -308,21 +320,28 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { + define_scoped_cx!(cx); + if empty { empty = false; - print!(cx, write("{}", start)) + p!(write("{}", start)) } else { - print!(cx, write("{}", cont)) + p!(write("{}", cont)) } }; + // NOTE(eddyb) this must be below `start_or_continue`'s definition + // as that also has a `define_scoped_cx` and that kind of shadowing + // is disallowed (name resolution thinks `scoped_cx!` is ambiguous). + define_scoped_cx!(self); + let old_region_index = self.region_index; let mut region_index = old_region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { let _ = start_or_continue(self, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { - let _ = print!(self, write("{}", name)); + let _ = p!(write("{}", name)); br } ty::BrAnon(_) | @@ -335,7 +354,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { break name; } }; - let _ = print!(self, write("{}", name)); + let _ = p!(write("{}", name)); ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name) } }; @@ -431,7 +450,7 @@ define_print! { for (_, def_id) in auto_traits { if !first { - print!(cx, write(" + "))?; + p!(write(" + "))?; } first = false; @@ -501,7 +520,8 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { - print!(cx, write("UpvarId({:?};`{}`;{:?})", + define_scoped_cx!(cx); + p!(write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)), self.closure_expr_id)) @@ -519,15 +539,15 @@ impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { define_print! { ('tcx) &'tcx ty::List>, (self, cx) { display { - print!(cx, write("{{"))?; + p!(write("{{"))?; let mut tys = self.iter(); if let Some(&ty) = tys.next() { - print!(cx, print(ty))?; + p!(print(ty))?; for &ty in tys { - print!(cx, write(", "), print(ty))?; + p!(write(", "), print(ty))?; } } - print!(cx, write("}}")) + p!(write("}}")) } } } @@ -535,7 +555,7 @@ define_print! { define_print! { ('tcx) ty::TypeAndMut<'tcx>, (self, cx) { display { - print!(cx, + p!( write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), print(self.ty)) } @@ -561,7 +581,7 @@ define_print! { define_print! { ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) { debug { - print!(cx, write("{:?} -> ", self.kind), print(self.target)) + p!(write("{:?} -> ", self.kind), print(self.target)) } } } @@ -575,14 +595,14 @@ define_print! { if let BrNamed(_, name) = *self { if name != "" && name != "'_" { - return print!(cx, write("{}", name)); + return p!(write("{}", name)); } } let highlight = RegionHighlightMode::get(); if let Some((region, counter)) = highlight.highlight_bound_region { if *self == region { - return print!(cx, write("'{}", counter)); + return p!(write("'{}", counter)); } } @@ -590,13 +610,13 @@ define_print! { } debug { return match *self { - BrAnon(n) => print!(cx, write("BrAnon({:?})", n)), - BrFresh(n) => print!(cx, write("BrFresh({:?})", n)), + BrAnon(n) => p!(write("BrAnon({:?})", n)), + BrFresh(n) => p!(write("BrFresh({:?})", n)), BrNamed(did, name) => { - print!(cx, write("BrNamed({:?}:{:?}, {})", + p!(write("BrNamed({:?}:{:?}, {})", did.krate, did.index, name)) } - BrEnv => print!(cx, write("BrEnv")), + BrEnv => p!(write("BrEnv")), }; } } @@ -637,10 +657,10 @@ define_print! { let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.placeholder_highlight(*self) { - return print!(cx, write("'{}", counter)); + return p!(write("'{}", counter)); } - print!(cx, print_display(self.name)) + p!(print_display(self.name)) } } } @@ -672,7 +692,7 @@ define_print! { // Watch out for region highlights. if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { - return print!(cx, write("'{:?}", n)); + return p!(write("'{:?}", n)); } // These printouts are concise. They do not contain all the information @@ -682,29 +702,29 @@ define_print! { match *self { ty::ReEarlyBound(ref data) => { if data.name != "'_" { - print!(cx, write("{}", data.name)) + p!(write("{}", data.name)) } else { Ok(()) } } ty::ReLateBound(_, br) | ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { - print!(cx, print_display(br)) + p!(print_display(br)) } ty::RePlaceholder(p) => { - print!(cx, print_display(p)) + p!(print_display(p)) } ty::ReScope(scope) if cx.identify_regions => { match scope.data { region::ScopeData::Node => - print!(cx, write("'{}s", scope.item_local_id().as_usize())), + p!(write("'{}s", scope.item_local_id().as_usize())), region::ScopeData::CallSite => - print!(cx, write("'{}cs", scope.item_local_id().as_usize())), + p!(write("'{}cs", scope.item_local_id().as_usize())), region::ScopeData::Arguments => - print!(cx, write("'{}as", scope.item_local_id().as_usize())), + p!(write("'{}as", scope.item_local_id().as_usize())), region::ScopeData::Destruction => - print!(cx, write("'{}ds", scope.item_local_id().as_usize())), - region::ScopeData::Remainder(first_statement_index) => print!(cx, write( + p!(write("'{}ds", scope.item_local_id().as_usize())), + region::ScopeData::Remainder(first_statement_index) => p!(write( "'{}_{}rs", scope.item_local_id().as_usize(), first_statement_index.index() @@ -712,58 +732,58 @@ define_print! { } } ty::ReVar(region_vid) if cx.identify_regions => { - print!(cx, print_debug(region_vid)) + p!(print_debug(region_vid)) } ty::ReVar(region_vid) => { - print!(cx, print_display(region_vid)) + p!(print_display(region_vid)) } ty::ReScope(_) | ty::ReErased => Ok(()), - ty::ReStatic => print!(cx, write("'static")), - ty::ReEmpty => print!(cx, write("'")), + ty::ReStatic => p!(write("'static")), + ty::ReEmpty => p!(write("'")), // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => print!(cx, write("{:?}", vid)), + ty::ReClosureBound(vid) => p!(write("{:?}", vid)), } } debug { match *self { ty::ReEarlyBound(ref data) => { - print!(cx, write("ReEarlyBound({}, {})", + p!(write("ReEarlyBound({}, {})", data.index, data.name)) } ty::ReClosureBound(ref vid) => { - print!(cx, write("ReClosureBound({:?})", + p!(write("ReClosureBound({:?})", vid)) } ty::ReLateBound(binder_id, ref bound_region) => { - print!(cx, write("ReLateBound({:?}, {:?})", + p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region)) } - ty::ReFree(ref fr) => print!(cx, write("{:?}", fr)), + ty::ReFree(ref fr) => p!(write("{:?}", fr)), ty::ReScope(id) => { - print!(cx, write("ReScope({:?})", id)) + p!(write("ReScope({:?})", id)) } - ty::ReStatic => print!(cx, write("ReStatic")), + ty::ReStatic => p!(write("ReStatic")), ty::ReVar(ref vid) => { - print!(cx, write("{:?}", vid)) + p!(write("{:?}", vid)) } ty::RePlaceholder(placeholder) => { - print!(cx, write("RePlaceholder({:?})", placeholder)) + p!(write("RePlaceholder({:?})", placeholder)) } - ty::ReEmpty => print!(cx, write("ReEmpty")), + ty::ReEmpty => p!(write("ReEmpty")), - ty::ReErased => print!(cx, write("ReErased")) + ty::ReErased => p!(write("ReErased")) } } } @@ -816,7 +836,7 @@ impl ty::RegionKind { define_print! { () ty::FreeRegion, (self, cx) { debug { - print!(cx, write("ReFree({:?}, {:?})", self.scope, self.bound_region)) + p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region)) } } } @@ -838,18 +858,18 @@ define_print! { ('tcx) ty::FnSig<'tcx>, (self, cx) { display { if self.unsafety == hir::Unsafety::Unsafe { - print!(cx, write("unsafe "))?; + p!(write("unsafe "))?; } if self.abi != Abi::Rust { - print!(cx, write("extern {} ", self.abi))?; + p!(write("extern {} ", self.abi))?; } - print!(cx, write("fn"))?; + p!(write("fn"))?; cx.fn_sig(self.inputs(), self.variadic, self.output()) } debug { - print!(cx, write("({:?}; variadic: {})->{:?}", + p!(write("({:?}; variadic: {})->{:?}", self.inputs(), self.variadic, self.output())) } } @@ -882,7 +902,7 @@ define_print! { let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - return print!(cx, write("'{:?}", counter)); + return p!(write("'{:?}", counter)); } Ok(()) @@ -892,10 +912,10 @@ define_print! { // to keep NLL borrowck working even with `-Zverbose`. let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - return print!(cx, write("'{:?}", counter)); + return p!(write("'{:?}", counter)); } - print!(cx, write("'_#{}r", self.index())) + p!(write("'_#{}r", self.index())) } } } @@ -925,22 +945,22 @@ define_print! { return self.print_debug(cx); } match *self { - ty::TyVar(_) => print!(cx, write("_")), - ty::IntVar(_) => print!(cx, write("{}", "{integer}")), - ty::FloatVar(_) => print!(cx, write("{}", "{float}")), - ty::FreshTy(v) => print!(cx, write("FreshTy({})", v)), - ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({})", v)), - ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({})", v)) + ty::TyVar(_) => p!(write("_")), + ty::IntVar(_) => p!(write("{}", "{integer}")), + ty::FloatVar(_) => p!(write("{}", "{float}")), + ty::FreshTy(v) => p!(write("FreshTy({})", v)), + ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)), + ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) } } debug { match *self { - ty::TyVar(ref v) => print!(cx, write("{:?}", v)), - ty::IntVar(ref v) => print!(cx, write("{:?}", v)), - ty::FloatVar(ref v) => print!(cx, write("{:?}", v)), - ty::FreshTy(v) => print!(cx, write("FreshTy({:?})", v)), - ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({:?})", v)), - ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({:?})", v)) + ty::TyVar(ref v) => p!(write("{:?}", v)), + ty::IntVar(ref v) => p!(write("{:?}", v)), + ty::FloatVar(ref v) => p!(write("{:?}", v)), + ty::FreshTy(v) => p!(write("FreshTy({:?})", v)), + ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)), + ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v)) } } } @@ -1013,68 +1033,68 @@ define_print! { ('tcx) ty::Ty<'tcx>, (self, cx) { display { match self.sty { - Bool => print!(cx, write("bool")), - Char => print!(cx, write("char")), - Int(t) => print!(cx, write("{}", t.ty_to_string())), - Uint(t) => print!(cx, write("{}", t.ty_to_string())), - Float(t) => print!(cx, write("{}", t.ty_to_string())), + Bool => p!(write("bool")), + Char => p!(write("char")), + Int(t) => p!(write("{}", t.ty_to_string())), + Uint(t) => p!(write("{}", t.ty_to_string())), + Float(t) => p!(write("{}", t.ty_to_string())), RawPtr(ref tm) => { - print!(cx, write("*{} ", match tm.mutbl { + p!(write("*{} ", match tm.mutbl { hir::MutMutable => "mut", hir::MutImmutable => "const", }))?; tm.ty.print(cx) } Ref(r, ty, mutbl) => { - print!(cx, write("&"))?; + p!(write("&"))?; if r.display_outputs_anything(cx) { - print!(cx, print_display(r), write(" "))?; + p!(print_display(r), write(" "))?; } ty::TypeAndMut { ty, mutbl }.print(cx) } - Never => print!(cx, write("!")), + Never => p!(write("!")), Tuple(ref tys) => { - print!(cx, write("("))?; + p!(write("("))?; let mut tys = tys.iter(); if let Some(&ty) = tys.next() { - print!(cx, print(ty), write(","))?; + p!(print(ty), write(","))?; if let Some(&ty) = tys.next() { - print!(cx, write(" "), print(ty))?; + p!(write(" "), print(ty))?; for &ty in tys { - print!(cx, write(", "), print(ty))?; + p!(write(", "), print(ty))?; } } } - print!(cx, write(")")) + p!(write(")")) } FnDef(def_id, substs) => { let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); - print!(cx, print(sig), write(" {{"))?; + p!(print(sig), write(" {{"))?; let _ = cx.print_def_path( def_id, Some(substs), Namespace::ValueNS, iter::empty(), )?; - print!(cx, write("}}")) + p!(write("}}")) } FnPtr(ref bare_fn) => { bare_fn.print(cx) } - Infer(infer_ty) => print!(cx, write("{}", infer_ty)), - Error => print!(cx, write("[type error]")), - Param(ref param_ty) => print!(cx, write("{}", param_ty)), + Infer(infer_ty) => p!(write("{}", infer_ty)), + Error => p!(write("[type error]")), + Param(ref param_ty) => p!(write("{}", param_ty)), Bound(debruijn, bound_ty) => { match bound_ty.kind { ty::BoundTyKind::Anon => { if debruijn == ty::INNERMOST { - print!(cx, write("^{}", bound_ty.var.index())) + p!(write("^{}", bound_ty.var.index())) } else { - print!(cx, write("^{}_{}", debruijn.index(), bound_ty.var.index())) + p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) } } - ty::BoundTyKind::Param(p) => print!(cx, write("{}", p)), + ty::BoundTyKind::Param(p) => p!(write("{}", p)), } } Adt(def, substs) => { @@ -1089,12 +1109,12 @@ define_print! { Dynamic(data, r) => { let print_r = r.display_outputs_anything(cx); if print_r { - print!(cx, write("("))?; + p!(write("("))?; } - print!(cx, write("dyn "))?; + p!(write("dyn "))?; data.print(cx)?; if print_r { - print!(cx, write(" + "), print_display(r), write(")"))?; + p!(write(" + "), print_display(r), write(")"))?; } Ok(()) } @@ -1109,30 +1129,30 @@ define_print! { } Projection(ref data) => data.print(cx), UnnormalizedProjection(ref data) => { - print!(cx, write("Unnormalized("))?; + p!(write("Unnormalized("))?; data.print(cx)?; - print!(cx, write(")")) + p!(write(")")) } Placeholder(placeholder) => { - print!(cx, write("Placeholder({:?})", placeholder)) + p!(write("Placeholder({:?})", placeholder)) } Opaque(def_id, substs) => { if cx.is_verbose { - return print!(cx, write("Opaque({:?}, {:?})", def_id, substs)); + return p!(write("Opaque({:?}, {:?})", def_id, substs)); } let def_key = cx.tcx.def_key(def_id); if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - print!(cx, write("{}", name))?; + p!(write("{}", name))?; let mut substs = substs.iter(); // FIXME(eddyb) print this with `print_def_path`. if let Some(first) = substs.next() { - print!(cx, write("::<"))?; - print!(cx, write("{}", first))?; + p!(write("::<"))?; + p!(write("{}", first))?; for subst in substs { - print!(cx, write(", {}", subst))?; + p!(write(", {}", subst))?; } - print!(cx, write(">"))?; + p!(write(">"))?; } return Ok(()); } @@ -1142,7 +1162,7 @@ define_print! { let mut first = true; let mut is_sized = false; - print!(cx, write("impl"))?; + p!(write("impl"))?; for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. @@ -1151,36 +1171,36 @@ define_print! { continue; } - print!(cx, + p!( write("{}", if first { " " } else { "+" }), print(trait_ref))?; first = false; } } if !is_sized { - print!(cx, write("{}?Sized", if first { " " } else { "+" }))?; + p!(write("{}?Sized", if first { " " } else { "+" }))?; } else if first { - print!(cx, write(" Sized"))?; + p!(write(" Sized"))?; } Ok(()) } - Str => print!(cx, write("str")), + Str => p!(write("str")), Generator(did, substs, movability) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); let witness = substs.witness(did, cx.tcx); if movability == hir::GeneratorMovability::Movable { - print!(cx, write("[generator"))?; + p!(write("[generator"))?; } else { - print!(cx, write("[static generator"))?; + p!(write("[static generator"))?; } // FIXME(eddyb) should use `def_span`. if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { - print!(cx, write("@{:?}", cx.tcx.hir().span(node_id)))?; + p!(write("@{:?}", cx.tcx.hir().span(node_id)))?; let mut sep = " "; cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - print!(cx, + p!( write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), @@ -1192,36 +1212,36 @@ define_print! { } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. - print!(cx, write("@{:?}", did))?; + p!(write("@{:?}", did))?; let mut sep = " "; for (index, upvar_ty) in upvar_tys.enumerate() { - print!(cx, + p!( write("{}{}:", sep, index), print(upvar_ty))?; sep = ", "; } } - print!(cx, write(" "), print(witness), write("]")) + p!(write(" "), print(witness), write("]")) }, GeneratorWitness(types) => { cx.in_binder(&types) } Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); - print!(cx, write("[closure"))?; + p!(write("[closure"))?; // FIXME(eddyb) should use `def_span`. if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { if cx.tcx.sess.opts.debugging_opts.span_free_formats { - print!(cx, write("@{:?}", node_id))?; + p!(write("@{:?}", node_id))?; } else { - print!(cx, write("@{:?}", cx.tcx.hir().span(node_id)))?; + p!(write("@{:?}", cx.tcx.hir().span(node_id)))?; } let mut sep = " "; cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - print!(cx, + p!( write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), @@ -1233,32 +1253,32 @@ define_print! { } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. - print!(cx, write("@{:?}", did))?; + p!(write("@{:?}", did))?; let mut sep = " "; for (index, upvar_ty) in upvar_tys.enumerate() { - print!(cx, + p!( write("{}{}:", sep, index), print(upvar_ty))?; sep = ", "; } } - print!(cx, write("]")) + p!(write("]")) }, Array(ty, sz) => { - print!(cx, write("["), print(ty), write("; "))?; + p!(write("["), print(ty), write("; "))?; match sz { ty::LazyConst::Unevaluated(_def_id, _substs) => { - print!(cx, write("_"))?; + p!(write("_"))?; } ty::LazyConst::Evaluated(c) => { - print!(cx, write("{}", c.unwrap_usize(cx.tcx)))?; + p!(write("{}", c.unwrap_usize(cx.tcx)))?; } } - print!(cx, write("]")) + p!(write("]")) } Slice(ty) => { - print!(cx, write("["), print(ty), write("]")) + p!(write("["), print(ty), write("]")) } } } @@ -1271,10 +1291,10 @@ define_print! { define_print! { () ty::ParamTy, (self, cx) { display { - print!(cx, write("{}", self.name)) + p!(write("{}", self.name)) } debug { - print!(cx, write("{}/#{}", self.name, self.idx)) + p!(write("{}/#{}", self.name, self.idx)) } } } @@ -1287,7 +1307,7 @@ define_print_multi! { ] (self, cx) { display { - print!(cx, print(self.0), write(" : "), print(self.1)) + p!(print(self.0), write(" : "), print(self.1)) } } } @@ -1295,7 +1315,7 @@ define_print_multi! { define_print! { ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) { display { - print!(cx, print(self.a), write(" <: "), print(self.b)) + p!(print(self.a), write(" <: "), print(self.b)) } } } @@ -1303,11 +1323,11 @@ define_print! { define_print! { ('tcx) ty::TraitPredicate<'tcx>, (self, cx) { debug { - print!(cx, write("TraitPredicate({:?})", + p!(write("TraitPredicate({:?})", self.trait_ref)) } display { - print!(cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) } } } @@ -1315,7 +1335,7 @@ define_print! { define_print! { ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) { debug { - print!(cx, + p!( write("ProjectionPredicate("), print(self.projection_ty), write(", "), @@ -1323,7 +1343,7 @@ define_print! { write(")")) } display { - print!(cx, print(self.projection_ty), write(" == "), print(self.ty)) + p!(print(self.projection_ty), write(" == "), print(self.ty)) } } } @@ -1346,9 +1366,9 @@ define_print! { () ty::ClosureKind, (self, cx) { display { match *self { - ty::ClosureKind::Fn => print!(cx, write("Fn")), - ty::ClosureKind::FnMut => print!(cx, write("FnMut")), - ty::ClosureKind::FnOnce => print!(cx, write("FnOnce")), + ty::ClosureKind::Fn => p!(write("Fn")), + ty::ClosureKind::FnMut => p!(write("FnMut")), + ty::ClosureKind::FnOnce => p!(write("FnOnce")), } } } @@ -1363,36 +1383,36 @@ define_print! { ty::Predicate::RegionOutlives(ref predicate) => predicate.print(cx), ty::Predicate::TypeOutlives(ref predicate) => predicate.print(cx), ty::Predicate::Projection(ref predicate) => predicate.print(cx), - ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")), + ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { - print!(cx, write("the trait `"))?; + p!(write("the trait `"))?; let _ = cx.print_def_path( trait_def_id, None, Namespace::TypeNS, iter::empty(), )?; - print!(cx, write("` is object-safe")) + p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - print!(cx, write("the closure `"))?; + p!(write("the closure `"))?; let _ = cx.print_def_path( closure_def_id, None, Namespace::ValueNS, iter::empty(), )?; - print!(cx, write("` implements the trait `{}`", kind)) + p!(write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { - print!(cx, write("the constant `"))?; + p!(write("the constant `"))?; let _ = cx.print_def_path( def_id, Some(substs), Namespace::ValueNS, iter::empty(), )?; - print!(cx, write("` can be evaluated")) + p!(write("` can be evaluated")) } } } @@ -1405,14 +1425,14 @@ define_print! { ty::Predicate::Projection(ref pair) => pair.print(cx), ty::Predicate::WellFormed(ty) => ty.print(cx), ty::Predicate::ObjectSafe(trait_def_id) => { - print!(cx, write("ObjectSafe({:?})", trait_def_id)) + p!(write("ObjectSafe({:?})", trait_def_id)) } ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - print!(cx, write("ClosureKind({:?}, {:?}, {:?})", + p!(write("ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { - print!(cx, write("ConstEvaluatable({:?}, {:?})", def_id, substs)) + p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs)) } } } @@ -1423,14 +1443,14 @@ define_print! { ('tcx) Kind<'tcx>, (self, cx) { display { match self.unpack() { - UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), - UnpackedKind::Type(ty) => print!(cx, print(ty)), + UnpackedKind::Lifetime(lt) => p!(print(lt)), + UnpackedKind::Type(ty) => p!(print(ty)), } } debug { match self.unpack() { - UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), - UnpackedKind::Type(ty) => print!(cx, print(ty)), + UnpackedKind::Lifetime(lt) => p!(print(lt)), + UnpackedKind::Type(ty) => p!(print(ty)), } } } From 6930d3e9ba099b05fc9d4894b4f7a7fb6c275d93 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jan 2019 16:30:10 +0200 Subject: [PATCH 37/68] rustc: uniformize ty::print's error handling by requiring Result. --- src/librustc/infer/error_reporting/mod.rs | 20 ++-- src/librustc/ty/print.rs | 110 +++++++++++---------- src/librustc/util/ppaux.rs | 10 +- src/librustc_codegen_utils/symbol_names.rs | 34 ++++--- src/librustdoc/clean/mod.rs | 24 +++-- src/librustdoc/lib.rs | 1 + 6 files changed, 114 insertions(+), 85 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 9442069635f82..c10d991acd2a3 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -455,9 +455,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { struct NonTrivialPath; impl Printer for AbsolutePathPrinter { - type Path = Result, NonTrivialPath>; + type Error = NonTrivialPath; - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + type Path = Vec; + + fn path_crate( + self: &mut PrintCx<'_, '_, '_, Self>, + cnum: CrateNum, + ) -> Result { Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) } fn path_qualified<'tcx>( @@ -466,15 +471,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _self_ty: Ty<'tcx>, _trait_ref: Option>, _ns: Namespace, - ) -> Self::Path { + ) -> Result { Err(NonTrivialPath) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, - path: Self::Path, + mut path: Self::Path, text: &str, - ) -> Self::Path { - let mut path = path?; + ) -> Result { path.push(text.to_string()); Ok(path) } @@ -485,8 +489,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _substs: &'tcx Substs<'tcx>, _ns: Namespace, _projections: impl Iterator>, - ) -> Self::Path { - path + ) -> Result { + Ok(path) } } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 13b17c9a23829..99b430eba681a 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -110,16 +110,20 @@ impl

PrintCx<'a, 'gcx, 'tcx, P> { pub trait Print<'tcx, P> { type Output; + type Error; - fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output; - fn print_display(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output { + fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result; + fn print_display( + &self, + cx: &mut PrintCx<'_, '_, 'tcx, P>, + ) -> Result { let old_debug = cx.is_debug; cx.is_debug = false; let result = self.print(cx); cx.is_debug = old_debug; result } - fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output { + fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result { let old_debug = cx.is_debug; cx.is_debug = true; let result = self.print(cx); @@ -129,19 +133,19 @@ pub trait Print<'tcx, P> { } pub trait Printer: Sized { + type Error; + type Path; - #[must_use] fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, projections: impl Iterator>, - ) -> Self::Path { + ) -> Result { self.default_print_def_path(def_id, substs, ns, projections) } - #[must_use] fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, @@ -149,27 +153,26 @@ pub trait Printer: Sized { ns: Namespace, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Self::Path { + ) -> Result { self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref) } - #[must_use] - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; - #[must_use] + fn path_crate( + self: &mut PrintCx<'_, '_, '_, Self>, + cnum: CrateNum, + ) -> Result; fn path_qualified( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_prefix: Option, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, - ) -> Self::Path; - #[must_use] + ) -> Result; fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, path: Self::Path, text: &str, - ) -> Self::Path; - #[must_use] + ) -> Result; fn path_generic_args( self: &mut PrintCx<'_, '_, 'tcx, Self>, path: Self::Path, @@ -177,7 +180,7 @@ pub trait Printer: Sized { substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, - ) -> Self::Path; + ) -> Result; } #[must_use] @@ -186,7 +189,7 @@ pub struct PrettyPath { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter: Printer> + fmt::Write {} +pub trait PrettyPrinter: Printer + fmt::Write {} impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always @@ -225,7 +228,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, projections: impl Iterator>, - ) -> P::Path { + ) -> Result { debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); let key = self.tcx.def_key(def_id); debug!("default_print_def_path: key={:?}", key); @@ -263,12 +266,12 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { parent_generics.has_self && parent_generics.parent_count == 0; if let (Some(substs), true) = (substs, parent_has_own_self) { let trait_ref = ty::TraitRef::new(parent_def_id, substs); - self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns) + self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns)? } else { - self.print_def_path(parent_def_id, substs, ns, iter::empty()) + self.print_def_path(parent_def_id, substs, ns, iter::empty())? } } else { - self.print_def_path(parent_def_id, None, ns, iter::empty()) + self.print_def_path(parent_def_id, None, ns, iter::empty())? }; let path = match key.disambiguated_data.data { // Skip `::{{constructor}}` on tuple/unit structs. @@ -278,7 +281,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self.path_append( path, &key.disambiguated_data.data.as_interned_str().as_str(), - ) + )? } }; @@ -287,7 +290,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let params = &generics.params[has_own_self as usize..]; self.path_generic_args(path, params, substs, ns, projections) } else { - path + Ok(path) } } } @@ -300,7 +303,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { ns: Namespace, self_ty: Ty<'tcx>, impl_trait_ref: Option>, - ) -> P::Path { + ) -> Result { debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", impl_def_id, self_ty, impl_trait_ref); @@ -323,7 +326,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - Some(self.print_def_path(parent_def_id, None, ns, iter::empty())) + Some(self.print_def_path(parent_def_id, None, ns, iter::empty())?) } else { // Otherwise, try to give a good form that would be valid language // syntax. Preferably using associated item notation. @@ -390,7 +393,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option { + fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result, P::Error> { debug!("try_print_visible_def_path: def_id={:?}", def_id); // If `def_id` is a direct or injected extern crate, return the @@ -399,7 +402,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let cnum = def_id.krate; if cnum == LOCAL_CRATE { - return Some(self.path_crate(cnum)); + return Ok(Some(self.path_crate(cnum)?)); } // In local mode, when we encounter a crate other than @@ -421,21 +424,21 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { }) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); let path = if !span.is_dummy() { - self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) + self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())? } else { - self.path_crate(cnum) + self.path_crate(cnum)? }; - return Some(path); + return Ok(Some(path)); } None => { - return Some(self.path_crate(cnum)); + return Ok(Some(self.path_crate(cnum)?)); } _ => {}, } } if def_id.is_local() { - return None; + return Ok(None); } let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); @@ -453,8 +456,14 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { cur_def_key = self.tcx.def_key(parent); } - let visible_parent = visible_parent_map.get(&def_id).cloned()?; - let path = self.try_print_visible_def_path(visible_parent)?; + let visible_parent = match visible_parent_map.get(&def_id).cloned() { + Some(parent) => parent, + None => return Ok(None), + }; + let path = match self.try_print_visible_def_path(visible_parent)? { + Some(path) => path, + None => return Ok(None), + }; let actual_parent = self.tcx.parent(def_id); let data = cur_def_key.disambiguated_data.data; @@ -518,7 +527,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { }, }; debug!("try_print_visible_def_path: symbol={:?}", symbol); - Some(self.path_append(path, &symbol)) + Ok(Some(self.path_append(path, &symbol)?)) } pub fn pretty_path_qualified( @@ -527,7 +536,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, - ) -> P::Path { + ) -> Result { if let Some(prefix) = impl_prefix { // HACK(eddyb) going through `path_append` means symbol name // computation gets to handle its equivalent of `::` correctly. @@ -585,9 +594,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, - ) -> P::Path { - let path = path?; - + ) -> Result { let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { if empty { @@ -669,7 +676,9 @@ impl fmt::Write for FmtPrinter { } impl Printer for FmtPrinter { - type Path = Result; + type Error = fmt::Error; + + type Path = PrettyPath; fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, @@ -677,20 +686,20 @@ impl Printer for FmtPrinter { substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, projections: impl Iterator>, - ) -> Self::Path { + ) -> Result { // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. let generics = substs.map(|_| self.tcx.generics_of(def_id)); if generics.as_ref().and_then(|g| g.parent).is_none() { - if let Some(path) = self.try_print_visible_def_path(def_id) { + if let Some(path) = self.try_print_visible_def_path(def_id)? { let path = if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(path, params, substs, ns, projections) + self.path_generic_args(path, params, substs, ns, projections)? } else { path }; - return path; + return Ok(path); } } @@ -710,7 +719,7 @@ impl Printer for FmtPrinter { // pretty printing some span information. This should // only occur very early in the compiler pipeline. let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let path = self.print_def_path(parent_def_id, None, ns, iter::empty()); + let path = self.print_def_path(parent_def_id, None, ns, iter::empty())?; let span = self.tcx.def_span(def_id); return self.path_append(path, &format!("", span)); } @@ -719,7 +728,10 @@ impl Printer for FmtPrinter { self.default_print_def_path(def_id, substs, ns, projections) } - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + fn path_crate( + self: &mut PrintCx<'_, '_, '_, Self>, + cnum: CrateNum, + ) -> Result { if cnum == LOCAL_CRATE { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. @@ -740,16 +752,14 @@ impl Printer for FmtPrinter { self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, - ) -> Self::Path { + ) -> Result { self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, path: Self::Path, text: &str, - ) -> Self::Path { - let path = path?; - + ) -> Result { // FIXME(eddyb) this shouldn't happen, but is currently // the case for `extern { ... }` "foreign modules". if text.is_empty() { @@ -769,7 +779,7 @@ impl Printer for FmtPrinter { substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, - ) -> Self::Path { + ) -> Result { self.pretty_path_generic_args(path, params, substs, ns, projections) } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index baa3c2bc4f887..43ca8eda569e2 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -193,7 +193,8 @@ macro_rules! gen_display_debug { macro_rules! gen_print_impl { ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target { - type Output = fmt::Result; + type Output = (); + type Error = fmt::Error; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { define_scoped_cx!($cx); if $cx.is_debug $dbg @@ -203,7 +204,8 @@ macro_rules! gen_print_impl { }; ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { impl Print<'tcx, P> for $target { - type Output = fmt::Result; + type Output = (); + type Error = fmt::Error; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { define_scoped_cx!($cx); if $cx.is_debug $dbg @@ -298,8 +300,8 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { Ok(()) } - fn in_binder(&mut self, value: &ty::Binder) -> fmt::Result - where T: Print<'tcx, P, Output = fmt::Result> + TypeFoldable<'tcx> + fn in_binder(&mut self, value: &ty::Binder) -> Result + where T: Print<'tcx, P, Error = fmt::Error> + TypeFoldable<'tcx> { fn name_by_region_index(index: usize) -> InternedString { match index { diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index ba57c00035b3f..9e909ce794cb7 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -405,9 +405,14 @@ impl fmt::Write for SymbolPath { } impl Printer for SymbolPath { - type Path = Result; + type Error = fmt::Error; - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + type Path = PrettyPath; + + fn path_crate( + self: &mut PrintCx<'_, '_, '_, Self>, + cnum: CrateNum, + ) -> Result { self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?; Ok(PrettyPath { empty: false }) } @@ -417,7 +422,7 @@ impl Printer for SymbolPath { self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, - ) -> Self::Path { + ) -> Result { // HACK(eddyb) avoid `keep_within_component` for the cases // that print without `<...>` around `self_ty`. match self_ty.sty { @@ -433,14 +438,17 @@ impl Printer for SymbolPath { // HACK(eddyb) make sure to finalize the last component of the // `impl` prefix, to avoid it fusing with the following text. - let impl_prefix = impl_prefix.map(|prefix| { - let mut prefix = self.path_append(prefix, "")?; + let impl_prefix = match impl_prefix { + Some(prefix) => { + let mut prefix = self.path_append(prefix, "")?; - // HACK(eddyb) also avoid an unnecessary `::`. - prefix.empty = true; + // HACK(eddyb) also avoid an unnecessary `::`. + prefix.empty = true; - Ok(prefix) - }); + Some(prefix) + } + None => None, + }; let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); let r = self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns); @@ -449,11 +457,9 @@ impl Printer for SymbolPath { } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, - path: Self::Path, + mut path: Self::Path, text: &str, - ) -> Self::Path { - let mut path = path?; - + ) -> Result { if self.keep_within_component { // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. if !path.empty { @@ -476,7 +482,7 @@ impl Printer for SymbolPath { substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, - ) -> Self::Path { + ) -> Result { let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); let r = self.pretty_path_generic_args(path, params, substs, ns, projections); self.printer.keep_within_component = kept_within_component; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index cabd83a6164f3..bcd6fbc0394d3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4050,10 +4050,15 @@ where F: Fn(DefId) -> Def { struct AbsolutePathPrinter; impl Printer for AbsolutePathPrinter { + type Error = !; + type Path = Vec; - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { - vec![self.tcx.original_crate_name(cnum).to_string()] + fn path_crate( + self: &mut PrintCx<'_, '_, '_, Self>, + cnum: CrateNum, + ) -> Result { + Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) } fn path_qualified( self: &mut PrintCx<'_, '_, 'tcx, Self>, @@ -4061,7 +4066,7 @@ where F: Fn(DefId) -> Def { self_ty: Ty<'tcx>, trait_ref: Option>, _ns: Namespace, - ) -> Self::Path { + ) -> Result { let mut path = impl_prefix.unwrap_or(vec![]); // This shouldn't ever be needed, but just in case: @@ -4071,15 +4076,15 @@ where F: Fn(DefId) -> Def { path.push(format!("<{}>", self_ty)); } - path + Ok(path) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, mut path: Self::Path, text: &str, - ) -> Self::Path { + ) -> Result { path.push(text.to_string()); - path + Ok(path) } fn path_generic_args( self: &mut PrintCx<'_, '_, 'tcx, Self>, @@ -4088,13 +4093,14 @@ where F: Fn(DefId) -> Def { _substs: &'tcx Substs<'tcx>, _ns: Namespace, _projections: impl Iterator>, - ) -> Self::Path { - path + ) -> Result { + Ok(path) } } let names = PrintCx::new(tcx, AbsolutePathPrinter) - .print_def_path(def_id, None, Namespace::TypeNS, iter::empty()); + .print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) + .unwrap(); hir::Path { span: DUMMY_SP, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 8f3567761b6e8..90250a515b8ac 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -19,6 +19,7 @@ #![feature(const_fn)] #![feature(drain_filter)] #![feature(inner_deref)] +#![feature(never_type)] #![recursion_limit="256"] From 18c504af489ebe90abf3dd27f84d2c3b519a035f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 10 Jan 2019 13:26:35 +0200 Subject: [PATCH 38/68] rustc: split off most of ty::print::PrintCx's fields into a separate struct. --- src/librustc/infer/error_reporting/mod.rs | 5 +- src/librustc/mir/mod.rs | 4 +- src/librustc/ty/print.rs | 69 ++++++++++++++-------- src/librustc/util/ppaux.rs | 61 +++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 7 ++- src/librustdoc/clean/mod.rs | 6 +- 6 files changed, 86 insertions(+), 66 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index c10d991acd2a3..2c53e1460e838 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -499,8 +499,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // module we could have false positives if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { - PrintCx::new(self.tcx, AbsolutePathPrinter) - .print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) + PrintCx::with(self.tcx, AbsolutePathPrinter, |mut cx| { + cx.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) + }) }; // We compare strings because DefPath can be different diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 00bc28ef0cb18..34075f13f2631 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2341,8 +2341,8 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; // When printing regions, add trailing space if necessary. - ty::print::PrintCx::with(ty::print::FmtPrinter { fmt }, |cx| { - let region = if cx.is_verbose || cx.identify_regions { + ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter { fmt }, |cx| { + let region = if cx.config.is_verbose || cx.config.identify_regions { let mut region = region.to_string(); if region.len() > 0 { region.push(' '); diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 99b430eba681a..dd02e34f6fd52 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -61,9 +61,7 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } } -pub struct PrintCx<'a, 'gcx, 'tcx, P> { - pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub printer: P, +pub(crate) struct PrintConfig { pub(crate) is_debug: bool, pub(crate) is_verbose: bool, pub(crate) identify_regions: bool, @@ -72,6 +70,25 @@ pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub(crate) binder_depth: usize, } +impl PrintConfig { + pub(crate) fn new(tcx: TyCtxt<'_, '_, '_>) -> Self { + PrintConfig { + is_debug: false, + is_verbose: tcx.sess.verbose(), + identify_regions: tcx.sess.opts.debugging_opts.identify_regions, + used_region_names: None, + region_index: 0, + binder_depth: 0, + } + } +} + +pub struct PrintCx<'a, 'gcx, 'tcx, P> { + pub tcx: TyCtxt<'a, 'gcx, 'tcx>, + pub printer: P, + pub(crate) config: &'a mut PrintConfig, +} + // HACK(eddyb) this is solely for `self: &mut PrintCx`, e.g. to // implement traits on the printer and call the methods on the context. impl

Deref for PrintCx<'_, '_, '_, P> { @@ -81,30 +98,29 @@ impl

Deref for PrintCx<'_, '_, '_, P> { } } -impl

PrintCx<'a, 'gcx, 'tcx, P> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, printer: P) -> Self { - PrintCx { +impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { + pub fn with( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + printer: P, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, P>) -> R, + ) -> R { + f(PrintCx { tcx, printer, - is_debug: false, - is_verbose: tcx.sess.verbose(), - identify_regions: tcx.sess.opts.debugging_opts.identify_regions, - used_region_names: None, - region_index: 0, - binder_depth: 0, - } + config: &mut PrintConfig::new(tcx), + }) } - pub(crate) fn with(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { - ty::tls::with(|tcx| f(PrintCx::new(tcx, printer))) + pub(crate) fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { + ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) } pub(crate) fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) where T: TypeFoldable<'tcx> { let mut collector = LateBoundRegionNameCollector(Default::default()); value.visit_with(&mut collector); - self.used_region_names = Some(collector.0); - self.region_index = 0; + self.config.used_region_names = Some(collector.0); + self.config.region_index = 0; } } @@ -117,17 +133,17 @@ pub trait Print<'tcx, P> { &self, cx: &mut PrintCx<'_, '_, 'tcx, P>, ) -> Result { - let old_debug = cx.is_debug; - cx.is_debug = false; + let old_debug = cx.config.is_debug; + cx.config.is_debug = false; let result = self.print(cx); - cx.is_debug = old_debug; + cx.config.is_debug = old_debug; result } fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result { - let old_debug = cx.is_debug; - cx.is_debug = true; + let old_debug = cx.config.is_debug; + cx.config.is_debug = true; let result = self.print(cx); - cx.is_debug = old_debug; + cx.config.is_debug = old_debug; result } } @@ -215,8 +231,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); - let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s }) - .print_def_path(def_id, None, ns, iter::empty()); + let _ = PrintCx::with(self, FmtPrinter { fmt: &mut s }, |mut cx| { + cx.print_def_path(def_id, None, ns, iter::empty()) + }); s } } @@ -616,7 +633,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { }); // Don't print args that are the defaults of their respective parameters. - let num_supplied_defaults = if self.is_verbose { + let num_supplied_defaults = if self.config.is_verbose { 0 } else { params.iter().rev().take_while(|param| { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 43ca8eda569e2..ae0dd28ec7526 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -161,7 +161,7 @@ impl RegionHighlightMode { macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { $with(&cx.tcx.lift(self).expect("could not lift for printing"), &mut cx) }) } @@ -197,7 +197,7 @@ macro_rules! gen_print_impl { type Error = fmt::Error; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { define_scoped_cx!($cx); - if $cx.is_debug $dbg + if $cx.config.is_debug $dbg else $disp } } @@ -208,7 +208,7 @@ macro_rules! gen_print_impl { type Error = fmt::Error; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { define_scoped_cx!($cx); - if $cx.is_debug $dbg + if $cx.config.is_debug $dbg else $disp } } @@ -316,7 +316,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // 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 { + if self.config.binder_depth == 0 { self.prepare_late_bound_region_info(value); } @@ -337,7 +337,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // is disallowed (name resolution thinks `scoped_cx!` is ambiguous). define_scoped_cx!(self); - let old_region_index = self.region_index; + let old_region_index = self.config.region_index; let mut region_index = old_region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { let _ = start_or_continue(self, "for<", ", "); @@ -365,16 +365,16 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { start_or_continue(self, "", "> ")?; // Push current state to gcx, and restore after writing new_value. - self.binder_depth += 1; - self.region_index = region_index; + self.config.binder_depth += 1; + self.config.region_index = region_index; let result = new_value.print_display(self); - self.region_index = old_region_index; - self.binder_depth -= 1; + self.config.region_index = old_region_index; + self.config.binder_depth -= 1; result } fn is_name_used(&self, name: &InternedString) -> bool { - match self.used_region_names { + match self.config.used_region_names { Some(ref names) => names.contains(name), None => false, } @@ -387,7 +387,7 @@ pub fn parameterized( substs: &Substs<'_>, ns: Namespace, ) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); let _ = cx.print_def_path(did, Some(substs), ns, iter::empty())?; Ok(()) @@ -404,8 +404,9 @@ define_print! { let mut resugared_principal = false; // Special-case `Fn(...) -> ...` and resugar it. - if !cx.is_verbose && cx.tcx.lang_items().fn_trait_kind(principal.def_id).is_some() { - if let Tuple(ref args) = principal.substs.type_at(0).sty { + let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); + if !cx.config.is_verbose && fn_trait_kind.is_some() { + if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { let _ = cx.print_def_path( @@ -485,7 +486,7 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { let _ = cx.print_def_path( self.def_id, None, @@ -499,7 +500,7 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { let _ = cx.print_def_path( self.did, None, @@ -521,7 +522,7 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { define_scoped_cx!(cx); p!(write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, @@ -591,7 +592,7 @@ define_print! { define_print! { () ty::BoundRegion, (self, cx) { display { - if cx.is_verbose { + if cx.config.is_verbose { return self.print_debug(cx); } @@ -629,7 +630,7 @@ define_print! { // NB: this must be kept in sync with the printing logic above. impl ty::BoundRegion { fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { - if cx.is_verbose { + if cx.config.is_verbose { return true; } @@ -653,7 +654,7 @@ impl ty::BoundRegion { define_print! { () ty::PlaceholderRegion, (self, cx) { display { - if cx.is_verbose { + if cx.config.is_verbose { return self.print_debug(cx); } @@ -672,7 +673,7 @@ define_print! { // NB: this must be kept in sync with the printing logic above. impl ty::PlaceholderRegion { fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { - if cx.is_verbose { + if cx.config.is_verbose { return true; } @@ -688,7 +689,7 @@ impl ty::PlaceholderRegion { define_print! { () ty::RegionKind, (self, cx) { display { - if cx.is_verbose { + if cx.config.is_verbose { return self.print_debug(cx); } @@ -716,7 +717,7 @@ define_print! { ty::RePlaceholder(p) => { p!(print_display(p)) } - ty::ReScope(scope) if cx.identify_regions => { + ty::ReScope(scope) if cx.config.identify_regions => { match scope.data { region::ScopeData::Node => p!(write("'{}s", scope.item_local_id().as_usize())), @@ -733,7 +734,7 @@ define_print! { )), } } - ty::ReVar(region_vid) if cx.identify_regions => { + ty::ReVar(region_vid) if cx.config.identify_regions => { p!(print_debug(region_vid)) } ty::ReVar(region_vid) => { @@ -800,7 +801,7 @@ define_print! { impl ty::RegionKind { // HACK(eddyb) `pub(crate)` only for `ty::print`. pub(crate) fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { - if cx.is_verbose { + if cx.config.is_verbose { return true; } @@ -821,7 +822,7 @@ impl ty::RegionKind { ty::RePlaceholder(p) => p.display_outputs_anything(cx), ty::ReScope(_) | - ty::ReVar(_) if cx.identify_regions => true, + ty::ReVar(_) if cx.config.identify_regions => true, ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx), @@ -898,7 +899,7 @@ impl fmt::Debug for ty::FloatVid { define_print! { () ty::RegionVid, (self, cx) { display { - if cx.is_verbose { + if cx.config.is_verbose { return self.print_debug(cx); } @@ -927,7 +928,7 @@ define_print! { // NB: this must be kept in sync with the printing logic above. impl ty::RegionVid { fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { - if cx.is_verbose { + if cx.config.is_verbose { return true; } @@ -943,7 +944,7 @@ impl ty::RegionVid { define_print! { () ty::InferTy, (self, cx) { display { - if cx.is_verbose { + if cx.config.is_verbose { return self.print_debug(cx); } match *self { @@ -990,7 +991,7 @@ impl fmt::Debug for ty::FloatVarValue { for<'a> >::Lifted: fmt::Display + TypeFoldable<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(|cx| cx.in_binder(cx.tcx.lift(self) + PrintCx::with_tls_tcx(|cx| cx.in_binder(cx.tcx.lift(self) .expect("could not lift for printing"))) } }*/ @@ -1139,7 +1140,7 @@ define_print! { p!(write("Placeholder({:?})", placeholder)) } Opaque(def_id, substs) => { - if cx.is_verbose { + if cx.config.is_verbose { return p!(write("Opaque({:?}, {:?})", def_id, substs)); } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 9e909ce794cb7..d5cc3807524c2 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -223,9 +223,10 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - let mut cx = PrintCx::new(tcx, SymbolPath::new()); - let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); - cx.printer.into_interned() + PrintCx::with(tcx, SymbolPath::new(), |mut cx| { + let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); + cx.printer.into_interned() + }) } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index bcd6fbc0394d3..7caa54e1a26c5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4098,9 +4098,9 @@ where F: Fn(DefId) -> Def { } } - let names = PrintCx::new(tcx, AbsolutePathPrinter) - .print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) - .unwrap(); + let names = PrintCx::with(tcx, AbsolutePathPrinter, |mut cx| { + cx.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()).unwrap() + }); hir::Path { span: DUMMY_SP, From d9934290e0aa8bc05c72de4d21d6361e9701fefd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 10 Jan 2019 14:50:36 +0200 Subject: [PATCH 39/68] rustc: remove the closure from ppaux's p! macro (by making ? implicit). --- src/librustc/ty/print.rs | 8 +- src/librustc/util/ppaux.rs | 240 ++++++++++++++++++------------------- 2 files changed, 118 insertions(+), 130 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index dd02e34f6fd52..1ded480cd05e0 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -614,12 +614,12 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { ) -> Result { let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - if empty { + write!(cx.printer, "{}", if empty { empty = false; - write!(cx.printer, "{}", start) + start } else { - write!(cx.printer, "{}", cont) - } + cont + }) }; let start = if ns == Namespace::ValueNS { "::<" } else { "<" }; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ae0dd28ec7526..c4ccef443122f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -196,9 +196,11 @@ macro_rules! gen_print_impl { type Output = (); type Error = fmt::Error; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { - define_scoped_cx!($cx); - if $cx.config.is_debug $dbg - else $disp + Ok({ + define_scoped_cx!($cx); + if $cx.config.is_debug $dbg + else $disp + }) } } }; @@ -207,9 +209,11 @@ macro_rules! gen_print_impl { type Output = (); type Error = fmt::Error; fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { - define_scoped_cx!($cx); - if $cx.config.is_debug $dbg - else $disp + Ok({ + define_scoped_cx!($cx); + if $cx.config.is_debug $dbg + else $disp + }) } } }; @@ -238,7 +242,7 @@ macro_rules! define_print { ( $generic:tt $target:ty, ($self:ident, $cx:ident) { display $disp:block } ) => { gen_print_impl! { $generic $target, ($self, $cx) yes $disp no { - write!($cx.printer, "{:?}", $self) + write!($cx.printer, "{:?}", $self)? } } }; } @@ -257,10 +261,9 @@ macro_rules! print_inner { } macro_rules! p { ($($kind:ident $data:tt),+) => { - (|| -> fmt::Result { - $(print_inner!($kind $data)?;)+ - Ok(()) - })() + { + $(print_inner!($kind $data)?);+ + } }; } macro_rules! define_scoped_cx { @@ -281,20 +284,20 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { ) -> fmt::Result { define_scoped_cx!(self); - p!(write("("))?; + p!(write("(")); let mut inputs = inputs.iter(); if let Some(&ty) = inputs.next() { - p!(print_display(ty))?; + p!(print_display(ty)); for &ty in inputs { - p!(write(", "), print_display(ty))?; + p!(write(", "), print_display(ty)); } if variadic { - p!(write(", ..."))?; + p!(write(", ...")); } } - p!(write(")"))?; + p!(write(")")); if !output.is_unit() { - p!(write(" -> "), print_display(output))?; + p!(write(" -> "), print_display(output)); } Ok(()) @@ -322,14 +325,12 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - define_scoped_cx!(cx); - - if empty { + write!(cx.printer, "{}", if empty { empty = false; - p!(write("{}", start)) + start } else { - p!(write("{}", cont)) - } + cont + }) }; // NOTE(eddyb) this must be below `start_or_continue`'s definition @@ -343,7 +344,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let _ = start_or_continue(self, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { - let _ = p!(write("{}", name)); + let _ = write!(self.printer, "{}", name); br } ty::BrAnon(_) | @@ -356,7 +357,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { break name; } }; - let _ = p!(write("{}", name)); + let _ = write!(self.printer, "{}", name); ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name) } }; @@ -453,7 +454,7 @@ define_print! { for (_, def_id) in auto_traits { if !first { - p!(write(" + "))?; + p!(write(" + ")); } first = false; @@ -464,8 +465,6 @@ define_print! { iter::empty(), )?; } - - Ok(()) } } } @@ -527,7 +526,8 @@ impl fmt::Debug for ty::UpvarId { p!(write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)), - self.closure_expr_id)) + self.closure_expr_id)); + Ok(()) }) } } @@ -542,12 +542,12 @@ impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { define_print! { ('tcx) &'tcx ty::List>, (self, cx) { display { - p!(write("{{"))?; + p!(write("{{")); let mut tys = self.iter(); if let Some(&ty) = tys.next() { - p!(print(ty))?; + p!(print(ty)); for &ty in tys { - p!(write(", "), print(ty))?; + p!(write(", "), print(ty)); } } p!(write("}}")) @@ -570,13 +570,12 @@ define_print! { display { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - ty::Binder::bind(*self) + p!(print_display(ty::Binder::bind(*self) .with_self_ty(cx.tcx, dummy_self) - .skip_binder() - .print_display(cx) + .skip_binder())) } debug { - self.print_display(cx) + p!(print_display(self)) } } } @@ -598,21 +597,20 @@ define_print! { if let BrNamed(_, name) = *self { if name != "" && name != "'_" { - return p!(write("{}", name)); + p!(write("{}", name)); + return Ok(()); } } let highlight = RegionHighlightMode::get(); if let Some((region, counter)) = highlight.highlight_bound_region { if *self == region { - return p!(write("'{}", counter)); + p!(write("'{}", counter)); } } - - Ok(()) } debug { - return match *self { + match *self { BrAnon(n) => p!(write("BrAnon({:?})", n)), BrFresh(n) => p!(write("BrFresh({:?})", n)), BrNamed(did, name) => { @@ -620,7 +618,7 @@ define_print! { did.krate, did.index, name)) } BrEnv => p!(write("BrEnv")), - }; + } } } } @@ -660,10 +658,10 @@ define_print! { let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.placeholder_highlight(*self) { - return p!(write("'{}", counter)); + p!(write("'{}", counter)); + } else { + p!(print_display(self.name)); } - - p!(print_display(self.name)) } } } @@ -695,7 +693,8 @@ define_print! { // Watch out for region highlights. if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { - return p!(write("'{:?}", n)); + p!(write("'{:?}", n)); + return Ok(()); } // These printouts are concise. They do not contain all the information @@ -706,8 +705,6 @@ define_print! { ty::ReEarlyBound(ref data) => { if data.name != "'_" { p!(write("{}", data.name)) - } else { - Ok(()) } } ty::ReLateBound(_, br) | @@ -741,7 +738,7 @@ define_print! { p!(print_display(region_vid)) } ty::ReScope(_) | - ty::ReErased => Ok(()), + ty::ReErased => {} ty::ReStatic => p!(write("'static")), ty::ReEmpty => p!(write("'")), @@ -852,7 +849,7 @@ define_print! { ty::Contravariant => "-", ty::Invariant => "o", ty::Bivariant => "*", - }) + })? } } } @@ -861,15 +858,15 @@ define_print! { ('tcx) ty::FnSig<'tcx>, (self, cx) { display { if self.unsafety == hir::Unsafety::Unsafe { - p!(write("unsafe "))?; + p!(write("unsafe ")); } if self.abi != Abi::Rust { - p!(write("extern {} ", self.abi))?; + p!(write("extern {} ", self.abi)); } - p!(write("fn"))?; - cx.fn_sig(self.inputs(), self.variadic, self.output()) + p!(write("fn")); + cx.fn_sig(self.inputs(), self.variadic, self.output())? } debug { p!(write("({:?}; variadic: {})->{:?}", @@ -905,20 +902,18 @@ define_print! { let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - return p!(write("'{:?}", counter)); + p!(write("'{:?}", counter)); } - - Ok(()) } debug { // HACK(eddyb) this is duplicated from `display` printing, // to keep NLL borrowck working even with `-Zverbose`. let highlight = RegionHighlightMode::get(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - return p!(write("'{:?}", counter)); + p!(write("'{:?}", counter)); + } else { + p!(write("'_#{}r", self.index())); } - - p!(write("'_#{}r", self.index())) } } } @@ -1009,7 +1004,7 @@ define_print_multi! { ] (self, cx) { display { - cx.in_binder(self) + cx.in_binder(self)? } } } @@ -1023,11 +1018,9 @@ define_print! { Namespace::TypeNS, iter::empty(), )?; - Ok(()) } debug { let _ = cx.path_qualified(None, self.self_ty(), Some(*self), Namespace::TypeNS)?; - Ok(()) } } } @@ -1045,26 +1038,26 @@ define_print! { p!(write("*{} ", match tm.mutbl { hir::MutMutable => "mut", hir::MutImmutable => "const", - }))?; - tm.ty.print(cx) + })); + p!(print(tm.ty)) } Ref(r, ty, mutbl) => { - p!(write("&"))?; + p!(write("&")); if r.display_outputs_anything(cx) { - p!(print_display(r), write(" "))?; + p!(print_display(r), write(" ")); } - ty::TypeAndMut { ty, mutbl }.print(cx) + p!(print(ty::TypeAndMut { ty, mutbl })) } Never => p!(write("!")), Tuple(ref tys) => { - p!(write("("))?; + p!(write("(")); let mut tys = tys.iter(); if let Some(&ty) = tys.next() { - p!(print(ty), write(","))?; + p!(print(ty), write(",")); if let Some(&ty) = tys.next() { - p!(write(" "), print(ty))?; + p!(write(" "), print(ty)); for &ty in tys { - p!(write(", "), print(ty))?; + p!(write(", "), print(ty)); } } } @@ -1072,7 +1065,7 @@ define_print! { } FnDef(def_id, substs) => { let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); - p!(print(sig), write(" {{"))?; + p!(print(sig), write(" {{")); let _ = cx.print_def_path( def_id, Some(substs), @@ -1082,7 +1075,7 @@ define_print! { p!(write("}}")) } FnPtr(ref bare_fn) => { - bare_fn.print(cx) + p!(print(bare_fn)) } Infer(infer_ty) => p!(write("{}", infer_ty)), Error => p!(write("[type error]")), @@ -1107,19 +1100,16 @@ define_print! { Namespace::TypeNS, iter::empty(), )?; - Ok(()) } Dynamic(data, r) => { let print_r = r.display_outputs_anything(cx); if print_r { - p!(write("("))?; + p!(write("(")); } - p!(write("dyn "))?; - data.print(cx)?; + p!(write("dyn "), print(data)); if print_r { - p!(write(" + "), print_display(r), write(")"))?; + p!(write(" + "), print_display(r), write(")")); } - Ok(()) } Foreign(def_id) => { let _ = cx.print_def_path( @@ -1128,11 +1118,10 @@ define_print! { Namespace::TypeNS, iter::empty(), )?; - Ok(()) } - Projection(ref data) => data.print(cx), + Projection(ref data) => p!(print(data)), UnnormalizedProjection(ref data) => { - p!(write("Unnormalized("))?; + p!(write("Unnormalized(")); data.print(cx)?; p!(write(")")) } @@ -1141,21 +1130,22 @@ define_print! { } Opaque(def_id, substs) => { if cx.config.is_verbose { - return p!(write("Opaque({:?}, {:?})", def_id, substs)); + p!(write("Opaque({:?}, {:?})", def_id, substs)); + return Ok(()); } let def_key = cx.tcx.def_key(def_id); if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - p!(write("{}", name))?; + p!(write("{}", name)); let mut substs = substs.iter(); // FIXME(eddyb) print this with `print_def_path`. if let Some(first) = substs.next() { - p!(write("::<"))?; - p!(write("{}", first))?; + p!(write("::<")); + p!(write("{}", first)); for subst in substs { - p!(write(", {}", subst))?; + p!(write(", {}", subst)); } - p!(write(">"))?; + p!(write(">")); } return Ok(()); } @@ -1165,7 +1155,7 @@ define_print! { let mut first = true; let mut is_sized = false; - p!(write("impl"))?; + p!(write("impl")); for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. @@ -1176,30 +1166,29 @@ define_print! { p!( write("{}", if first { " " } else { "+" }), - print(trait_ref))?; + print(trait_ref)); first = false; } } if !is_sized { - p!(write("{}?Sized", if first { " " } else { "+" }))?; + p!(write("{}?Sized", if first { " " } else { "+" })); } else if first { - p!(write(" Sized"))?; + p!(write(" Sized")); } - Ok(()) } Str => p!(write("str")), Generator(did, substs, movability) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); let witness = substs.witness(did, cx.tcx); if movability == hir::GeneratorMovability::Movable { - p!(write("[generator"))?; + p!(write("[generator")); } else { - p!(write("[static generator"))?; + p!(write("[static generator")); } // FIXME(eddyb) should use `def_span`. if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { - p!(write("@{:?}", cx.tcx.hir().span(node_id)))?; + p!(write("@{:?}", cx.tcx.hir().span(node_id))); let mut sep = " "; cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { @@ -1207,7 +1196,7 @@ define_print! { write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty))?; + print(upvar_ty)); sep = ", "; } Ok(()) @@ -1215,12 +1204,12 @@ define_print! { } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. - p!(write("@{:?}", did))?; + p!(write("@{:?}", did)); let mut sep = " "; for (index, upvar_ty) in upvar_tys.enumerate() { p!( write("{}{}:", sep, index), - print(upvar_ty))?; + print(upvar_ty)); sep = ", "; } } @@ -1228,18 +1217,18 @@ define_print! { p!(write(" "), print(witness), write("]")) }, GeneratorWitness(types) => { - cx.in_binder(&types) + cx.in_binder(&types)? } Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); - p!(write("[closure"))?; + p!(write("[closure")); // FIXME(eddyb) should use `def_span`. if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { if cx.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", node_id))?; + p!(write("@{:?}", node_id)); } else { - p!(write("@{:?}", cx.tcx.hir().span(node_id)))?; + p!(write("@{:?}", cx.tcx.hir().span(node_id))); } let mut sep = " "; cx.tcx.with_freevars(node_id, |freevars| { @@ -1248,7 +1237,7 @@ define_print! { write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty))?; + print(upvar_ty)); sep = ", "; } Ok(()) @@ -1256,12 +1245,12 @@ define_print! { } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. - p!(write("@{:?}", did))?; + p!(write("@{:?}", did)); let mut sep = " "; for (index, upvar_ty) in upvar_tys.enumerate() { p!( write("{}{}:", sep, index), - print(upvar_ty))?; + print(upvar_ty)); sep = ", "; } } @@ -1269,13 +1258,13 @@ define_print! { p!(write("]")) }, Array(ty, sz) => { - p!(write("["), print(ty), write("; "))?; + p!(write("["), print(ty), write("; ")); match sz { ty::LazyConst::Unevaluated(_def_id, _substs) => { - p!(write("_"))?; + p!(write("_")); } ty::LazyConst::Evaluated(c) => { - p!(write("{}", c.unwrap_usize(cx.tcx)))?; + p!(write("{}", c.unwrap_usize(cx.tcx))); } } p!(write("]")) @@ -1286,7 +1275,7 @@ define_print! { } } debug { - self.print_display(cx) + p!(print_display(self)) } } } @@ -1360,7 +1349,6 @@ define_print! { Namespace::TypeNS, iter::empty(), )?; - Ok(()) } } } @@ -1381,14 +1369,14 @@ define_print! { ('tcx) ty::Predicate<'tcx>, (self, cx) { display { match *self { - ty::Predicate::Trait(ref data) => data.print(cx), - ty::Predicate::Subtype(ref predicate) => predicate.print(cx), - ty::Predicate::RegionOutlives(ref predicate) => predicate.print(cx), - ty::Predicate::TypeOutlives(ref predicate) => predicate.print(cx), - ty::Predicate::Projection(ref predicate) => predicate.print(cx), + ty::Predicate::Trait(ref data) => p!(print(data)), + ty::Predicate::Subtype(ref predicate) => p!(print(predicate)), + ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)), + ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)), + ty::Predicate::Projection(ref predicate) => p!(print(predicate)), ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { - p!(write("the trait `"))?; + p!(write("the trait `")); let _ = cx.print_def_path( trait_def_id, None, @@ -1398,7 +1386,7 @@ define_print! { p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - p!(write("the closure `"))?; + p!(write("the closure `")); let _ = cx.print_def_path( closure_def_id, None, @@ -1408,7 +1396,7 @@ define_print! { p!(write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { - p!(write("the constant `"))?; + p!(write("the constant `")); let _ = cx.print_def_path( def_id, Some(substs), @@ -1421,12 +1409,12 @@ define_print! { } debug { match *self { - ty::Predicate::Trait(ref a) => a.print(cx), - ty::Predicate::Subtype(ref pair) => pair.print(cx), - ty::Predicate::RegionOutlives(ref pair) => pair.print(cx), - ty::Predicate::TypeOutlives(ref pair) => pair.print(cx), - ty::Predicate::Projection(ref pair) => pair.print(cx), - ty::Predicate::WellFormed(ty) => ty.print(cx), + ty::Predicate::Trait(ref a) => p!(print(a)), + ty::Predicate::Subtype(ref pair) => p!(print(pair)), + ty::Predicate::RegionOutlives(ref pair) => p!(print(pair)), + ty::Predicate::TypeOutlives(ref pair) => p!(print(pair)), + ty::Predicate::Projection(ref pair) => p!(print(pair)), + ty::Predicate::WellFormed(ty) => p!(print(ty)), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("ObjectSafe({:?})", trait_def_id)) } From 3cbe070e10d94e3d4711008ab173ae5d7e5c4f06 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 10 Jan 2019 13:27:11 +0200 Subject: [PATCH 40/68] rustc: pass ty::print::PrintCx by value. --- src/librustc/infer/error_reporting/mod.rs | 37 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/print.rs | 387 ++++++++++++++------- src/librustc/util/ppaux.rs | 205 ++++++----- src/librustc_codegen_utils/symbol_names.rs | 117 ++++--- src/librustdoc/clean/mod.rs | 54 ++- 6 files changed, 498 insertions(+), 304 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 2c53e1460e838..b299e4ab748bb 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -460,37 +460,52 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Path = Vec; fn path_crate( - self: &mut PrintCx<'_, '_, '_, Self>, + self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) } fn path_qualified<'tcx>( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - _impl_prefix: Option, + self: PrintCx<'_, '_, 'tcx, Self>, _self_ty: Ty<'tcx>, _trait_ref: Option>, _ns: Namespace, ) -> Result { Err(NonTrivialPath) } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, + + fn path_append_impl<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + _print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + _self_ty: Ty<'tcx>, + _trait_ref: Option>, + ) -> Result { + Err(NonTrivialPath) + } + fn path_append<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, text: &str, ) -> Result { + let mut path = print_prefix(self)?; path.push(text.to_string()); Ok(path) } - fn path_generic_args<'tcx>( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - path: Self::Path, + fn path_generic_args<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, _params: &[ty::GenericParamDef], _substs: &'tcx Substs<'tcx>, _ns: Namespace, _projections: impl Iterator>, ) -> Result { - Ok(path) + print_prefix(self) } } @@ -499,7 +514,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // module we could have false positives if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { - PrintCx::with(self.tcx, AbsolutePathPrinter, |mut cx| { + PrintCx::with(self.tcx, AbsolutePathPrinter, |cx| { cx.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) }) }; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 34075f13f2631..6c4ab85125e29 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2341,7 +2341,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; // When printing regions, add trailing space if necessary. - ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter { fmt }, |cx| { + ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter::new(fmt), |cx| { let region = if cx.config.is_verbose || cx.config.identify_regions { let mut region = region.to_string(); if region.len() > 0 { diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 1ded480cd05e0..b7713249d2133 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -89,7 +89,7 @@ pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub(crate) config: &'a mut PrintConfig, } -// HACK(eddyb) this is solely for `self: &mut PrintCx`, e.g. to +// HACK(eddyb) this is solely for `self: PrintCx`, e.g. to // implement traits on the printer and call the methods on the context. impl

Deref for PrintCx<'_, '_, '_, P> { type Target = P; @@ -128,21 +128,29 @@ pub trait Print<'tcx, P> { type Output; type Error; - fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result; + fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result; fn print_display( &self, - cx: &mut PrintCx<'_, '_, 'tcx, P>, + cx: PrintCx<'_, '_, 'tcx, P>, ) -> Result { let old_debug = cx.config.is_debug; cx.config.is_debug = false; - let result = self.print(cx); + let result = self.print(PrintCx { + tcx: cx.tcx, + printer: cx.printer, + config: cx.config, + }); cx.config.is_debug = old_debug; result } - fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print_debug(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { let old_debug = cx.config.is_debug; cx.config.is_debug = true; - let result = self.print(cx); + let result = self.print(PrintCx { + tcx: cx.tcx, + printer: cx.printer, + config: cx.config, + }); cx.config.is_debug = old_debug; result } @@ -154,7 +162,7 @@ pub trait Printer: Sized { type Path; fn print_def_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, + self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, @@ -163,7 +171,7 @@ pub trait Printer: Sized { self.default_print_def_path(def_id, substs, ns, projections) } fn print_impl_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, + self: PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, @@ -174,24 +182,36 @@ pub trait Printer: Sized { } fn path_crate( - self: &mut PrintCx<'_, '_, '_, Self>, + self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result; fn path_qualified( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_prefix: Option, + self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, ) -> Result; - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - path: Self::Path, + + fn path_append_impl<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result; + fn path_append<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, text: &str, ) -> Result; - fn path_generic_args( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - path: Self::Path, + fn path_generic_args<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, ns: Namespace, @@ -199,13 +219,32 @@ pub trait Printer: Sized { ) -> Result; } -#[must_use] -pub struct PrettyPath { - pub empty: bool, +/// Trait for printers that pretty-print using `fmt::Write` to the printer. +pub trait PrettyPrinter: Printer + fmt::Write { + /// Enter a nested print context, for pretty-printing + /// nested components in some larger context. + fn nest<'a, 'gcx, 'tcx, E>( + self: PrintCx<'a, 'gcx, 'tcx, Self>, + f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result, + ) -> Result, E> { + let printer = f(PrintCx { + tcx: self.tcx, + printer: self.printer, + config: self.config, + })?; + Ok(PrintCx { + tcx: self.tcx, + printer, + config: self.config, + }) + } } -/// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter: Printer + fmt::Write {} +macro_rules! nest { + ($cx:ident, $closure:expr) => { + $cx = $cx.nest($closure)? + } +} impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always @@ -231,7 +270,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); - let _ = PrintCx::with(self, FmtPrinter { fmt: &mut s }, |mut cx| { + let _ = PrintCx::with(self, FmtPrinter::new(&mut s), |cx| { cx.print_def_path(def_id, None, ns, iter::empty()) }); s @@ -240,7 +279,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { impl PrintCx<'a, 'gcx, 'tcx, P> { pub fn default_print_def_path( - &mut self, + self, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, @@ -273,48 +312,52 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let generics = substs.map(|_| self.tcx.generics_of(def_id)); let generics_parent = generics.as_ref().and_then(|g| g.parent); let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let path = if let Some(generics_parent_def_id) = generics_parent { - assert_eq!(parent_def_id, generics_parent_def_id); - - // FIXME(eddyb) try to move this into the parent's printing - // logic, instead of doing it when printing the child. - let parent_generics = self.tcx.generics_of(parent_def_id); - let parent_has_own_self = - parent_generics.has_self && parent_generics.parent_count == 0; - if let (Some(substs), true) = (substs, parent_has_own_self) { - let trait_ref = ty::TraitRef::new(parent_def_id, substs); - self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns)? + let print_parent_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| { + if let Some(generics_parent_def_id) = generics_parent { + assert_eq!(parent_def_id, generics_parent_def_id); + + // FIXME(eddyb) try to move this into the parent's printing + // logic, instead of doing it when printing the child. + let parent_generics = cx.tcx.generics_of(parent_def_id); + let parent_has_own_self = + parent_generics.has_self && parent_generics.parent_count == 0; + if let (Some(substs), true) = (substs, parent_has_own_self) { + let trait_ref = ty::TraitRef::new(parent_def_id, substs); + cx.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns) + } else { + cx.print_def_path(parent_def_id, substs, ns, iter::empty()) + } } else { - self.print_def_path(parent_def_id, substs, ns, iter::empty())? + cx.print_def_path(parent_def_id, None, ns, iter::empty()) } - } else { - self.print_def_path(parent_def_id, None, ns, iter::empty())? }; - let path = match key.disambiguated_data.data { - // Skip `::{{constructor}}` on tuple/unit structs. - DefPathData::StructCtor => path, - - _ => { - self.path_append( - path, - &key.disambiguated_data.data.as_interned_str().as_str(), - )? + let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| { + match key.disambiguated_data.data { + // Skip `::{{constructor}}` on tuple/unit structs. + DefPathData::StructCtor => print_parent_path(cx), + + _ => { + cx.path_append( + print_parent_path, + &key.disambiguated_data.data.as_interned_str().as_str(), + ) + } } }; if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(path, params, substs, ns, projections) + self.path_generic_args(print_path, params, substs, ns, projections) } else { - Ok(path) + print_path(self) } } } } fn default_print_impl_path( - &mut self, + self, impl_def_id: DefId, _substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, @@ -339,18 +382,20 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), }; - let prefix_path = if !in_self_mod && !in_trait_mod { + if !in_self_mod && !in_trait_mod { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - Some(self.print_def_path(parent_def_id, None, ns, iter::empty())?) + self.path_append_impl( + |cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()), + self_ty, + impl_trait_ref, + ) } else { // Otherwise, try to give a good form that would be valid language // syntax. Preferably using associated item notation. - None - }; - - self.path_qualified(prefix_path, self_ty, impl_trait_ref, ns) + self.path_qualified(self_ty, impl_trait_ref, ns) + } } } @@ -403,14 +448,27 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } pub struct FmtPrinter { - pub fmt: F, + pub(crate) fmt: F, + empty: bool, +} + +impl FmtPrinter { + pub fn new(fmt: F) -> Self { + FmtPrinter { + fmt, + empty: true, + } + } } -impl PrintCx<'a, 'gcx, 'tcx, P> { +impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result, P::Error> { + fn try_print_visible_def_path( + mut self, + def_id: DefId, + ) -> Result<(P, bool), P::Error> { debug!("try_print_visible_def_path: def_id={:?}", def_id); // If `def_id` is a direct or injected extern crate, return the @@ -419,7 +477,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let cnum = def_id.krate; if cnum == LOCAL_CRATE { - return Ok(Some(self.path_crate(cnum)?)); + return Ok((self.path_crate(cnum)?, true)); } // In local mode, when we encounter a crate other than @@ -440,22 +498,21 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { .. }) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); - let path = if !span.is_dummy() { + return Ok((if !span.is_dummy() { self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())? } else { self.path_crate(cnum)? - }; - return Ok(Some(path)); + }, true)); } None => { - return Ok(Some(self.path_crate(cnum)?)); + return Ok((self.path_crate(cnum)?, true)); } _ => {}, } } if def_id.is_local() { - return Ok(None); + return Ok((self.printer, false)); } let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); @@ -475,11 +532,20 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let visible_parent = match visible_parent_map.get(&def_id).cloned() { Some(parent) => parent, - None => return Ok(None), + None => return Ok((self.printer, false)), }; - let path = match self.try_print_visible_def_path(visible_parent)? { - Some(path) => path, - None => return Ok(None), + // HACK(eddyb) this uses `nest` to avoid knowing ahead of time whether + // the entire path will succeed or not. To support printers that do not + // implement `PrettyPrinter`, a `Vec` or linked list on the stack would + // need to be built, before starting to print anything. + let mut prefix_success = false; + nest!(self, |cx| { + let (printer, success) = cx.try_print_visible_def_path(visible_parent)?; + prefix_success = success; + Ok(printer) + }); + if !prefix_success { + return Ok((self.printer, false)); }; let actual_parent = self.tcx.parent(def_id); @@ -544,29 +610,15 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { }, }; debug!("try_print_visible_def_path: symbol={:?}", symbol); - Ok(Some(self.path_append(path, &symbol)?)) + Ok((self.path_append(|cx| Ok(cx.printer), &symbol)?, true)) } pub fn pretty_path_qualified( - &mut self, - impl_prefix: Option, + mut self, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, ) -> Result { - if let Some(prefix) = impl_prefix { - // HACK(eddyb) going through `path_append` means symbol name - // computation gets to handle its equivalent of `::` correctly. - let _ = self.path_append(prefix, "")?; - return Ok(PrettyPath { empty: false }); - } - if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is @@ -581,8 +633,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { - self_ty.print_display(self)?; - return Ok(PrettyPath { empty: false }); + return self_ty.print_display(self); } _ => {} @@ -590,28 +641,54 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } write!(self.printer, "<")?; - self_ty.print_display(self)?; + nest!(self, |cx| self_ty.print_display(cx)); if let Some(trait_ref) = trait_ref { write!(self.printer, " as ")?; - let _ = self.print_def_path( + nest!(self, |cx| cx.print_def_path( trait_ref.def_id, Some(trait_ref.substs), Namespace::TypeNS, iter::empty(), - )?; + )); + } + write!(self.printer, ">")?; + + Ok(self.printer) + } + + pub fn pretty_path_append_impl( + mut self, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, P>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + // HACK(eddyb) going through `path_append` means symbol name + // computation gets to handle its equivalent of `::` correctly. + nest!(self, |cx| cx.path_append(print_prefix, "")?; - Ok(PrettyPath { empty: false }) + + Ok(self.printer) } pub fn pretty_path_generic_args( - &mut self, - path: P::Path, + mut self, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, P>, + ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, ) -> Result { + nest!(self, |cx| print_prefix(cx)); + let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { write!(cx.printer, "{}", if empty { @@ -654,8 +731,8 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { if !print_regions { continue; } - start_or_continue(self, start, ", ")?; - if !region.display_outputs_anything(self) { + start_or_continue(&mut self, start, ", ")?; + if !region.display_outputs_anything(&self) { // This happens when the value of the region // parameter is not easily serialized. This may be // because the user omitted it in the first place, @@ -663,31 +740,32 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // etc. I'm not sure how best to serialize this. write!(self.printer, "'_")?; } else { - region.print_display(self)?; + nest!(self, |cx| region.print_display(cx)); } } UnpackedKind::Type(ty) => { - start_or_continue(self, start, ", ")?; - ty.print_display(self)?; + start_or_continue(&mut self, start, ", ")?; + nest!(self, |cx| ty.print_display(cx)); } } } for projection in projections { - start_or_continue(self, start, ", ")?; + start_or_continue(&mut self, start, ", ")?; write!(self.printer, "{}=", self.tcx.associated_item(projection.item_def_id).ident)?; - projection.ty.print_display(self)?; + nest!(self, |cx| projection.ty.print_display(cx)); } - start_or_continue(self, "", ">")?; + start_or_continue(&mut self, "", ">")?; - Ok(path) + Ok(self.printer) } } impl fmt::Write for FmtPrinter { fn write_str(&mut self, s: &str) -> fmt::Result { + self.empty &= s.is_empty(); self.fmt.write_str(s) } } @@ -695,10 +773,10 @@ impl fmt::Write for FmtPrinter { impl Printer for FmtPrinter { type Error = fmt::Error; - type Path = PrettyPath; + type Path = Self; fn print_def_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, + mut self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, @@ -708,15 +786,20 @@ impl Printer for FmtPrinter { // both here and in `default_print_def_path`. let generics = substs.map(|_| self.tcx.generics_of(def_id)); if generics.as_ref().and_then(|g| g.parent).is_none() { - if let Some(path) = self.try_print_visible_def_path(def_id)? { - let path = if let (Some(generics), Some(substs)) = (generics, substs) { + let mut visible_path_success = false; + nest!(self, |cx| { + let (printer, success) = cx.try_print_visible_def_path(def_id)?; + visible_path_success = success; + Ok(printer) + }); + if visible_path_success { + return if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(path, params, substs, ns, projections)? + self.path_generic_args(|cx| Ok(cx.printer), params, substs, ns, projections) } else { - path + Ok(self.printer) }; - return Ok(path); } } @@ -736,9 +819,11 @@ impl Printer for FmtPrinter { // pretty printing some span information. This should // only occur very early in the compiler pipeline. let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let path = self.print_def_path(parent_def_id, None, ns, iter::empty())?; let span = self.tcx.def_span(def_id); - return self.path_append(path, &format!("", span)); + return self.path_append( + |cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()), + &format!("", span), + ); } } @@ -746,7 +831,7 @@ impl Printer for FmtPrinter { } fn path_crate( - self: &mut PrintCx<'_, '_, '_, Self>, + mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { if cnum == LOCAL_CRATE { @@ -754,51 +839,83 @@ impl Printer for FmtPrinter { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { write!(self.printer, "{}", keywords::Crate.name())?; - return Ok(PrettyPath { empty: false }); } } - Ok(PrettyPath { empty: true }) + Ok(self.printer) } else { write!(self.printer, "{}", self.tcx.crate_name(cnum))?; - Ok(PrettyPath { empty: false }) + Ok(self.printer) } } fn path_qualified( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_prefix: Option, + self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, ) -> Result { - self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns) + self.pretty_path_qualified(self_ty, trait_ref, ns) } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - path: Self::Path, + + fn path_append_impl<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.pretty_path_append_impl(print_prefix, self_ty, trait_ref) + } + fn path_append<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, text: &str, ) -> Result { - // FIXME(eddyb) this shouldn't happen, but is currently - // the case for `extern { ... }` "foreign modules". - if text.is_empty() { - return Ok(path); - } + let mut printer = print_prefix(self)?; - if !path.empty { - write!(self.printer, "::")?; + // FIXME(eddyb) `text` should never be empty, but it + // currently is for `extern { ... }` "foreign modules". + if !text.is_empty() { + if !printer.empty { + write!(printer, "::")?; + } + write!(printer, "{}", text)?; } - write!(self.printer, "{}", text)?; - Ok(PrettyPath { empty: false }) + + Ok(printer) } - fn path_generic_args( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - path: Self::Path, + fn path_generic_args<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, ) -> Result { - self.pretty_path_generic_args(path, params, substs, ns, projections) + self.pretty_path_generic_args(print_prefix, params, substs, ns, projections) } } -impl PrettyPrinter for FmtPrinter {} +impl PrettyPrinter for FmtPrinter { + fn nest<'a, 'gcx, 'tcx, E>( + mut self: PrintCx<'a, 'gcx, 'tcx, Self>, + f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result, + ) -> Result, E> { + let was_empty = std::mem::replace(&mut self.printer.empty, true); + let mut printer = f(PrintCx { + tcx: self.tcx, + printer: self.printer, + config: self.config, + })?; + printer.empty &= was_empty; + Ok(PrintCx { + tcx: self.tcx, + printer, + config: self.config, + }) + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c4ccef443122f..0dc897df3f3ec 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -161,8 +161,9 @@ impl RegionHighlightMode { macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { - $with(&cx.tcx.lift(self).expect("could not lift for printing"), &mut cx) + PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { + $with(&cx.tcx.lift(self).expect("could not lift for printing"), cx)?; + Ok(()) }) } }; @@ -193,27 +194,35 @@ macro_rules! gen_display_debug { macro_rules! gen_print_impl { ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target { - type Output = (); + type Output = P; type Error = fmt::Error; - fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { - Ok({ + fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + #[allow(unused_mut)] + let mut $cx = $cx; + let _: () = { define_scoped_cx!($cx); + if $cx.config.is_debug $dbg else $disp - }) + }; + Ok($cx.printer) } } }; ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { impl Print<'tcx, P> for $target { - type Output = (); + type Output = P; type Error = fmt::Error; - fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { - Ok({ + fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + #[allow(unused_mut)] + let mut $cx = $cx; + let _: () = { define_scoped_cx!($cx); + if $cx.config.is_debug $dbg else $disp - }) + }; + Ok($cx.printer) } } }; @@ -251,18 +260,23 @@ macro_rules! define_print_multi { $(define_print! { $generic $target, $vars $def })* }; } +macro_rules! nest { + ($closure:expr) => { + scoped_cx!() = scoped_cx!().nest($closure)? + } +} macro_rules! print_inner { (write ($($data:expr),+)) => { - write!(scoped_cx!().printer, $($data),+) + write!(scoped_cx!().printer, $($data),+)? }; ($kind:ident ($data:expr)) => { - $data.$kind(scoped_cx!()) + nest!(|cx| $data.$kind(cx)) }; } macro_rules! p { ($($kind:ident $data:tt),+) => { { - $(print_inner!($kind $data)?);+ + $(print_inner!($kind $data));+ } }; } @@ -277,11 +291,11 @@ macro_rules! define_scoped_cx { impl PrintCx<'a, 'gcx, 'tcx, P> { fn fn_sig( - &mut self, + mut self, inputs: &[Ty<'tcx>], variadic: bool, output: Ty<'tcx>, - ) -> fmt::Result { + ) -> Result { define_scoped_cx!(self); p!(write("(")); @@ -300,11 +314,11 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { p!(write(" -> "), print_display(output)); } - Ok(()) + Ok(self.printer) } - fn in_binder(&mut self, value: &ty::Binder) -> Result - where T: Print<'tcx, P, Error = fmt::Error> + TypeFoldable<'tcx> + fn in_binder(mut self, value: &ty::Binder) -> Result + where T: Print<'tcx, P, Output = P, Error = fmt::Error> + TypeFoldable<'tcx> { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -341,7 +355,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { let old_region_index = self.config.region_index; let mut region_index = old_region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { - let _ = start_or_continue(self, "for<", ", "); + let _ = start_or_continue(&mut self, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { let _ = write!(self.printer, "{}", name); @@ -363,12 +377,16 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { }; self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) }).0; - start_or_continue(self, "", "> ")?; + start_or_continue(&mut self, "", "> ")?; // Push current state to gcx, and restore after writing new_value. self.config.binder_depth += 1; self.config.region_index = region_index; - let result = new_value.print_display(self); + let result = new_value.print_display(PrintCx { + tcx: self.tcx, + printer: self.printer, + config: self.config, + }); self.config.region_index = old_region_index; self.config.binder_depth -= 1; result @@ -388,9 +406,9 @@ pub fn parameterized( substs: &Substs<'_>, ns: Namespace, ) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - let _ = cx.print_def_path(did, Some(substs), ns, iter::empty())?; + cx.print_def_path(did, Some(substs), ns, iter::empty())?; Ok(()) }) } @@ -410,13 +428,13 @@ define_print! { if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( principal.def_id, None, Namespace::TypeNS, iter::empty(), - )?; - cx.fn_sig(args, false, proj.ty)?; + )); + nest!(|cx| cx.fn_sig(args, false, proj.ty)); resugared_principal = true; } } @@ -426,12 +444,12 @@ define_print! { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); let principal = principal.with_self_ty(cx.tcx, dummy_self); - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( principal.def_id, Some(principal.substs), Namespace::TypeNS, self.projection_bounds(), - )?; + )); } first = false; } @@ -458,12 +476,12 @@ define_print! { } first = false; - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( def_id, None, Namespace::TypeNS, iter::empty(), - )?; + )); } } } @@ -485,8 +503,8 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { - let _ = cx.print_def_path( + PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { + cx.print_def_path( self.def_id, None, Namespace::TypeNS, @@ -499,8 +517,8 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { - let _ = cx.print_def_path( + PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { + cx.print_def_path( self.did, None, Namespace::TypeNS, @@ -521,7 +539,7 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter { fmt: f }, |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter::new(f), |mut cx| { define_scoped_cx!(cx); p!(write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, @@ -570,9 +588,10 @@ define_print! { display { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - p!(print_display(ty::Binder::bind(*self) + let trait_ref = *ty::Binder::bind(*self) .with_self_ty(cx.tcx, dummy_self) - .skip_binder())) + .skip_binder(); + p!(print_display(trait_ref)) } debug { p!(print_display(self)) @@ -598,7 +617,7 @@ define_print! { if let BrNamed(_, name) = *self { if name != "" && name != "'_" { p!(write("{}", name)); - return Ok(()); + return Ok(cx.printer); } } @@ -627,7 +646,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::BoundRegion { - fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { if cx.config.is_verbose { return true; } @@ -670,7 +689,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::PlaceholderRegion { - fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { if cx.config.is_verbose { return true; } @@ -694,7 +713,7 @@ define_print! { // Watch out for region highlights. if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { p!(write("'{:?}", n)); - return Ok(()); + return Ok(cx.printer); } // These printouts are concise. They do not contain all the information @@ -797,7 +816,7 @@ define_print! { // NB: this must be kept in sync with the printing logic above. impl ty::RegionKind { // HACK(eddyb) `pub(crate)` only for `ty::print`. - pub(crate) fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { + pub(crate) fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { if cx.config.is_verbose { return true; } @@ -866,7 +885,7 @@ define_print! { } p!(write("fn")); - cx.fn_sig(self.inputs(), self.variadic, self.output())? + nest!(|cx| cx.fn_sig(self.inputs(), self.variadic, self.output())); } debug { p!(write("({:?}; variadic: {})->{:?}", @@ -922,7 +941,7 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::RegionVid { - fn display_outputs_anything

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { if cx.config.is_verbose { return true; } @@ -1004,7 +1023,7 @@ define_print_multi! { ] (self, cx) { display { - cx.in_binder(self)? + nest!(|cx| cx.in_binder(self)) } } } @@ -1012,15 +1031,15 @@ define_print_multi! { define_print! { ('tcx) ty::TraitRef<'tcx>, (self, cx) { display { - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( self.def_id, Some(self.substs), Namespace::TypeNS, iter::empty(), - )?; + )); } debug { - let _ = cx.path_qualified(None, self.self_ty(), Some(*self), Namespace::TypeNS)?; + nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self), Namespace::TypeNS)); } } } @@ -1043,7 +1062,7 @@ define_print! { } Ref(r, ty, mutbl) => { p!(write("&")); - if r.display_outputs_anything(cx) { + if r.display_outputs_anything(&cx) { p!(print_display(r), write(" ")); } p!(print(ty::TypeAndMut { ty, mutbl })) @@ -1066,12 +1085,12 @@ define_print! { FnDef(def_id, substs) => { let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); p!(print(sig), write(" {{")); - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( def_id, Some(substs), Namespace::ValueNS, iter::empty(), - )?; + )); p!(write("}}")) } FnPtr(ref bare_fn) => { @@ -1094,15 +1113,15 @@ define_print! { } } Adt(def, substs) => { - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( def.did, Some(substs), Namespace::TypeNS, iter::empty(), - )?; + )); } Dynamic(data, r) => { - let print_r = r.display_outputs_anything(cx); + let print_r = r.display_outputs_anything(&cx); if print_r { p!(write("(")); } @@ -1112,18 +1131,16 @@ define_print! { } } Foreign(def_id) => { - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( def_id, None, Namespace::TypeNS, iter::empty(), - )?; + )); } Projection(ref data) => p!(print(data)), UnnormalizedProjection(ref data) => { - p!(write("Unnormalized(")); - data.print(cx)?; - p!(write(")")) + p!(write("Unnormalized("), print(data), write(")")) } Placeholder(placeholder) => { p!(write("Placeholder({:?})", placeholder)) @@ -1131,7 +1148,7 @@ define_print! { Opaque(def_id, substs) => { if cx.config.is_verbose { p!(write("Opaque({:?}, {:?})", def_id, substs)); - return Ok(()); + return Ok(cx.printer); } let def_key = cx.tcx.def_key(def_id); @@ -1147,7 +1164,7 @@ define_print! { } p!(write(">")); } - return Ok(()); + return Ok(cx.printer); } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. @@ -1190,17 +1207,19 @@ define_print! { if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { p!(write("@{:?}", cx.tcx.hir().span(node_id))); let mut sep = " "; - cx.tcx.with_freevars(node_id, |freevars| { - for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - p!( - write("{}{}:", - sep, - cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty)); - sep = ", "; - } - Ok(()) - })? + for (freevar, upvar_ty) in cx.tcx.freevars(did) + .as_ref() + .map_or(&[][..], |fv| &fv[..]) + .iter() + .zip(upvar_tys) + { + p!( + write("{}{}:", + sep, + cx.tcx.hir().name(freevar.var_id())), + print(upvar_ty)); + sep = ", "; + } } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. @@ -1217,7 +1236,7 @@ define_print! { p!(write(" "), print(witness), write("]")) }, GeneratorWitness(types) => { - cx.in_binder(&types)? + nest!(|cx| cx.in_binder(&types)) } Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); @@ -1231,17 +1250,19 @@ define_print! { p!(write("@{:?}", cx.tcx.hir().span(node_id))); } let mut sep = " "; - cx.tcx.with_freevars(node_id, |freevars| { - for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - p!( - write("{}{}:", - sep, - cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty)); - sep = ", "; - } - Ok(()) - })? + for (freevar, upvar_ty) in cx.tcx.freevars(did) + .as_ref() + .map_or(&[][..], |fv| &fv[..]) + .iter() + .zip(upvar_tys) + { + p!( + write("{}{}:", + sep, + cx.tcx.hir().name(freevar.var_id())), + print(upvar_ty)); + sep = ", "; + } } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. @@ -1343,12 +1364,12 @@ define_print! { define_print! { ('tcx) ty::ProjectionTy<'tcx>, (self, cx) { display { - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( self.item_def_id, Some(self.substs), Namespace::TypeNS, iter::empty(), - )?; + )); } } } @@ -1377,32 +1398,32 @@ define_print! { ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("the trait `")); - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( trait_def_id, None, Namespace::TypeNS, iter::empty(), - )?; + )); p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { p!(write("the closure `")); - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( closure_def_id, None, Namespace::ValueNS, iter::empty(), - )?; + )); p!(write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { p!(write("the constant `")); - let _ = cx.print_def_path( + nest!(|cx| cx.print_def_path( def_id, Some(substs), Namespace::ValueNS, iter::empty(), - )?; + )); p!(write("` can be evaluated")) } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index d5cc3807524c2..35914259ae3dd 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -93,7 +93,7 @@ use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::print::{PrettyPath, PrettyPrinter, PrintCx, Printer}; +use rustc::ty::print::{PrettyPrinter, PrintCx, Printer}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -223,9 +223,10 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - PrintCx::with(tcx, SymbolPath::new(), |mut cx| { - let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); - cx.printer.into_interned() + PrintCx::with(tcx, SymbolPath::new(), |cx| { + cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()) + .unwrap() + .into_interned() }) } @@ -345,7 +346,7 @@ struct SymbolPath { result: String, temp_buf: String, - // When `true`, `finalize_pending_component` is a noop. + // When `true`, `finalize_pending_component` isn't used. // This is needed when recursing into `path_qualified`, // or `path_generic_args`, as any nested paths are // logically within one component. @@ -408,18 +409,17 @@ impl fmt::Write for SymbolPath { impl Printer for SymbolPath { type Error = fmt::Error; - type Path = PrettyPath; + type Path = Self; fn path_crate( - self: &mut PrintCx<'_, '_, '_, Self>, + mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?; - Ok(PrettyPath { empty: false }) + Ok(self.printer) } fn path_qualified( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_prefix: Option, + mut self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, @@ -430,64 +430,85 @@ impl Printer for SymbolPath { ty::Adt(..) | ty::Foreign(_) | ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) - if impl_prefix.is_none() && trait_ref.is_none() => + if trait_ref.is_none() => { - return self.pretty_path_qualified(None, self_ty, trait_ref, ns); + return self.pretty_path_qualified(self_ty, trait_ref, ns); } _ => {} } - // HACK(eddyb) make sure to finalize the last component of the - // `impl` prefix, to avoid it fusing with the following text. - let impl_prefix = match impl_prefix { - Some(prefix) => { - let mut prefix = self.path_append(prefix, "")?; - - // HACK(eddyb) also avoid an unnecessary `::`. - prefix.empty = true; - - Some(prefix) - } - None => None, - }; - let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); - let r = self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns); - self.printer.keep_within_component = kept_within_component; - r + let mut path = self.pretty_path_qualified(self_ty, trait_ref, ns)?; + path.keep_within_component = kept_within_component; + Ok(path) + } + + fn path_append_impl<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + let kept_within_component = self.printer.keep_within_component; + let mut path = self.pretty_path_append_impl( + |cx| { + let mut path = print_prefix(cx)?; + path.keep_within_component = true; + Ok(path) + }, + self_ty, + trait_ref, + )?; + path.keep_within_component = kept_within_component; + Ok(path) } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, + fn path_append<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, text: &str, ) -> Result { - if self.keep_within_component { + let keep_within_component = self.printer.keep_within_component; + + let mut path = print_prefix(self)?; + + if keep_within_component { // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. - if !path.empty { - self.printer.write_str("::")?; - } else { - path.empty = text.is_empty(); - } + path.write_str("::")?; } else { - self.printer.finalize_pending_component(); - path.empty = false; + path.finalize_pending_component(); } - self.printer.write_str(text)?; + path.write_str(text)?; Ok(path) } - fn path_generic_args( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - path: Self::Path, + fn path_generic_args<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, ns: Namespace, projections: impl Iterator>, ) -> Result { - let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); - let r = self.pretty_path_generic_args(path, params, substs, ns, projections); - self.printer.keep_within_component = kept_within_component; - r + let kept_within_component = self.printer.keep_within_component; + let mut path = self.pretty_path_generic_args( + |cx| { + let mut path = print_prefix(cx)?; + path.keep_within_component = true; + Ok(path) + }, + params, + substs, + ns, + projections, + )?; + path.keep_within_component = kept_within_component; + Ok(path) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7caa54e1a26c5..3289833365045 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4055,50 +4055,70 @@ where F: Fn(DefId) -> Def { type Path = Vec; fn path_crate( - self: &mut PrintCx<'_, '_, '_, Self>, + self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) } fn path_qualified( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_prefix: Option, + self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, _ns: Namespace, ) -> Result { - let mut path = impl_prefix.unwrap_or(vec![]); + // This shouldn't ever be needed, but just in case: + Ok(vec![match trait_ref { + Some(trait_ref) => format!("{:?}", trait_ref), + None => format!("<{}>", self_ty), + }]) + } + + fn path_append_impl<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + let mut path = print_prefix(self)?; // This shouldn't ever be needed, but just in case: - if let Some(trait_ref) = trait_ref { - path.push(format!("{:?}", trait_ref)); - } else { - path.push(format!("<{}>", self_ty)); - } + path.push(match trait_ref { + Some(trait_ref) => { + format!("", trait_ref, self_ty) + } + None => format!("", self_ty), + }); Ok(path) } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, + fn path_append<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, text: &str, ) -> Result { + let mut path = print_prefix(self)?; path.push(text.to_string()); Ok(path) } - fn path_generic_args( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - path: Self::Path, + fn path_generic_args<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, _params: &[ty::GenericParamDef], _substs: &'tcx Substs<'tcx>, _ns: Namespace, _projections: impl Iterator>, ) -> Result { - Ok(path) + print_prefix(self) } } - let names = PrintCx::with(tcx, AbsolutePathPrinter, |mut cx| { + let names = PrintCx::with(tcx, AbsolutePathPrinter, |cx| { cx.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()).unwrap() }); From 400b50d4b46da5eec18458d672ecbd593c153ae3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 11 Jan 2019 13:07:01 +0200 Subject: [PATCH 41/68] rustc: don't keep RegionHighlightMode in a thread-local. --- .../infer/error_reporting/need_type_info.rs | 25 ++- .../nice_region_error/placeholder_error.rs | 112 +++++----- src/librustc/ty/print.rs | 107 ++++++++++ src/librustc/util/ppaux.rs | 194 +++--------------- .../borrow_check/error_reporting.rs | 72 ++++--- .../error_reporting/region_name.rs | 14 +- 6 files changed, 267 insertions(+), 257 deletions(-) diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 8ee367c87c3ea..b5ecd7f89249f 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -3,6 +3,7 @@ use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::InferCtxt; use infer::type_variable::TypeVariableOrigin; use ty::{self, Ty, Infer, TyVar}; +use ty::print::Print; use syntax::source_map::CompilerDesugaringKind; use syntax_pos::Span; use errors::DiagnosticBuilder; @@ -64,18 +65,28 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for FindLocalByTypeVisitor<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { + pub fn extract_type_name( + &self, + ty: &'a Ty<'tcx>, + highlight: Option, + ) -> String { if let ty::Infer(ty::TyVar(ty_vid)) = (*ty).sty { let ty_vars = self.type_variables.borrow(); if let TypeVariableOrigin::TypeParameterDefinition(_, name) = *ty_vars.var_origin(ty_vid) { - name.to_string() - } else { - ty.to_string() + return name.to_string(); } - } else { - ty.to_string() } + + let mut s = String::new(); + let mut printer = ty::print::FmtPrinter::new(&mut s); + if let Some(highlight) = highlight { + printer.region_highlight_mode = highlight; + } + let _ = ty::print::PrintCx::with(self.tcx, printer, |cx| { + ty.print(cx) + }); + s } pub fn need_type_info_err(&self, @@ -84,7 +95,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty: Ty<'tcx>) -> DiagnosticBuilder<'gcx> { let ty = self.resolve_type_vars_if_possible(&ty); - let name = self.extract_type_name(&ty); + let name = self.extract_type_name(&ty, None); let mut err_span = span; let mut labels = vec![( diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index e534ae3b29a38..1b2fb22ce6ba4 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -7,8 +7,10 @@ use traits::{ObligationCause, ObligationCauseCode}; use ty; use ty::error::ExpectedFound; use ty::subst::Substs; +use ty::print::{Print, PrettyPrinter}; use util::common::ErrorReported; -use util::ppaux::RegionHighlightMode; + +use std::fmt::Write; impl NiceRegionError<'me, 'gcx, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and @@ -241,65 +243,63 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { .tcx .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid); - RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || { - RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || { - match (has_sub, has_sup) { - (Some(n1), Some(n2)) => { - err.note(&format!( - "`{}` must implement `{}` \ - for any two lifetimes `'{}` and `'{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - std::cmp::min(n1, n2), - std::cmp::max(n1, n2), - )); - } - (Some(n), _) | (_, Some(n)) => { - err.note(&format!( - "`{}` must implement `{}` \ - for any lifetime `'{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - n, - )); - } - (None, None) => { - err.note(&format!( - "`{}` must implement `{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - )); - } - } - }) - }); + { + let mut note = String::new(); + let mut printer = ty::print::FmtPrinter::new(&mut note); + printer.region_highlight_mode.maybe_highlighting_region(sub_placeholder, has_sub); + printer.region_highlight_mode.maybe_highlighting_region(sup_placeholder, has_sup); + + let _ = ty::print::PrintCx::with(self.tcx, printer, |mut cx| { + write!(cx.printer, "`")?; + cx = cx.nest(|cx| expected_trait_ref.self_ty().print(cx))?; + write!(cx.printer, "` must implement `")?; + cx = cx.nest(|cx| expected_trait_ref.print(cx))?; + write!(cx.printer, "`") + }); - RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid { - Some(n) => { - if self_ty_has_vid { - err.note(&format!( - "but `{}` only implements `{}` for the lifetime `'{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - n - )); - } else { - err.note(&format!( - "but `{}` only implements `{}` for some lifetime `'{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - n - )); + match (has_sub, has_sup) { + (Some(n1), Some(n2)) => { + let _ = write!(note, + " for any two lifetimes `'{}` and `'{}`", + std::cmp::min(n1, n2), + std::cmp::max(n1, n2), + ); } + (Some(n), _) | (_, Some(n)) => { + let _ = write!(note, + " for any lifetime `'{}`", + n, + ); + } + (None, None) => {} } - None => { - err.note(&format!( - "but `{}` only implements `{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - )); + + err.note(¬e); + } + + { + let mut note = String::new(); + let mut printer = ty::print::FmtPrinter::new(&mut note); + printer.region_highlight_mode.maybe_highlighting_region(vid, has_vid); + + let _ = ty::print::PrintCx::with(self.tcx, printer, |mut cx| { + write!(cx.printer, "but `")?; + cx = cx.nest(|cx| actual_trait_ref.self_ty().print(cx))?; + write!(cx.printer, "` only implements `")?; + cx = cx.nest(|cx| actual_trait_ref.print(cx))?; + write!(cx.printer, "`") + }); + + if let Some(n) = has_vid { + let _ = write!(note, + " for {} lifetime `'{}`", + if self_ty_has_vid { "the" } else { "some" }, + n + ); } - }); + + err.note(¬e); + } err.emit(); ErrorReported diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index b7713249d2133..5ab5f24945617 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -48,6 +48,103 @@ pub fn with_crate_prefix R, R>(f: F) -> R { // FIXME(eddyb) this module uses `pub(crate)` for things used only // from `ppaux` - when that is removed, they can be re-privatized. +/// The "region highlights" are used to control region printing during +/// specific error messages. When a "region highlight" is enabled, it +/// gives an alternate way to print specific regions. For now, we +/// always print those regions using a number, so something like `'0`. +/// +/// Regions not selected by the region highlight mode are presently +/// unaffected. +#[derive(Copy, Clone, Default)] +pub struct RegionHighlightMode { + /// If enabled, when we see the selected region, use `"'N"` + /// instead of the ordinary behavior. + highlight_regions: [Option<(ty::RegionKind, usize)>; 3], + + /// If enabled, when printing a "free region" that originated from + /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily + /// have names print as normal. + /// + /// This is used when you have a signature like `fn foo(x: &u32, + /// y: &'a u32)` and we want to give a name to the region of the + /// reference `x`. + pub(crate) highlight_bound_region: Option<(ty::BoundRegion, usize)>, +} + +impl RegionHighlightMode { + /// If `region` and `number` are both `Some`, invoke + /// `highlighting_region`. + pub fn maybe_highlighting_region( + &mut self, + region: Option>, + number: Option, + ) { + if let Some(k) = region { + if let Some(n) = number { + self.highlighting_region(k, n); + } + } + } + + /// Highlight the region inference variable `vid` as `'N`. + pub fn highlighting_region( + &mut self, + region: ty::Region<'_>, + number: usize, + ) { + let num_slots = self.highlight_regions.len(); + let first_avail_slot = self.highlight_regions.iter_mut() + .filter(|s| s.is_none()) + .next() + .unwrap_or_else(|| { + bug!( + "can only highlight {} placeholders at a time", + num_slots, + ) + }); + *first_avail_slot = Some((*region, number)); + } + + /// Convenience wrapper for `highlighting_region` + pub fn highlighting_region_vid( + &mut self, + vid: ty::RegionVid, + number: usize, + ) { + self.highlighting_region(&ty::ReVar(vid), number) + } + + /// Returns `Some(n)` with the number to use for the given region, + /// if any. + pub(crate) fn region_highlighted(&self, region: ty::Region<'_>) -> Option { + self + .highlight_regions + .iter() + .filter_map(|h| match h { + Some((r, n)) if r == region => Some(*n), + _ => None, + }) + .next() + } + + /// Highlight the given bound region. + /// We can only highlight one bound region at a time. See + /// the field `highlight_bound_region` for more detailed notes. + pub fn highlighting_bound_region( + &mut self, + br: ty::BoundRegion, + number: usize, + ) { + assert!(self.highlight_bound_region.is_none()); + self.highlight_bound_region = Some((br, number)); + } + + /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. + pub(crate) fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option { + self.region_highlighted(&ty::RePlaceholder(p)) + } +} + struct LateBoundRegionNameCollector(FxHashSet); impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { @@ -238,6 +335,10 @@ pub trait PrettyPrinter: Printer + fmt::Write { config: self.config, }) } + + fn region_highlight_mode(&self) -> RegionHighlightMode { + RegionHighlightMode::default() + } } macro_rules! nest { @@ -450,6 +551,7 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { pub struct FmtPrinter { pub(crate) fmt: F, empty: bool, + pub region_highlight_mode: RegionHighlightMode, } impl FmtPrinter { @@ -457,6 +559,7 @@ impl FmtPrinter { FmtPrinter { fmt, empty: true, + region_highlight_mode: RegionHighlightMode::default(), } } } @@ -918,4 +1021,8 @@ impl PrettyPrinter for FmtPrinter { config: self.config, }) } + + fn region_highlight_mode(&self) -> RegionHighlightMode { + self.region_highlight_mode + } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 0dc897df3f3ec..a93d07816ce0d 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -11,7 +11,6 @@ use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TypeFoldable}; use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; -use std::cell::Cell; use std::fmt::{self, Write as _}; use std::iter; use std::usize; @@ -21,143 +20,6 @@ use syntax::ast::CRATE_NODE_ID; use syntax::symbol::{Symbol, InternedString}; use hir; -/// The "region highlights" are used to control region printing during -/// specific error messages. When a "region highlight" is enabled, it -/// gives an alternate way to print specific regions. For now, we -/// always print those regions using a number, so something like `'0`. -/// -/// Regions not selected by the region highlight mode are presently -/// unaffected. -#[derive(Copy, Clone, Default)] -pub struct RegionHighlightMode { - /// If enabled, when we see the selected region, use `"'N"` - /// instead of the ordinary behavior. - highlight_regions: [Option<(ty::RegionKind, usize)>; 3], - - /// If enabled, when printing a "free region" that originated from - /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily - /// have names print as normal. - /// - /// This is used when you have a signature like `fn foo(x: &u32, - /// y: &'a u32)` and we want to give a name to the region of the - /// reference `x`. - highlight_bound_region: Option<(ty::BoundRegion, usize)>, -} - -thread_local! { - /// Mechanism for highlighting of specific regions for display in NLL region inference errors. - /// Contains region to highlight and counter for number to use when highlighting. - static REGION_HIGHLIGHT_MODE: Cell = - Cell::new(RegionHighlightMode::default()) -} - -impl RegionHighlightMode { - /// Read and return current region highlight settings (accesses thread-local state).a - pub fn get() -> Self { - REGION_HIGHLIGHT_MODE.with(|c| c.get()) - } - - /// Internal helper to update current settings during the execution of `op`. - fn set( - old_mode: Self, - new_mode: Self, - op: impl FnOnce() -> R, - ) -> R { - REGION_HIGHLIGHT_MODE.with(|c| { - c.set(new_mode); - let result = op(); - c.set(old_mode); - result - }) - } - - /// If `region` and `number` are both `Some`, invoke - /// `highlighting_region`. Otherwise, just invoke `op` directly. - pub fn maybe_highlighting_region( - region: Option>, - number: Option, - op: impl FnOnce() -> R, - ) -> R { - if let Some(k) = region { - if let Some(n) = number { - return Self::highlighting_region(k, n, op); - } - } - - op() - } - - /// During the execution of `op`, highlight the region inference - /// vairable `vid` as `'N`. We can only highlight one region vid - /// at a time. - pub fn highlighting_region( - region: ty::Region<'_>, - number: usize, - op: impl FnOnce() -> R, - ) -> R { - let old_mode = Self::get(); - let mut new_mode = old_mode; - let first_avail_slot = new_mode.highlight_regions.iter_mut() - .filter(|s| s.is_none()) - .next() - .unwrap_or_else(|| { - panic!( - "can only highlight {} placeholders at a time", - old_mode.highlight_regions.len(), - ) - }); - *first_avail_slot = Some((*region, number)); - Self::set(old_mode, new_mode, op) - } - - /// Convenience wrapper for `highlighting_region` - pub fn highlighting_region_vid( - vid: ty::RegionVid, - number: usize, - op: impl FnOnce() -> R, - ) -> R { - Self::highlighting_region(&ty::ReVar(vid), number, op) - } - - /// Returns `Some(n)` with the number to use for the given region, - /// if any. - fn region_highlighted(&self, region: ty::Region<'_>) -> Option { - Self::get() - .highlight_regions - .iter() - .filter_map(|h| match h { - Some((r, n)) if r == region => Some(*n), - _ => None, - }) - .next() - } - - /// During the execution of `op`, highlight the given bound - /// region. We can only highlight one bound region at a time. See - /// the field `highlight_bound_region` for more detailed notes. - pub fn highlighting_bound_region( - br: ty::BoundRegion, - number: usize, - op: impl FnOnce() -> R, - ) -> R { - let old_mode = Self::get(); - assert!(old_mode.highlight_bound_region.is_none()); - Self::set( - old_mode, - Self { - highlight_bound_region: Some((br, number)), - ..old_mode - }, - op, - ) - } - - /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. - pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option { - self.region_highlighted(&ty::RePlaceholder(p)) - } -} - macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -621,7 +483,7 @@ define_print! { } } - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if let Some((region, counter)) = highlight.highlight_bound_region { if *self == region { p!(write("'{}", counter)); @@ -646,7 +508,9 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::BoundRegion { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool + where P: PrettyPrinter + { if cx.config.is_verbose { return true; } @@ -657,7 +521,7 @@ impl ty::BoundRegion { } } - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if let Some((region, _)) = highlight.highlight_bound_region { if *self == region { return true; @@ -675,7 +539,7 @@ define_print! { return self.print_debug(cx); } - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if let Some(counter) = highlight.placeholder_highlight(*self) { p!(write("'{}", counter)); } else { @@ -689,12 +553,14 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::PlaceholderRegion { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool + where P: PrettyPrinter + { if cx.config.is_verbose { return true; } - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if highlight.placeholder_highlight(*self).is_some() { return true; } @@ -711,8 +577,8 @@ define_print! { } // Watch out for region highlights. - if let Some(n) = RegionHighlightMode::get().region_highlighted(self) { - p!(write("'{:?}", n)); + if let Some(n) = cx.printer.region_highlight_mode().region_highlighted(self) { + p!(write("'{}", n)); return Ok(cx.printer); } @@ -779,12 +645,12 @@ define_print! { } ty::ReLateBound(binder_id, ref bound_region) => { - p!(write("ReLateBound({:?}, {:?})", - binder_id, - bound_region)) + p!(write("ReLateBound({:?}, ", binder_id), + print_debug(bound_region), + write(")")) } - ty::ReFree(ref fr) => p!(write("{:?}", fr)), + ty::ReFree(ref fr) => p!(print_debug(fr)), ty::ReScope(id) => { p!(write("ReScope({:?})", id)) @@ -793,11 +659,11 @@ define_print! { ty::ReStatic => p!(write("ReStatic")), ty::ReVar(ref vid) => { - p!(write("{:?}", vid)) + p!(print_debug(vid)) } ty::RePlaceholder(placeholder) => { - p!(write("RePlaceholder({:?})", placeholder)) + p!(write("RePlaceholder("), print_debug(placeholder), write(")")) } ty::ReEmpty => p!(write("ReEmpty")), @@ -816,12 +682,14 @@ define_print! { // NB: this must be kept in sync with the printing logic above. impl ty::RegionKind { // HACK(eddyb) `pub(crate)` only for `ty::print`. - pub(crate) fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + pub(crate) fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool + where P: PrettyPrinter + { if cx.config.is_verbose { return true; } - if RegionHighlightMode::get().region_highlighted(self).is_some() { + if cx.printer.region_highlight_mode().region_highlighted(self).is_some() { return true; } @@ -919,17 +787,17 @@ define_print! { return self.print_debug(cx); } - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - p!(write("'{:?}", counter)); + p!(write("'{}", counter)); } } debug { // HACK(eddyb) this is duplicated from `display` printing, // to keep NLL borrowck working even with `-Zverbose`. - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - p!(write("'{:?}", counter)); + p!(write("'{}", counter)); } else { p!(write("'_#{}r", self.index())); } @@ -941,12 +809,14 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::RegionVid { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool { + fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool + where P: PrettyPrinter + { if cx.config.is_verbose { return true; } - let highlight = RegionHighlightMode::get(); + let highlight = cx.printer.region_highlight_mode(); if highlight.region_highlighted(&ty::ReVar(*self)).is_some() { return true; } @@ -1158,9 +1028,9 @@ define_print! { // FIXME(eddyb) print this with `print_def_path`. if let Some(first) = substs.next() { p!(write("::<")); - p!(write("{}", first)); + p!(print_display(first)); for subst in substs { - p!(write(", {}", subst)); + p!(write(", "), print_display(subst)); } p!(write(">")); } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a7e705039eb66..14821e5d41c9d 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -12,7 +12,7 @@ use rustc::mir::{ TerminatorKind, VarBindingForm, }; use rustc::ty::{self, DefIdTree}; -use rustc::util::ppaux::RegionHighlightMode; +use rustc::ty::print::Print; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::sync::Lrc; @@ -826,7 +826,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ); if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) { - let region_name = annotation.emit(&mut err); + let region_name = annotation.emit(self, &mut err); err.span_label( borrow_span, @@ -1860,7 +1860,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { fn annotate_argument_and_return_for_borrow( &self, borrow: &BorrowData<'tcx>, - ) -> Option { + ) -> Option> { // Define a fallback for when we can't match a closure. let fallback = || { let is_closure = self.infcx.tcx.is_closure(self.mir_def_id); @@ -2081,7 +2081,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &self, did: DefId, sig: ty::PolyFnSig<'tcx>, - ) -> Option { + ) -> Option> { debug!("annotate_fn_sig: did={:?} sig={:?}", did, sig); let is_closure = self.infcx.tcx.is_closure(did); let fn_node_id = self.infcx.tcx.hir().as_local_node_id(did)?; @@ -2227,7 +2227,11 @@ enum AnnotatedBorrowFnSignature<'tcx> { impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { /// Annotate the provided diagnostic with information about borrow from the fn signature that /// helps explain. - fn emit(&self, diag: &mut DiagnosticBuilder<'_>) -> String { + fn emit( + &self, + cx: &mut MirBorrowckCtxt<'_, '_, 'tcx>, + diag: &mut DiagnosticBuilder<'_>, + ) -> String { match self { AnnotatedBorrowFnSignature::Closure { argument_ty, @@ -2235,10 +2239,10 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { } => { diag.span_label( *argument_span, - format!("has type `{}`", self.get_name_for_ty(argument_ty, 0)), + format!("has type `{}`", cx.get_name_for_ty(argument_ty, 0)), ); - self.get_region_name_for_ty(argument_ty, 0) + cx.get_region_name_for_ty(argument_ty, 0) } AnnotatedBorrowFnSignature::AnonymousFunction { argument_ty, @@ -2246,10 +2250,10 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { return_ty, return_span, } => { - let argument_ty_name = self.get_name_for_ty(argument_ty, 0); + let argument_ty_name = cx.get_name_for_ty(argument_ty, 0); diag.span_label(*argument_span, format!("has type `{}`", argument_ty_name)); - let return_ty_name = self.get_name_for_ty(return_ty, 0); + let return_ty_name = cx.get_name_for_ty(return_ty, 0); let types_equal = return_ty_name == argument_ty_name; diag.span_label( *return_span, @@ -2268,7 +2272,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { lifetime-syntax.html#lifetime-elision>", ); - self.get_region_name_for_ty(return_ty, 0) + cx.get_region_name_for_ty(return_ty, 0) } AnnotatedBorrowFnSignature::NamedFunction { arguments, @@ -2276,7 +2280,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { return_span, } => { // Region of return type and arguments checked to be the same earlier. - let region_name = self.get_region_name_for_ty(return_ty, 0); + let region_name = cx.get_region_name_for_ty(return_ty, 0); for (_, argument_span) in arguments { diag.span_label(*argument_span, format!("has lifetime `{}`", region_name)); } @@ -2296,10 +2300,15 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { } } } +} +impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Return the name of the provided `Ty` (that must be a reference) with a synthesized lifetime /// name where required. fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { + let mut s = String::new(); + let mut printer = ty::print::FmtPrinter::new(&mut s); + // We need to add synthesized lifetimes where appropriate. We do // this by hooking into the pretty printer and telling it to label the // lifetimes without names with the value `'0`. @@ -2309,28 +2318,41 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }), _, _, - ) => RegionHighlightMode::highlighting_bound_region(*br, counter, || ty.to_string()), - _ => ty.to_string(), + ) => printer.region_highlight_mode.highlighting_bound_region(*br, counter), + _ => {} } + + let _ = ty::print::PrintCx::with(self.infcx.tcx, printer, |cx| { + ty.print(cx) + }); + s } /// Return the name of the provided `Ty` (that must be a reference)'s region with a /// synthesized lifetime name where required. fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { - match ty.sty { - ty::TyKind::Ref(region, _, _) => match region { - ty::RegionKind::ReLateBound(_, br) - | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { - RegionHighlightMode::highlighting_bound_region( - *br, - counter, - || region.to_string(), - ) + let mut s = String::new(); + let mut printer = ty::print::FmtPrinter::new(&mut s); + + let region = match ty.sty { + ty::TyKind::Ref(region, _, _) => { + match region { + ty::RegionKind::ReLateBound(_, br) + | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => { + printer.region_highlight_mode.highlighting_bound_region(*br, counter) + } + _ => {} } - _ => region.to_string(), - }, + + region + } _ => bug!("ty for annotation of borrow region is not a reference"), - } + }; + + let _ = ty::print::PrintCx::with(self.infcx.tcx, printer, |cx| { + region.print(cx) + }); + s } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs index bff8015511242..e743013b1aae1 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -8,7 +8,7 @@ use rustc::infer::InferCtxt; use rustc::mir::Mir; use rustc::ty::subst::{Substs, UnpackedKind}; use rustc::ty::{self, RegionKind, RegionVid, Ty, TyCtxt}; -use rustc::util::ppaux::RegionHighlightMode; +use rustc::ty::print::RegionHighlightMode; use rustc_errors::DiagnosticBuilder; use syntax::ast::{Name, DUMMY_NODE_ID}; use syntax::symbol::keywords; @@ -396,9 +396,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { argument_ty: Ty<'tcx>, counter: &mut usize, ) -> Option { - let type_name = RegionHighlightMode::highlighting_region_vid(needle_fr, *counter, || { - infcx.extract_type_name(&argument_ty) - }); + let mut highlight = RegionHighlightMode::default(); + highlight.highlighting_region_vid(needle_fr, *counter); + let type_name = infcx.extract_type_name(&argument_ty, Some(highlight)); debug!( "give_name_if_we_cannot_match_hir_ty: type_name={:?} needle_fr={:?}", @@ -673,9 +673,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { return None; } - let type_name = RegionHighlightMode::highlighting_region_vid( - fr, *counter, || infcx.extract_type_name(&return_ty), - ); + let mut highlight = RegionHighlightMode::default(); + highlight.highlighting_region_vid(fr, *counter); + let type_name = infcx.extract_type_name(&return_ty, Some(highlight)); let mir_node_id = tcx.hir().as_local_node_id(mir_def_id).expect("non-local mir"); From c80c4d3e98875baf65408172031fe68c36ec7cfc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 16:26:03 +0200 Subject: [PATCH 42/68] rustc: centralize region printing in ty::RegionKind's Print impl. --- src/librustc/infer/error_reporting/mod.rs | 7 +- src/librustc/ty/print.rs | 5 - src/librustc/util/ppaux.rs | 222 ++++++---------------- 3 files changed, 61 insertions(+), 173 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b299e4ab748bb..b6497d07e0ad6 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -224,7 +224,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.hir().span(node), ), _ => ( - format!("the lifetime {} as defined on", fr.bound_region), + format!("the lifetime {} as defined on", region), cm.def_span(self.hir().span(node)), ), }, @@ -1495,7 +1495,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { var_origin: RegionVariableOrigin, ) -> DiagnosticBuilder<'tcx> { let br_string = |br: ty::BoundRegion| { - let mut s = br.to_string(); + let mut s = match br { + ty::BrNamed(_, name) => name.to_string(), + _ => String::new(), + }; if !s.is_empty() { s.push_str(" "); } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 5ab5f24945617..127d66603547b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -138,11 +138,6 @@ impl RegionHighlightMode { assert!(self.highlight_bound_region.is_none()); self.highlight_bound_region = Some((br, number)); } - - /// Returns `Some(N)` if the placeholder `p` is highlighted to print as `'N`. - pub(crate) fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option { - self.region_highlighted(&ty::RePlaceholder(p)) - } } struct LateBoundRegionNameCollector(FxHashSet); diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a93d07816ce0d..847a05125a21b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -2,7 +2,6 @@ use hir::def::Namespace; use hir::def_id::DefId; use middle::region; use ty::subst::{Kind, Subst, Substs, UnpackedKind}; -use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; @@ -469,119 +468,34 @@ define_print! { } } -define_print! { - () ty::BoundRegion, (self, cx) { - display { - if cx.config.is_verbose { - return self.print_debug(cx); - } - - if let BrNamed(_, name) = *self { - if name != "" && name != "'_" { - p!(write("{}", name)); - return Ok(cx.printer); - } - } - - let highlight = cx.printer.region_highlight_mode(); - if let Some((region, counter)) = highlight.highlight_bound_region { - if *self == region { - p!(write("'{}", counter)); - } - } - } - debug { - match *self { - BrAnon(n) => p!(write("BrAnon({:?})", n)), - BrFresh(n) => p!(write("BrFresh({:?})", n)), - BrNamed(did, name) => { - p!(write("BrNamed({:?}:{:?}, {})", - did.krate, did.index, name)) - } - BrEnv => p!(write("BrEnv")), - } - } - } -} - -// HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`) -// -// NB: this must be kept in sync with the printing logic above. -impl ty::BoundRegion { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool - where P: PrettyPrinter - { - if cx.config.is_verbose { - return true; - } - - if let BrNamed(_, name) = *self { - if name != "" && name != "'_" { - return true; - } - } - - let highlight = cx.printer.region_highlight_mode(); - if let Some((region, _)) = highlight.highlight_bound_region { - if *self == region { - return true; +impl fmt::Debug for ty::BoundRegion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), + ty::BrFresh(n) => write!(f, "BrFresh({:?})", n), + ty::BrNamed(did, name) => { + write!(f, "BrNamed({:?}:{:?}, {})", + did.krate, did.index, name) } + ty::BrEnv => write!(f, "BrEnv"), } - - false } } define_print! { - () ty::PlaceholderRegion, (self, cx) { + () ty::RegionKind, (self, cx) { display { - if cx.config.is_verbose { - return self.print_debug(cx); - } - + // Watch out for region highlights. let highlight = cx.printer.region_highlight_mode(); - if let Some(counter) = highlight.placeholder_highlight(*self) { - p!(write("'{}", counter)); - } else { - p!(print_display(self.name)); + if let Some(n) = highlight.region_highlighted(self) { + p!(write("'{}", n)); + return Ok(cx.printer); } - } - } -} - -// HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`) -// -// NB: this must be kept in sync with the printing logic above. -impl ty::PlaceholderRegion { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool - where P: PrettyPrinter - { - if cx.config.is_verbose { - return true; - } - - let highlight = cx.printer.region_highlight_mode(); - if highlight.placeholder_highlight(*self).is_some() { - return true; - } - self.name.display_outputs_anything(cx) - } -} - -define_print! { - () ty::RegionKind, (self, cx) { - display { if cx.config.is_verbose { return self.print_debug(cx); } - // Watch out for region highlights. - if let Some(n) = cx.printer.region_highlight_mode().region_highlighted(self) { - p!(write("'{}", n)); - return Ok(cx.printer); - } - // These printouts are concise. They do not contain all the information // the user might want to diagnose an error, but there is basically no way // to fit that into a short string. Hence the recommendation to use @@ -593,11 +507,20 @@ define_print! { } } ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { - p!(print_display(br)) - } - ty::RePlaceholder(p) => { - p!(print_display(p)) + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + p!(write("{}", name)); + return Ok(cx.printer); + } + } + + if let Some((region, counter)) = highlight.highlight_bound_region { + if br == region { + p!(write("'{}", counter)); + } + } } ty::ReScope(scope) if cx.config.identify_regions => { match scope.data { @@ -617,11 +540,9 @@ define_print! { } } ty::ReVar(region_vid) if cx.config.identify_regions => { - p!(print_debug(region_vid)) - } - ty::ReVar(region_vid) => { - p!(print_display(region_vid)) + p!(write("{:?}", region_vid)); } + ty::ReVar(_) => {} ty::ReScope(_) | ty::ReErased => {} ty::ReStatic => p!(write("'static")), @@ -640,14 +561,11 @@ define_print! { } ty::ReClosureBound(ref vid) => { - p!(write("ReClosureBound({:?})", - vid)) + p!(write("ReClosureBound({:?})", vid)) } ty::ReLateBound(binder_id, ref bound_region) => { - p!(write("ReLateBound({:?}, ", binder_id), - print_debug(bound_region), - write(")")) + p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region)) } ty::ReFree(ref fr) => p!(print_debug(fr)), @@ -659,11 +577,11 @@ define_print! { ty::ReStatic => p!(write("ReStatic")), ty::ReVar(ref vid) => { - p!(print_debug(vid)) + p!(write("{:?}", vid)); } ty::RePlaceholder(placeholder) => { - p!(write("RePlaceholder("), print_debug(placeholder), write(")")) + p!(write("RePlaceholder({:?})", placeholder)) } ty::ReEmpty => p!(write("ReEmpty")), @@ -685,11 +603,12 @@ impl ty::RegionKind { pub(crate) fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool where P: PrettyPrinter { - if cx.config.is_verbose { + let highlight = cx.printer.region_highlight_mode(); + if highlight.region_highlighted(self).is_some() { return true; } - if cx.printer.region_highlight_mode().region_highlighted(self).is_some() { + if cx.config.is_verbose { return true; } @@ -699,17 +618,27 @@ impl ty::RegionKind { } ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) => { - br.display_outputs_anything(cx) - } + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + return true; + } + } - ty::RePlaceholder(p) => p.display_outputs_anything(cx), + if let Some((region, _)) = highlight.highlight_bound_region { + if br == region { + return true; + } + } + + false + } ty::ReScope(_) | ty::ReVar(_) if cx.config.identify_regions => true, - ty::ReVar(region_vid) => region_vid.display_outputs_anything(cx), - + ty::ReVar(_) | ty::ReScope(_) | ty::ReErased => false, @@ -780,48 +709,9 @@ impl fmt::Debug for ty::FloatVid { } } -define_print! { - () ty::RegionVid, (self, cx) { - display { - if cx.config.is_verbose { - return self.print_debug(cx); - } - - let highlight = cx.printer.region_highlight_mode(); - if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - p!(write("'{}", counter)); - } - } - debug { - // HACK(eddyb) this is duplicated from `display` printing, - // to keep NLL borrowck working even with `-Zverbose`. - let highlight = cx.printer.region_highlight_mode(); - if let Some(counter) = highlight.region_highlighted(&ty::ReVar(*self)) { - p!(write("'{}", counter)); - } else { - p!(write("'_#{}r", self.index())); - } - } - } -} - -// HACK(eddyb) (see `ty::RegionKind::display_outputs_anything`) -// -// NB: this must be kept in sync with the printing logic above. -impl ty::RegionVid { - fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool - where P: PrettyPrinter - { - if cx.config.is_verbose { - return true; - } - - let highlight = cx.printer.region_highlight_mode(); - if highlight.region_highlighted(&ty::ReVar(*self)).is_some() { - return true; - } - - false +impl fmt::Debug for ty::RegionVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "'_#{}r", self.index()) } } From cec81e7af25c0a9cd2c83ad234d164593f572e0a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 17:55:57 +0200 Subject: [PATCH 43/68] rustc: support overriding region printing in ty::print::Printer. --- src/librustc/infer/error_reporting/mod.rs | 8 + src/librustc/ty/print.rs | 174 +++++++++++++++++++-- src/librustc/util/ppaux.rs | 129 +-------------- src/librustc_codegen_utils/symbol_names.rs | 17 +- src/librustdoc/clean/mod.rs | 8 + 5 files changed, 199 insertions(+), 137 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b6497d07e0ad6..cc4556fe4bad5 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -458,6 +458,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Error = NonTrivialPath; type Path = Vec; + type Region = !; + + fn print_region( + self: PrintCx<'_, '_, '_, Self>, + _region: ty::Region<'_>, + ) -> Result { + Err(NonTrivialPath) + } fn path_crate( self: PrintCx<'_, '_, '_, Self>, diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 127d66603547b..5ded809d2995b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -1,6 +1,7 @@ use hir::def::Namespace; use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use middle::region; use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use ty::subst::{Kind, Subst, Substs, UnpackedKind}; use middle::cstore::{ExternCrate, ExternCrateSource}; @@ -68,7 +69,7 @@ pub struct RegionHighlightMode { /// This is used when you have a signature like `fn foo(x: &u32, /// y: &'a u32)` and we want to give a name to the region of the /// reference `x`. - pub(crate) highlight_bound_region: Option<(ty::BoundRegion, usize)>, + highlight_bound_region: Option<(ty::BoundRegion, usize)>, } impl RegionHighlightMode { @@ -116,7 +117,7 @@ impl RegionHighlightMode { /// Returns `Some(n)` with the number to use for the given region, /// if any. - pub(crate) fn region_highlighted(&self, region: ty::Region<'_>) -> Option { + fn region_highlighted(&self, region: ty::Region<'_>) -> Option { self .highlight_regions .iter() @@ -252,6 +253,7 @@ pub trait Printer: Sized { type Error; type Path; + type Region; fn print_def_path( self: PrintCx<'_, '_, 'tcx, Self>, @@ -273,6 +275,11 @@ pub trait Printer: Sized { self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref) } + fn print_region( + self: PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> Result; + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -312,7 +319,7 @@ pub trait Printer: Sized { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter: Printer + fmt::Write { +pub trait PrettyPrinter: Printer + fmt::Write { /// Enter a nested print context, for pretty-printing /// nested components in some larger context. fn nest<'a, 'gcx, 'tcx, E>( @@ -331,9 +338,26 @@ pub trait PrettyPrinter: Printer + fmt::Write { }) } - fn region_highlight_mode(&self) -> RegionHighlightMode { - RegionHighlightMode::default() + /// Return `true` if the region should be printed in path generic args + /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`. + fn always_print_region_in_paths( + self: &PrintCx<'_, '_, '_, Self>, + _region: ty::Region<'_>, + ) -> bool { + false } + + // HACK(eddyb) Trying to print a lifetime might not print anything, which + // may need special handling in the caller (of `ty::RegionKind::print`). + // To avoid printing to a temporary string (which isn't even supported), + // the `print_region_outputs_anything` method can instead be used to + // determine this, ahead of time. + // + // NB: this must be kept in sync with the implementation of `print_region`. + fn print_region_outputs_anything( + self: &PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> bool; } macro_rules! nest { @@ -799,10 +823,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let start = if ns == Namespace::ValueNS { "::<" } else { "<" }; - // Don't print any regions if they're all erased. + // Don't print `'_` if there's no printed region. let print_regions = params.iter().any(|param| { match substs[param.index as usize].unpack() { - UnpackedKind::Lifetime(r) => *r != ty::ReErased, + UnpackedKind::Lifetime(r) => { + self.always_print_region_in_paths(r) || + self.print_region_outputs_anything(r) + } _ => false, } }); @@ -830,7 +857,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { continue; } start_or_continue(&mut self, start, ", ")?; - if !region.display_outputs_anything(&self) { + if !self.print_region_outputs_anything(region) { // This happens when the value of the region // parameter is not easily serialized. This may be // because the user omitted it in the first place, @@ -872,6 +899,7 @@ impl Printer for FmtPrinter { type Error = fmt::Error; type Path = Self; + type Region = Self; fn print_def_path( mut self: PrintCx<'_, '_, 'tcx, Self>, @@ -928,6 +956,80 @@ impl Printer for FmtPrinter { self.default_print_def_path(def_id, substs, ns, projections) } + fn print_region( + mut self: PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> Result { + // Watch out for region highlights. + let highlight = self.printer.region_highlight_mode; + if let Some(n) = highlight.region_highlighted(region) { + write!(self.printer, "'{}", n)?; + return Ok(self.printer); + } + + if self.config.is_verbose { + return region.print_debug(self); + } + + // These printouts are concise. They do not contain all the information + // the user might want to diagnose an error, but there is basically no way + // to fit that into a short string. Hence the recommendation to use + // `explain_region()` or `note_and_explain_region()`. + match *region { + ty::ReEarlyBound(ref data) => { + if data.name != "'_" { + write!(self.printer, "{}", data.name)?; + } + } + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + write!(self.printer, "{}", name)?; + return Ok(self.printer); + } + } + + if let Some((region, counter)) = highlight.highlight_bound_region { + if br == region { + write!(self.printer, "'{}", counter)?; + } + } + } + ty::ReScope(scope) if self.config.identify_regions => { + match scope.data { + region::ScopeData::Node => + write!(self.printer, "'{}s", scope.item_local_id().as_usize())?, + region::ScopeData::CallSite => + write!(self.printer, "'{}cs", scope.item_local_id().as_usize())?, + region::ScopeData::Arguments => + write!(self.printer, "'{}as", scope.item_local_id().as_usize())?, + region::ScopeData::Destruction => + write!(self.printer, "'{}ds", scope.item_local_id().as_usize())?, + region::ScopeData::Remainder(first_statement_index) => write!(self.printer, + "'{}_{}rs", + scope.item_local_id().as_usize(), + first_statement_index.index() + )?, + } + } + ty::ReVar(region_vid) if self.config.identify_regions => { + write!(self.printer, "{:?}", region_vid)?; + } + ty::ReVar(_) => {} + ty::ReScope(_) | + ty::ReErased => {} + ty::ReStatic => write!(self.printer, "'static")?, + ty::ReEmpty => write!(self.printer, "'")?, + + // The user should never encounter these in unsubstituted form. + ty::ReClosureBound(vid) => write!(self.printer, "{:?}", vid)?, + } + + Ok(self.printer) + } + fn path_crate( mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -1017,7 +1119,59 @@ impl PrettyPrinter for FmtPrinter { }) } - fn region_highlight_mode(&self) -> RegionHighlightMode { - self.region_highlight_mode + fn always_print_region_in_paths( + self: &PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> bool { + *region != ty::ReErased + } + + fn print_region_outputs_anything( + self: &PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> bool { + let highlight = self.printer.region_highlight_mode; + if highlight.region_highlighted(region).is_some() { + return true; + } + + if self.config.is_verbose { + return true; + } + + match *region { + ty::ReEarlyBound(ref data) => { + data.name != "" && data.name != "'_" + } + + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + return true; + } + } + + if let Some((region, _)) = highlight.highlight_bound_region { + if br == region { + return true; + } + } + + false + } + + ty::ReScope(_) | + ty::ReVar(_) if self.config.identify_regions => true, + + ty::ReVar(_) | + ty::ReScope(_) | + ty::ReErased => false, + + ty::ReStatic | + ty::ReEmpty | + ty::ReClosureBound(_) => true, + } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 847a05125a21b..a4b986c68ac75 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,6 +1,5 @@ use hir::def::Namespace; use hir::def_id::DefId; -use middle::region; use ty::subst::{Kind, Subst, Substs, UnpackedKind}; use ty::{Bool, Char, Adt}; use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; @@ -485,72 +484,7 @@ impl fmt::Debug for ty::BoundRegion { define_print! { () ty::RegionKind, (self, cx) { display { - // Watch out for region highlights. - let highlight = cx.printer.region_highlight_mode(); - if let Some(n) = highlight.region_highlighted(self) { - p!(write("'{}", n)); - return Ok(cx.printer); - } - - if cx.config.is_verbose { - return self.print_debug(cx); - } - - // These printouts are concise. They do not contain all the information - // the user might want to diagnose an error, but there is basically no way - // to fit that into a short string. Hence the recommendation to use - // `explain_region()` or `note_and_explain_region()`. - match *self { - ty::ReEarlyBound(ref data) => { - if data.name != "'_" { - p!(write("{}", data.name)) - } - } - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { - p!(write("{}", name)); - return Ok(cx.printer); - } - } - - if let Some((region, counter)) = highlight.highlight_bound_region { - if br == region { - p!(write("'{}", counter)); - } - } - } - ty::ReScope(scope) if cx.config.identify_regions => { - match scope.data { - region::ScopeData::Node => - p!(write("'{}s", scope.item_local_id().as_usize())), - region::ScopeData::CallSite => - p!(write("'{}cs", scope.item_local_id().as_usize())), - region::ScopeData::Arguments => - p!(write("'{}as", scope.item_local_id().as_usize())), - region::ScopeData::Destruction => - p!(write("'{}ds", scope.item_local_id().as_usize())), - region::ScopeData::Remainder(first_statement_index) => p!(write( - "'{}_{}rs", - scope.item_local_id().as_usize(), - first_statement_index.index() - )), - } - } - ty::ReVar(region_vid) if cx.config.identify_regions => { - p!(write("{:?}", region_vid)); - } - ty::ReVar(_) => {} - ty::ReScope(_) | - ty::ReErased => {} - ty::ReStatic => p!(write("'static")), - ty::ReEmpty => p!(write("'")), - - // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => p!(write("{:?}", vid)), - } + return cx.print_region(self); } debug { match *self { @@ -592,63 +526,6 @@ define_print! { } } -// HACK(eddyb) Trying to print a lifetime might not print anything, which -// may need special handling in the caller (of `ty::RegionKind::print`). -// To avoid printing to a temporary string, the `display_outputs_anything` -// method can instead be used to determine this, ahead of time. -// -// NB: this must be kept in sync with the printing logic above. -impl ty::RegionKind { - // HACK(eddyb) `pub(crate)` only for `ty::print`. - pub(crate) fn display_outputs_anything

(&self, cx: &PrintCx<'_, '_, '_, P>) -> bool - where P: PrettyPrinter - { - let highlight = cx.printer.region_highlight_mode(); - if highlight.region_highlighted(self).is_some() { - return true; - } - - if cx.config.is_verbose { - return true; - } - - match *self { - ty::ReEarlyBound(ref data) => { - data.name != "" && data.name != "'_" - } - - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { - return true; - } - } - - if let Some((region, _)) = highlight.highlight_bound_region { - if br == region { - return true; - } - } - - false - } - - ty::ReScope(_) | - ty::ReVar(_) if cx.config.identify_regions => true, - - ty::ReVar(_) | - ty::ReScope(_) | - ty::ReErased => false, - - ty::ReStatic | - ty::ReEmpty | - ty::ReClosureBound(_) => true, - } - } -} - define_print! { () ty::FreeRegion, (self, cx) { debug { @@ -822,7 +699,7 @@ define_print! { } Ref(r, ty, mutbl) => { p!(write("&")); - if r.display_outputs_anything(&cx) { + if cx.print_region_outputs_anything(r) { p!(print_display(r), write(" ")); } p!(print(ty::TypeAndMut { ty, mutbl })) @@ -881,7 +758,7 @@ define_print! { )); } Dynamic(data, r) => { - let print_r = r.display_outputs_anything(&cx); + let print_r = cx.print_region_outputs_anything(r); if print_r { p!(write("(")); } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 35914259ae3dd..066c0a2826f23 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -410,6 +410,14 @@ impl Printer for SymbolPath { type Error = fmt::Error; type Path = Self; + type Region = Self; + + fn print_region( + self: PrintCx<'_, '_, '_, Self>, + _region: ty::Region<'_>, + ) -> Result { + Ok(self.printer) + } fn path_crate( mut self: PrintCx<'_, '_, '_, Self>, @@ -512,7 +520,14 @@ impl Printer for SymbolPath { } } -impl PrettyPrinter for SymbolPath {} +impl PrettyPrinter for SymbolPath { + fn print_region_outputs_anything( + self: &PrintCx<'_, '_, '_, Self>, + _region: ty::Region<'_>, + ) -> bool { + false + } +} // Name sanitation. LLVM will happily accept identifiers with weird names, but // gas doesn't! diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 3289833365045..d68f21235f8bf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4053,6 +4053,14 @@ where F: Fn(DefId) -> Def { type Error = !; type Path = Vec; + type Region = (); + + fn print_region( + self: PrintCx<'_, '_, '_, Self>, + _region: ty::Region<'_>, + ) -> Result { + Ok(()) + } fn path_crate( self: PrintCx<'_, '_, '_, Self>, From ca976f05ab3bca88b8d67ddcca4d86f993ff8164 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 19:56:46 +0200 Subject: [PATCH 44/68] rustc: support overriding type printing in ty::print::Printer. --- src/librustc/infer/error_reporting/mod.rs | 8 + src/librustc/ty/print.rs | 24 +- src/librustc/util/ppaux.rs | 463 +++++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 8 + src/librustdoc/clean/mod.rs | 8 + 5 files changed, 283 insertions(+), 228 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index cc4556fe4bad5..146d82046a628 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -459,6 +459,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Path = Vec; type Region = !; + type Type = !; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -467,6 +468,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Err(NonTrivialPath) } + fn print_type<'tcx>( + self: PrintCx<'_, '_, 'tcx, Self>, + _ty: Ty<'tcx>, + ) -> Result { + Err(NonTrivialPath) + } + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 5ded809d2995b..3e9c34d7c4028 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -254,6 +254,7 @@ pub trait Printer: Sized { type Path; type Region; + type Type; fn print_def_path( self: PrintCx<'_, '_, 'tcx, Self>, @@ -280,6 +281,11 @@ pub trait Printer: Sized { region: ty::Region<'_>, ) -> Result; + fn print_type( + self: PrintCx<'_, '_, 'tcx, Self>, + ty: Ty<'tcx>, + ) -> Result; + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -319,7 +325,15 @@ pub trait Printer: Sized { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter: Printer + fmt::Write { +pub trait PrettyPrinter: + Printer< + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + > + + fmt::Write +{ /// Enter a nested print context, for pretty-printing /// nested components in some larger context. fn nest<'a, 'gcx, 'tcx, E>( @@ -900,6 +914,7 @@ impl Printer for FmtPrinter { type Path = Self; type Region = Self; + type Type = Self; fn print_def_path( mut self: PrintCx<'_, '_, 'tcx, Self>, @@ -1030,6 +1045,13 @@ impl Printer for FmtPrinter { Ok(self.printer) } + fn print_type( + self: PrintCx<'_, '_, 'tcx, Self>, + ty: Ty<'tcx>, + ) -> Result { + self.pretty_print_type(ty) + } + fn path_crate( mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a4b986c68ac75..58d0f221972b6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,11 +1,6 @@ use hir::def::Namespace; use hir::def_id::DefId; use ty::subst::{Kind, Subst, Substs, UnpackedKind}; -use ty::{Bool, Char, Adt}; -use ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; -use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; -use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; -use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TypeFoldable}; use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; @@ -681,256 +676,270 @@ define_print! { } } -define_print! { - ('tcx) ty::Ty<'tcx>, (self, cx) { - display { - match self.sty { - Bool => p!(write("bool")), - Char => p!(write("char")), - Int(t) => p!(write("{}", t.ty_to_string())), - Uint(t) => p!(write("{}", t.ty_to_string())), - Float(t) => p!(write("{}", t.ty_to_string())), - RawPtr(ref tm) => { - p!(write("*{} ", match tm.mutbl { - hir::MutMutable => "mut", - hir::MutImmutable => "const", - })); - p!(print(tm.ty)) +// FIXME(eddyb) move this to `ty::print`. +impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { + pub fn pretty_print_type( + mut self, + ty: Ty<'tcx>, + ) -> Result { + define_scoped_cx!(self); + + match ty.sty { + ty::Bool => p!(write("bool")), + ty::Char => p!(write("char")), + ty::Int(t) => p!(write("{}", t.ty_to_string())), + ty::Uint(t) => p!(write("{}", t.ty_to_string())), + ty::Float(t) => p!(write("{}", t.ty_to_string())), + ty::RawPtr(ref tm) => { + p!(write("*{} ", match tm.mutbl { + hir::MutMutable => "mut", + hir::MutImmutable => "const", + })); + p!(print(tm.ty)) + } + ty::Ref(r, ty, mutbl) => { + p!(write("&")); + if self.print_region_outputs_anything(r) { + p!(print_display(r), write(" ")); } - Ref(r, ty, mutbl) => { - p!(write("&")); - if cx.print_region_outputs_anything(r) { - p!(print_display(r), write(" ")); + p!(print(ty::TypeAndMut { ty, mutbl })) + } + ty::Never => p!(write("!")), + ty::Tuple(ref tys) => { + p!(write("(")); + let mut tys = tys.iter(); + if let Some(&ty) = tys.next() { + p!(print(ty), write(",")); + if let Some(&ty) = tys.next() { + p!(write(" "), print(ty)); + for &ty in tys { + p!(write(", "), print(ty)); + } } - p!(print(ty::TypeAndMut { ty, mutbl })) } - Never => p!(write("!")), - Tuple(ref tys) => { - p!(write("(")); - let mut tys = tys.iter(); - if let Some(&ty) = tys.next() { - p!(print(ty), write(",")); - if let Some(&ty) = tys.next() { - p!(write(" "), print(ty)); - for &ty in tys { - p!(write(", "), print(ty)); - } + p!(write(")")) + } + ty::FnDef(def_id, substs) => { + let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); + p!(print(sig), write(" {{")); + nest!(|cx| cx.print_def_path( + def_id, + Some(substs), + Namespace::ValueNS, + iter::empty(), + )); + p!(write("}}")) + } + ty::FnPtr(ref bare_fn) => { + p!(print(bare_fn)) + } + ty::Infer(infer_ty) => p!(write("{}", infer_ty)), + ty::Error => p!(write("[type error]")), + ty::Param(ref param_ty) => p!(write("{}", param_ty)), + ty::Bound(debruijn, bound_ty) => { + match bound_ty.kind { + ty::BoundTyKind::Anon => { + if debruijn == ty::INNERMOST { + p!(write("^{}", bound_ty.var.index())) + } else { + p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) } } - p!(write(")")) + + ty::BoundTyKind::Param(p) => p!(write("{}", p)), } - FnDef(def_id, substs) => { - let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); - p!(print(sig), write(" {{")); - nest!(|cx| cx.print_def_path( - def_id, - Some(substs), - Namespace::ValueNS, - iter::empty(), - )); - p!(write("}}")) + } + ty::Adt(def, substs) => { + nest!(|cx| cx.print_def_path( + def.did, + Some(substs), + Namespace::TypeNS, + iter::empty(), + )); + } + ty::Dynamic(data, r) => { + let print_r = self.print_region_outputs_anything(r); + if print_r { + p!(write("(")); } - FnPtr(ref bare_fn) => { - p!(print(bare_fn)) + p!(write("dyn "), print(data)); + if print_r { + p!(write(" + "), print_display(r), write(")")); + } + } + ty::Foreign(def_id) => { + nest!(|cx| cx.print_def_path( + def_id, + None, + Namespace::TypeNS, + iter::empty(), + )); + } + ty::Projection(ref data) => p!(print(data)), + ty::UnnormalizedProjection(ref data) => { + p!(write("Unnormalized("), print(data), write(")")) + } + ty::Placeholder(placeholder) => { + p!(write("Placeholder({:?})", placeholder)) + } + ty::Opaque(def_id, substs) => { + if self.config.is_verbose { + p!(write("Opaque({:?}, {:?})", def_id, substs)); + return Ok(self.printer); } - Infer(infer_ty) => p!(write("{}", infer_ty)), - Error => p!(write("[type error]")), - Param(ref param_ty) => p!(write("{}", param_ty)), - Bound(debruijn, bound_ty) => { - match bound_ty.kind { - ty::BoundTyKind::Anon => { - if debruijn == ty::INNERMOST { - p!(write("^{}", bound_ty.var.index())) - } else { - p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) - } - } - ty::BoundTyKind::Param(p) => p!(write("{}", p)), + let def_key = self.tcx.def_key(def_id); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { + p!(write("{}", name)); + let mut substs = substs.iter(); + // FIXME(eddyb) print this with `print_def_path`. + if let Some(first) = substs.next() { + p!(write("::<")); + p!(print_display(first)); + for subst in substs { + p!(write(", "), print_display(subst)); + } + p!(write(">")); } + return Ok(self.printer); } - Adt(def, substs) => { - nest!(|cx| cx.print_def_path( - def.did, - Some(substs), - Namespace::TypeNS, - iter::empty(), - )); - } - Dynamic(data, r) => { - let print_r = cx.print_region_outputs_anything(r); - if print_r { - p!(write("(")); - } - p!(write("dyn "), print(data)); - if print_r { - p!(write(" + "), print_display(r), write(")")); + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); + + let mut first = true; + let mut is_sized = false; + p!(write("impl")); + for predicate in bounds.predicates { + if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + is_sized = true; + continue; + } + + p!( + write("{}", if first { " " } else { "+" }), + print(trait_ref)); + first = false; } } - Foreign(def_id) => { - nest!(|cx| cx.print_def_path( - def_id, - None, - Namespace::TypeNS, - iter::empty(), - )); - } - Projection(ref data) => p!(print(data)), - UnnormalizedProjection(ref data) => { - p!(write("Unnormalized("), print(data), write(")")) + if !is_sized { + p!(write("{}?Sized", if first { " " } else { "+" })); + } else if first { + p!(write(" Sized")); } - Placeholder(placeholder) => { - p!(write("Placeholder({:?})", placeholder)) + } + ty::Str => p!(write("str")), + ty::Generator(did, substs, movability) => { + let upvar_tys = substs.upvar_tys(did, self.tcx); + let witness = substs.witness(did, self.tcx); + if movability == hir::GeneratorMovability::Movable { + p!(write("[generator")); + } else { + p!(write("[static generator")); } - Opaque(def_id, substs) => { - if cx.config.is_verbose { - p!(write("Opaque({:?}, {:?})", def_id, substs)); - return Ok(cx.printer); - } - let def_key = cx.tcx.def_key(def_id); - if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - p!(write("{}", name)); - let mut substs = substs.iter(); - // FIXME(eddyb) print this with `print_def_path`. - if let Some(first) = substs.next() { - p!(write("::<")); - p!(print_display(first)); - for subst in substs { - p!(write(", "), print_display(subst)); - } - p!(write(">")); - } - return Ok(cx.printer); - } - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let bounds = cx.tcx.predicates_of(def_id).instantiate(cx.tcx, substs); - - let mut first = true; - let mut is_sized = false; - p!(write("impl")); - for predicate in bounds.predicates { - if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == cx.tcx.lang_items().sized_trait() { - is_sized = true; - continue; - } - - p!( - write("{}", if first { " " } else { "+" }), - print(trait_ref)); - first = false; - } + // FIXME(eddyb) should use `def_span`. + if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { + p!(write("@{:?}", self.tcx.hir().span(node_id))); + let mut sep = " "; + for (freevar, upvar_ty) in self.tcx.freevars(did) + .as_ref() + .map_or(&[][..], |fv| &fv[..]) + .iter() + .zip(upvar_tys) + { + p!( + write("{}{}:", + sep, + self.tcx.hir().name(freevar.var_id())), + print(upvar_ty)); + sep = ", "; } - if !is_sized { - p!(write("{}?Sized", if first { " " } else { "+" })); - } else if first { - p!(write(" Sized")); + } else { + // cross-crate closure types should only be + // visible in codegen bug reports, I imagine. + p!(write("@{:?}", did)); + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + p!( + write("{}{}:", sep, index), + print(upvar_ty)); + sep = ", "; } } - Str => p!(write("str")), - Generator(did, substs, movability) => { - let upvar_tys = substs.upvar_tys(did, cx.tcx); - let witness = substs.witness(did, cx.tcx); - if movability == hir::GeneratorMovability::Movable { - p!(write("[generator")); - } else { - p!(write("[static generator")); - } - // FIXME(eddyb) should use `def_span`. - if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { - p!(write("@{:?}", cx.tcx.hir().span(node_id))); - let mut sep = " "; - for (freevar, upvar_ty) in cx.tcx.freevars(did) - .as_ref() - .map_or(&[][..], |fv| &fv[..]) - .iter() - .zip(upvar_tys) - { - p!( - write("{}{}:", - sep, - cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty)); - sep = ", "; - } + p!(write(" "), print(witness), write("]")) + }, + ty::GeneratorWitness(types) => { + nest!(|cx| cx.in_binder(&types)) + } + ty::Closure(did, substs) => { + let upvar_tys = substs.upvar_tys(did, self.tcx); + p!(write("[closure")); + + // FIXME(eddyb) should use `def_span`. + if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { + if self.tcx.sess.opts.debugging_opts.span_free_formats { + p!(write("@{:?}", node_id)); } else { - // cross-crate closure types should only be - // visible in codegen bug reports, I imagine. - p!(write("@{:?}", did)); - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - p!( - write("{}{}:", sep, index), - print(upvar_ty)); - sep = ", "; - } + p!(write("@{:?}", self.tcx.hir().span(node_id))); } - - p!(write(" "), print(witness), write("]")) - }, - GeneratorWitness(types) => { - nest!(|cx| cx.in_binder(&types)) - } - Closure(did, substs) => { - let upvar_tys = substs.upvar_tys(did, cx.tcx); - p!(write("[closure")); - - // FIXME(eddyb) should use `def_span`. - if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { - if cx.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", node_id)); - } else { - p!(write("@{:?}", cx.tcx.hir().span(node_id))); - } - let mut sep = " "; - for (freevar, upvar_ty) in cx.tcx.freevars(did) - .as_ref() - .map_or(&[][..], |fv| &fv[..]) - .iter() - .zip(upvar_tys) - { - p!( - write("{}{}:", - sep, - cx.tcx.hir().name(freevar.var_id())), + let mut sep = " "; + for (freevar, upvar_ty) in self.tcx.freevars(did) + .as_ref() + .map_or(&[][..], |fv| &fv[..]) + .iter() + .zip(upvar_tys) + { + p!( + write("{}{}:", + sep, + self.tcx.hir().name(freevar.var_id())), + print(upvar_ty)); + sep = ", "; + } + } else { + // cross-crate closure types should only be + // visible in codegen bug reports, I imagine. + p!(write("@{:?}", did)); + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + p!( + write("{}{}:", sep, index), print(upvar_ty)); - sep = ", "; - } - } else { - // cross-crate closure types should only be - // visible in codegen bug reports, I imagine. - p!(write("@{:?}", did)); - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - p!( - write("{}{}:", sep, index), - print(upvar_ty)); - sep = ", "; - } + sep = ", "; } + } - p!(write("]")) - }, - Array(ty, sz) => { - p!(write("["), print(ty), write("; ")); - match sz { - ty::LazyConst::Unevaluated(_def_id, _substs) => { - p!(write("_")); - } - ty::LazyConst::Evaluated(c) => { - p!(write("{}", c.unwrap_usize(cx.tcx))); - } + p!(write("]")) + }, + ty::Array(ty, sz) => { + p!(write("["), print(ty), write("; ")); + match sz { + ty::LazyConst::Unevaluated(_def_id, _substs) => { + p!(write("_")); + } + ty::LazyConst::Evaluated(c) => { + p!(write("{}", c.unwrap_usize(self.tcx))); } - p!(write("]")) - } - Slice(ty) => { - p!(write("["), print(ty), write("]")) } + p!(write("]")) } + ty::Slice(ty) => { + p!(write("["), print(ty), write("]")) + } + } + + Ok(self.printer) + } +} + +define_print! { + ('tcx) Ty<'tcx>, (self, cx) { + display { + return cx.print_type(self); } debug { p!(print_display(self)) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 066c0a2826f23..5710255fc1bc2 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -411,6 +411,7 @@ impl Printer for SymbolPath { type Path = Self; type Region = Self; + type Type = Self; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -419,6 +420,13 @@ impl Printer for SymbolPath { Ok(self.printer) } + fn print_type( + self: PrintCx<'_, '_, 'tcx, Self>, + ty: Ty<'tcx>, + ) -> Result { + self.pretty_print_type(ty) + } + fn path_crate( mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d68f21235f8bf..70383cce7bad3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4054,6 +4054,7 @@ where F: Fn(DefId) -> Def { type Path = Vec; type Region = (); + type Type = (); fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -4062,6 +4063,13 @@ where F: Fn(DefId) -> Def { Ok(()) } + fn print_type( + self: PrintCx<'_, '_, 'tcx, Self>, + _ty: Ty<'tcx>, + ) -> Result { + Ok(()) + } + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, From 9c3ec4bdc240418523bd9f82b45a54c2774a4707 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 22:07:38 +0200 Subject: [PATCH 45/68] rustc: introduce a ty::print::PrettyPrinter helper for printing "<...>". --- src/librustc/ty/print.rs | 174 +++++++++++++-------- src/librustc_codegen_utils/symbol_names.rs | 68 +++----- 2 files changed, 129 insertions(+), 113 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 3e9c34d7c4028..5654ad1068fdb 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -338,7 +338,7 @@ pub trait PrettyPrinter: /// nested components in some larger context. fn nest<'a, 'gcx, 'tcx, E>( self: PrintCx<'a, 'gcx, 'tcx, Self>, - f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result, E> { let printer = f(PrintCx { tcx: self.tcx, @@ -352,6 +352,17 @@ pub trait PrettyPrinter: }) } + /// Print `<...>` around what `f` prints. + fn generic_delimiters<'gcx, 'tcx>( + mut self: PrintCx<'_, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result { + write!(self.printer, "<")?; + let mut printer = f(self)?; + write!(printer, ">")?; + Ok(printer) + } + /// Return `true` if the region should be printed in path generic args /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`. fn always_print_region_in_paths( @@ -750,7 +761,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } pub fn pretty_path_qualified( - mut self, + self, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, @@ -776,20 +787,19 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - write!(self.printer, "<")?; - nest!(self, |cx| self_ty.print_display(cx)); - if let Some(trait_ref) = trait_ref { - write!(self.printer, " as ")?; - nest!(self, |cx| cx.print_def_path( - trait_ref.def_id, - Some(trait_ref.substs), - Namespace::TypeNS, - iter::empty(), - )); - } - write!(self.printer, ">")?; - - Ok(self.printer) + self.generic_delimiters(|mut cx| { + nest!(cx, |cx| self_ty.print_display(cx)); + if let Some(trait_ref) = trait_ref { + write!(cx.printer, " as ")?; + nest!(cx, |cx| cx.print_def_path( + trait_ref.def_id, + Some(trait_ref.substs), + Namespace::TypeNS, + iter::empty(), + )); + } + Ok(cx.printer) + }) } pub fn pretty_path_append_impl( @@ -800,17 +810,18 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - // HACK(eddyb) going through `path_append` means symbol name - // computation gets to handle its equivalent of `::` correctly. - nest!(self, |cx| cx.path_append(print_prefix, "")?; + nest!(self, print_prefix); - Ok(self.printer) + self.generic_delimiters(|mut cx| { + write!(cx.printer, "impl ")?; + if let Some(trait_ref) = trait_ref { + nest!(cx, |cx| trait_ref.print_display(cx)); + write!(cx.printer, " for ")?; + } + nest!(cx, |cx| self_ty.print_display(cx)); + + Ok(cx.printer) + }) } pub fn pretty_path_generic_args( @@ -825,18 +836,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ) -> Result { nest!(self, |cx| print_prefix(cx)); - let mut empty = true; - let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - write!(cx.printer, "{}", if empty { - empty = false; - start - } else { - cont - }) - }; - - let start = if ns == Namespace::ValueNS { "::<" } else { "<" }; - // Don't print `'_` if there's no printed region. let print_regions = params.iter().any(|param| { match substs[param.index as usize].unpack() { @@ -864,41 +863,72 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }).count() }; - for param in ¶ms[..params.len() - num_supplied_defaults] { - match substs[param.index as usize].unpack() { - UnpackedKind::Lifetime(region) => { - if !print_regions { - continue; + let params = ¶ms[..params.len() - num_supplied_defaults]; + let mut args = params.iter().map(|param| { + substs[param.index as usize].unpack() + }).filter(|arg| { + match arg { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + let arg0 = args.next(); + + let mut projections = projections; + let projection0 = projections.next(); + + if arg0.is_none() && projection0.is_none() { + return Ok(self.printer); + } + + // FIXME(eddyb) move this into `generic_delimiters`. + if ns == Namespace::ValueNS { + write!(self.printer, "::")?; + } + + self.generic_delimiters(|mut cx| { + let mut empty = true; + let mut maybe_comma = |cx: &mut Self| { + if empty { + empty = false; + Ok(()) + } else { + write!(cx.printer, ", ") + } + }; + + for arg in arg0.into_iter().chain(args) { + maybe_comma(&mut cx)?; + + match arg { + UnpackedKind::Lifetime(region) => { + if !cx.print_region_outputs_anything(region) { + // This happens when the value of the region + // parameter is not easily serialized. This may be + // because the user omitted it in the first place, + // or because it refers to some block in the code, + // etc. I'm not sure how best to serialize this. + write!(cx.printer, "'_")?; + } else { + nest!(cx, |cx| region.print_display(cx)); + } } - start_or_continue(&mut self, start, ", ")?; - if !self.print_region_outputs_anything(region) { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - write!(self.printer, "'_")?; - } else { - nest!(self, |cx| region.print_display(cx)); + UnpackedKind::Type(ty) => { + nest!(cx, |cx| ty.print_display(cx)); } } - UnpackedKind::Type(ty) => { - start_or_continue(&mut self, start, ", ")?; - nest!(self, |cx| ty.print_display(cx)); - } } - } - for projection in projections { - start_or_continue(&mut self, start, ", ")?; - write!(self.printer, "{}=", - self.tcx.associated_item(projection.item_def_id).ident)?; - nest!(self, |cx| projection.ty.print_display(cx)); - } + for projection in projection0.into_iter().chain(projections) { + maybe_comma(&mut cx)?; - start_or_continue(&mut self, "", ">")?; + write!(cx.printer, "{}=", + cx.tcx.associated_item(projection.item_def_id).ident)?; + nest!(cx, |cx| projection.ty.print_display(cx)); + } - Ok(self.printer) + Ok(cx.printer) + }) } } @@ -1086,7 +1116,15 @@ impl Printer for FmtPrinter { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - self.pretty_path_append_impl(print_prefix, self_ty, trait_ref) + self.pretty_path_append_impl(|cx| { + let mut printer = print_prefix(cx)?; + + if !printer.empty { + write!(printer, "::")?; + } + + Ok(printer) + }, self_ty, trait_ref) } fn path_append<'gcx, 'tcx>( self: PrintCx<'_, 'gcx, 'tcx, Self>, @@ -1125,7 +1163,7 @@ impl Printer for FmtPrinter { impl PrettyPrinter for FmtPrinter { fn nest<'a, 'gcx, 'tcx, E>( mut self: PrintCx<'a, 'gcx, 'tcx, Self>, - f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result, E> { let was_empty = std::mem::replace(&mut self.printer.empty, true); let mut printer = f(PrintCx { diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 5710255fc1bc2..6def49efdb606 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -435,28 +435,12 @@ impl Printer for SymbolPath { Ok(self.printer) } fn path_qualified( - mut self: PrintCx<'_, '_, 'tcx, Self>, + self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, ns: Namespace, ) -> Result { - // HACK(eddyb) avoid `keep_within_component` for the cases - // that print without `<...>` around `self_ty`. - match self_ty.sty { - ty::Adt(..) | ty::Foreign(_) | - ty::Bool | ty::Char | ty::Str | - ty::Int(_) | ty::Uint(_) | ty::Float(_) - if trait_ref.is_none() => - { - return self.pretty_path_qualified(self_ty, trait_ref, ns); - } - _ => {} - } - - let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true); - let mut path = self.pretty_path_qualified(self_ty, trait_ref, ns)?; - path.keep_within_component = kept_within_component; - Ok(path) + self.pretty_path_qualified(self_ty, trait_ref, ns) } fn path_append_impl<'gcx, 'tcx>( @@ -467,18 +451,11 @@ impl Printer for SymbolPath { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - let kept_within_component = self.printer.keep_within_component; - let mut path = self.pretty_path_append_impl( - |cx| { - let mut path = print_prefix(cx)?; - path.keep_within_component = true; - Ok(path) - }, + self.pretty_path_append_impl( + |cx| cx.path_append(print_prefix, ""), self_ty, trait_ref, - )?; - path.keep_within_component = kept_within_component; - Ok(path) + ) } fn path_append<'gcx, 'tcx>( self: PrintCx<'_, 'gcx, 'tcx, Self>, @@ -487,11 +464,9 @@ impl Printer for SymbolPath { ) -> Result, text: &str, ) -> Result { - let keep_within_component = self.printer.keep_within_component; - let mut path = print_prefix(self)?; - if keep_within_component { + if path.keep_within_component { // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. path.write_str("::")?; } else { @@ -511,20 +486,7 @@ impl Printer for SymbolPath { ns: Namespace, projections: impl Iterator>, ) -> Result { - let kept_within_component = self.printer.keep_within_component; - let mut path = self.pretty_path_generic_args( - |cx| { - let mut path = print_prefix(cx)?; - path.keep_within_component = true; - Ok(path) - }, - params, - substs, - ns, - projections, - )?; - path.keep_within_component = kept_within_component; - Ok(path) + self.pretty_path_generic_args(print_prefix, params, substs, ns, projections) } } @@ -535,6 +497,22 @@ impl PrettyPrinter for SymbolPath { ) -> bool { false } + + fn generic_delimiters<'gcx, 'tcx>( + mut self: PrintCx<'_, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result { + write!(self.printer, "<")?; + + let kept_within_component = + mem::replace(&mut self.printer.keep_within_component, true); + let mut path = f(self)?; + path.keep_within_component = kept_within_component; + + write!(path, ">")?; + + Ok(path) + } } // Name sanitation. LLVM will happily accept identifiers with weird names, but From 82ee91253258bada7601f4dcb36b9be1be77f31e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 23:40:53 +0200 Subject: [PATCH 46/68] rustc: don't pass Namespace explicitly, but rather track it in FmtPrinter. --- src/librustc/infer/error_reporting/mod.rs | 5 +- .../infer/error_reporting/need_type_info.rs | 3 +- .../nice_region_error/placeholder_error.rs | 5 +- src/librustc/mir/mod.rs | 3 +- src/librustc/ty/print.rs | 123 ++++++++++-------- src/librustc/util/ppaux.rs | 99 +++----------- src/librustc_codegen_utils/symbol_names.rs | 9 +- .../borrow_check/error_reporting.rs | 5 +- src/librustdoc/clean/mod.rs | 6 +- 9 files changed, 102 insertions(+), 156 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 146d82046a628..91aad4ef7a6f3 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -445,7 +445,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { terr: &TypeError<'tcx>, sp: Span, ) { - use hir::def::Namespace; use hir::def_id::CrateNum; use ty::print::{PrintCx, Printer}; use ty::subst::Substs; @@ -485,7 +484,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self: PrintCx<'_, '_, 'tcx, Self>, _self_ty: Ty<'tcx>, _trait_ref: Option>, - _ns: Namespace, ) -> Result { Err(NonTrivialPath) } @@ -518,7 +516,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) -> Result, _params: &[ty::GenericParamDef], _substs: &'tcx Substs<'tcx>, - _ns: Namespace, _projections: impl Iterator>, ) -> Result { print_prefix(self) @@ -531,7 +528,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { PrintCx::with(self.tcx, AbsolutePathPrinter, |cx| { - cx.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) + cx.print_def_path(def_id, None, iter::empty()) }) }; diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index b5ecd7f89249f..e2cf351ca2065 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -1,3 +1,4 @@ +use hir::def::Namespace; use hir::{self, Local, Pat, Body, HirId}; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use infer::InferCtxt; @@ -79,7 +80,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut s); + let mut printer = ty::print::FmtPrinter::new(&mut s, Namespace::TypeNS); if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 1b2fb22ce6ba4..eb0ce6757f245 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -1,3 +1,4 @@ +use hir::def::Namespace; use hir::def_id::DefId; use infer::error_reporting::nice_region_error::NiceRegionError; use infer::lexical_region_resolve::RegionResolutionError; @@ -245,7 +246,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { { let mut note = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut note); + let mut printer = ty::print::FmtPrinter::new(&mut note, Namespace::TypeNS); printer.region_highlight_mode.maybe_highlighting_region(sub_placeholder, has_sub); printer.region_highlight_mode.maybe_highlighting_region(sup_placeholder, has_sup); @@ -279,7 +280,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { { let mut note = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut note); + let mut printer = ty::print::FmtPrinter::new(&mut note, Namespace::TypeNS); printer.region_highlight_mode.maybe_highlighting_region(vid, has_vid); let _ = ty::print::PrintCx::with(self.tcx, printer, |mut cx| { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 6c4ab85125e29..7f34f7421a49e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2341,7 +2341,8 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; // When printing regions, add trailing space if necessary. - ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter::new(fmt), |cx| { + let ns = Namespace::ValueNS; + ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter::new(fmt, ns), |cx| { let region = if cx.config.is_verbose || cx.config.identify_regions { let mut region = region.to_string(); if region.len() > 0 { diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 5654ad1068fdb..083434922425c 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -260,20 +260,18 @@ pub trait Printer: Sized { self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, projections: impl Iterator>, ) -> Result { - self.default_print_def_path(def_id, substs, ns, projections) + self.default_print_def_path(def_id, substs, projections) } fn print_impl_path( self: PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - self.default_print_impl_path(impl_def_id, substs, ns, self_ty, trait_ref) + self.default_print_impl_path(impl_def_id, substs, self_ty, trait_ref) } fn print_region( @@ -294,7 +292,6 @@ pub trait Printer: Sized { self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, - ns: Namespace, ) -> Result; fn path_append_impl<'gcx, 'tcx>( @@ -319,7 +316,6 @@ pub trait Printer: Sized { ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, - ns: Namespace, projections: impl Iterator>, ) -> Result; } @@ -352,16 +348,20 @@ pub trait PrettyPrinter: }) } + /// Like `print_def_path` but for value paths. + fn print_value_path( + self: PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + ) -> Result { + self.print_def_path(def_id, substs, iter::empty()) + } + /// Print `<...>` around what `f` prints. fn generic_delimiters<'gcx, 'tcx>( - mut self: PrintCx<'_, 'gcx, 'tcx, Self>, + self: PrintCx<'_, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result { - write!(self.printer, "<")?; - let mut printer = f(self)?; - write!(printer, ">")?; - Ok(printer) - } + ) -> Result; /// Return `true` if the region should be printed in path generic args /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`. @@ -415,8 +415,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); - let _ = PrintCx::with(self, FmtPrinter::new(&mut s), |cx| { - cx.print_def_path(def_id, None, ns, iter::empty()) + let _ = PrintCx::with(self, FmtPrinter::new(&mut s, ns), |cx| { + cx.print_def_path(def_id, None, iter::empty()) }); s } @@ -427,10 +427,9 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, projections: impl Iterator>, ) -> Result { - debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); + debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs); let key = self.tcx.def_key(def_id); debug!("default_print_def_path: key={:?}", key); @@ -450,7 +449,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { if let Some(substs) = substs { impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); } - self.print_impl_path(def_id, substs, ns, self_ty, impl_trait_ref) + self.print_impl_path(def_id, substs, self_ty, impl_trait_ref) } _ => { @@ -468,12 +467,12 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { parent_generics.has_self && parent_generics.parent_count == 0; if let (Some(substs), true) = (substs, parent_has_own_self) { let trait_ref = ty::TraitRef::new(parent_def_id, substs); - cx.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns) + cx.path_qualified(trait_ref.self_ty(), Some(trait_ref)) } else { - cx.print_def_path(parent_def_id, substs, ns, iter::empty()) + cx.print_def_path(parent_def_id, substs, iter::empty()) } } else { - cx.print_def_path(parent_def_id, None, ns, iter::empty()) + cx.print_def_path(parent_def_id, None, iter::empty()) } }; let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| { @@ -493,7 +492,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(print_path, params, substs, ns, projections) + self.path_generic_args(print_path, params, substs, projections) } else { print_path(self) } @@ -505,7 +504,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self, impl_def_id: DefId, _substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, self_ty: Ty<'tcx>, impl_trait_ref: Option>, ) -> Result { @@ -532,14 +530,14 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // trait-type, then fallback to a format that identifies // the module more clearly. self.path_append_impl( - |cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()), + |cx| cx.print_def_path(parent_def_id, None, iter::empty()), self_ty, impl_trait_ref, ) } else { // Otherwise, try to give a good form that would be valid language // syntax. Preferably using associated item notation. - self.path_qualified(self_ty, impl_trait_ref, ns) + self.path_qualified(self_ty, impl_trait_ref) } } } @@ -595,14 +593,16 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { pub struct FmtPrinter { pub(crate) fmt: F, empty: bool, + in_value: bool, pub region_highlight_mode: RegionHighlightMode, } impl FmtPrinter { - pub fn new(fmt: F) -> Self { + pub fn new(fmt: F, ns: Namespace) -> Self { FmtPrinter { fmt, empty: true, + in_value: ns == Namespace::ValueNS, region_highlight_mode: RegionHighlightMode::default(), } } @@ -646,7 +646,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); return Ok((if !span.is_dummy() { - self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())? + self.print_def_path(def_id, None, iter::empty())? } else { self.path_crate(cnum)? }, true)); @@ -764,20 +764,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { self, self_ty: Ty<'tcx>, trait_ref: Option>, - ns: Namespace, ) -> Result { if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is // anything other than a simple path. match self_ty.sty { - ty::Adt(adt_def, substs) => { - return self.print_def_path(adt_def.did, Some(substs), ns, iter::empty()); - } - ty::Foreign(did) => { - return self.print_def_path(did, None, ns, iter::empty()); - } - + ty::Adt(..) | ty::Foreign(_) | ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { return self_ty.print_display(self); @@ -791,12 +784,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { nest!(cx, |cx| self_ty.print_display(cx)); if let Some(trait_ref) = trait_ref { write!(cx.printer, " as ")?; - nest!(cx, |cx| cx.print_def_path( - trait_ref.def_id, - Some(trait_ref.substs), - Namespace::TypeNS, - iter::empty(), - )); + nest!(cx, |cx| trait_ref.print_display(cx)); } Ok(cx.printer) }) @@ -831,7 +819,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, - ns: Namespace, projections: impl Iterator>, ) -> Result { nest!(self, |cx| print_prefix(cx)); @@ -881,11 +868,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { return Ok(self.printer); } - // FIXME(eddyb) move this into `generic_delimiters`. - if ns == Namespace::ValueNS { - write!(self.printer, "::")?; - } - self.generic_delimiters(|mut cx| { let mut empty = true; let mut maybe_comma = |cx: &mut Self| { @@ -950,7 +932,6 @@ impl Printer for FmtPrinter { mut self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - ns: Namespace, projections: impl Iterator>, ) -> Result { // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` @@ -967,7 +948,7 @@ impl Printer for FmtPrinter { return if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(|cx| Ok(cx.printer), params, substs, ns, projections) + self.path_generic_args(|cx| Ok(cx.printer), params, substs, projections) } else { Ok(self.printer) }; @@ -992,13 +973,13 @@ impl Printer for FmtPrinter { let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; let span = self.tcx.def_span(def_id); return self.path_append( - |cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()), + |cx| cx.print_def_path(parent_def_id, None, iter::empty()), &format!("", span), ); } } - self.default_print_def_path(def_id, substs, ns, projections) + self.default_print_def_path(def_id, substs, projections) } fn print_region( @@ -1103,9 +1084,8 @@ impl Printer for FmtPrinter { self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, - ns: Namespace, ) -> Result { - self.pretty_path_qualified(self_ty, trait_ref, ns) + self.pretty_path_qualified(self_ty, trait_ref) } fn path_append_impl<'gcx, 'tcx>( @@ -1119,7 +1099,9 @@ impl Printer for FmtPrinter { self.pretty_path_append_impl(|cx| { let mut printer = print_prefix(cx)?; - if !printer.empty { + // HACK(eddyb) this accounts for `generic_delimiters` + // printing `::<` instead of `<` if `in_value` is set. + if !printer.empty && !printer.in_value { write!(printer, "::")?; } @@ -1153,10 +1135,9 @@ impl Printer for FmtPrinter { ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, - ns: Namespace, projections: impl Iterator>, ) -> Result { - self.pretty_path_generic_args(print_prefix, params, substs, ns, projections) + self.pretty_path_generic_args(print_prefix, params, substs, projections) } } @@ -1179,6 +1160,36 @@ impl PrettyPrinter for FmtPrinter { }) } + fn print_value_path( + mut self: PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + ) -> Result { + let was_in_value = std::mem::replace(&mut self.printer.in_value, true); + let mut printer = self.print_def_path(def_id, substs, iter::empty())?; + printer.in_value = was_in_value; + + Ok(printer) + } + + fn generic_delimiters<'gcx, 'tcx>( + mut self: PrintCx<'_, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result { + if !self.printer.empty && self.printer.in_value { + write!(self.printer, "::<")?; + } else { + write!(self.printer, "<")?; + } + + let was_in_value = std::mem::replace(&mut self.printer.in_value, false); + let mut printer = f(self)?; + printer.in_value = was_in_value; + + write!(printer, ">")?; + Ok(printer) + } + fn always_print_region_in_paths( self: &PrintCx<'_, '_, '_, Self>, region: ty::Region<'_>, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 58d0f221972b6..43afe8990eadf 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,7 +16,7 @@ use hir; macro_rules! gen_display_debug_body { ( $with:path ) => { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { $with(&cx.tcx.lift(self).expect("could not lift for printing"), cx)?; Ok(()) }) @@ -261,9 +261,9 @@ pub fn parameterized( substs: &Substs<'_>, ns: Namespace, ) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { + PrintCx::with_tls_tcx(FmtPrinter::new(f, ns), |cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.print_def_path(did, Some(substs), ns, iter::empty())?; + cx.print_def_path(did, Some(substs), iter::empty())?; Ok(()) }) } @@ -283,12 +283,7 @@ define_print! { if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - nest!(|cx| cx.print_def_path( - principal.def_id, - None, - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); nest!(|cx| cx.fn_sig(args, false, proj.ty)); resugared_principal = true; } @@ -302,7 +297,6 @@ define_print! { nest!(|cx| cx.print_def_path( principal.def_id, Some(principal.substs), - Namespace::TypeNS, self.projection_bounds(), )); } @@ -331,12 +325,7 @@ define_print! { } first = false; - nest!(|cx| cx.print_def_path( - def_id, - None, - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); } } } @@ -358,13 +347,8 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { - cx.print_def_path( - self.def_id, - None, - Namespace::TypeNS, - iter::empty(), - )?; + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.print_def_path(self.def_id, None, iter::empty())?; Ok(()) }) } @@ -372,13 +356,8 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f), |cx| { - cx.print_def_path( - self.did, - None, - Namespace::TypeNS, - iter::empty(), - )?; + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.print_def_path(self.did, None, iter::empty())?; Ok(()) }) } @@ -394,7 +373,7 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f), |mut cx| { + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |mut cx| { define_scoped_cx!(cx); p!(write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, @@ -663,15 +642,10 @@ define_print_multi! { define_print! { ('tcx) ty::TraitRef<'tcx>, (self, cx) { display { - nest!(|cx| cx.print_def_path( - self.def_id, - Some(self.substs), - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); } debug { - nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self), Namespace::TypeNS)); + nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self))); } } } @@ -722,12 +696,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ty::FnDef(def_id, substs) => { let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); p!(print(sig), write(" {{")); - nest!(|cx| cx.print_def_path( - def_id, - Some(substs), - Namespace::ValueNS, - iter::empty(), - )); + nest!(|cx| cx.print_value_path(def_id, Some(substs))); p!(write("}}")) } ty::FnPtr(ref bare_fn) => { @@ -750,12 +719,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Adt(def, substs) => { - nest!(|cx| cx.print_def_path( - def.did, - Some(substs), - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(def.did, Some(substs), iter::empty())); } ty::Dynamic(data, r) => { let print_r = self.print_region_outputs_anything(r); @@ -768,12 +732,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Foreign(def_id) => { - nest!(|cx| cx.print_def_path( - def_id, - None, - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); } ty::Projection(ref data) => p!(print(data)), ty::UnnormalizedProjection(ref data) => { @@ -1010,12 +969,7 @@ define_print! { define_print! { ('tcx) ty::ProjectionTy<'tcx>, (self, cx) { display { - nest!(|cx| cx.print_def_path( - self.item_def_id, - Some(self.substs), - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); } } } @@ -1044,32 +998,17 @@ define_print! { ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("the trait `")); - nest!(|cx| cx.print_def_path( - trait_def_id, - None, - Namespace::TypeNS, - iter::empty(), - )); + nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty())); p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { p!(write("the closure `")); - nest!(|cx| cx.print_def_path( - closure_def_id, - None, - Namespace::ValueNS, - iter::empty(), - )); + nest!(|cx| cx.print_value_path(closure_def_id, None)); p!(write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { p!(write("the constant `")); - nest!(|cx| cx.print_def_path( - def_id, - Some(substs), - Namespace::ValueNS, - iter::empty(), - )); + nest!(|cx| cx.print_value_path(def_id, Some(substs))); p!(write("` can be evaluated")) } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 6def49efdb606..d9a5c15883689 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -87,7 +87,6 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. -use rustc::hir::def::Namespace; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; @@ -224,7 +223,7 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { PrintCx::with(tcx, SymbolPath::new(), |cx| { - cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()) + cx.print_def_path(def_id, None, iter::empty()) .unwrap() .into_interned() }) @@ -438,9 +437,8 @@ impl Printer for SymbolPath { self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, - ns: Namespace, ) -> Result { - self.pretty_path_qualified(self_ty, trait_ref, ns) + self.pretty_path_qualified(self_ty, trait_ref) } fn path_append_impl<'gcx, 'tcx>( @@ -483,10 +481,9 @@ impl Printer for SymbolPath { ) -> Result, params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, - ns: Namespace, projections: impl Iterator>, ) -> Result { - self.pretty_path_generic_args(print_prefix, params, substs, ns, projections) + self.pretty_path_generic_args(print_prefix, params, substs, projections) } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 14821e5d41c9d..09f6379cb18f5 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -3,6 +3,7 @@ use borrow_check::nll::region_infer::{RegionName, RegionNameSource}; use borrow_check::prefixes::IsPrefixOf; use borrow_check::WriteKind; use rustc::hir; +use rustc::hir::def::Namespace; use rustc::hir::def_id::DefId; use rustc::middle::region::ScopeTree; use rustc::mir::{ @@ -2307,7 +2308,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// name where required. fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut s); + let mut printer = ty::print::FmtPrinter::new(&mut s, Namespace::TypeNS); // We need to add synthesized lifetimes where appropriate. We do // this by hooking into the pretty printer and telling it to label the @@ -2332,7 +2333,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// synthesized lifetime name where required. fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut s); + let mut printer = ty::print::FmtPrinter::new(&mut s, Namespace::TypeNS); let region = match ty.sty { ty::TyKind::Ref(region, _, _) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 70383cce7bad3..340fffd4595da 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -18,7 +18,7 @@ use rustc::middle::lang_items; use rustc::middle::stability; use rustc::mir::interpret::GlobalId; use rustc::hir::{self, GenericArg, HirVec}; -use rustc::hir::def::{self, Def, CtorKind, Namespace}; +use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::ty::subst::Substs; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; @@ -4080,7 +4080,6 @@ where F: Fn(DefId) -> Def { self: PrintCx<'_, '_, 'tcx, Self>, self_ty: Ty<'tcx>, trait_ref: Option>, - _ns: Namespace, ) -> Result { // This shouldn't ever be needed, but just in case: Ok(vec![match trait_ref { @@ -4127,7 +4126,6 @@ where F: Fn(DefId) -> Def { ) -> Result, _params: &[ty::GenericParamDef], _substs: &'tcx Substs<'tcx>, - _ns: Namespace, _projections: impl Iterator>, ) -> Result { print_prefix(self) @@ -4135,7 +4133,7 @@ where F: Fn(DefId) -> Def { } let names = PrintCx::with(tcx, AbsolutePathPrinter, |cx| { - cx.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()).unwrap() + cx.print_def_path(def_id, None, iter::empty()).unwrap() }); hir::Path { From fe30d5f18307b4fe76d9c2fd6df3b632b4b45c02 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 15 Jan 2019 00:41:14 +0200 Subject: [PATCH 47/68] rustc_codegen_utils: print all nominal types as paths, in symbol names. --- src/librustc_codegen_utils/symbol_names.rs | 30 ++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index d9a5c15883689..593aef546fdb8 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -423,7 +423,18 @@ impl Printer for SymbolPath { self: PrintCx<'_, '_, 'tcx, Self>, ty: Ty<'tcx>, ) -> Result { - self.pretty_print_type(ty) + match ty.sty { + // Print all nominal types as paths (unlike `pretty_print_type`). + ty::FnDef(def_id, substs) | + ty::Opaque(def_id, substs) | + ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::Closure(def_id, ty::ClosureSubsts { substs }) | + ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + self.print_def_path(def_id, Some(substs), iter::empty()) + } + _ => self.pretty_print_type(ty), + } } fn path_crate( @@ -438,7 +449,22 @@ impl Printer for SymbolPath { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - self.pretty_path_qualified(self_ty, trait_ref) + // Similar to `pretty_path_qualified`, but for the other + // types that are printed as paths (see `print_type` above). + match self_ty.sty { + ty::FnDef(..) | + ty::Opaque(..) | + ty::Projection(_) | + ty::UnnormalizedProjection(_) | + ty::Closure(..) | + ty::Generator(..) + if trait_ref.is_none() => + { + self.print_type(self_ty) + } + + _ => self.pretty_path_qualified(self_ty, trait_ref) + } } fn path_append_impl<'gcx, 'tcx>( From 05ba29e33b2626e35a4b24b18e046ce0a8f71b25 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 19:18:47 +0200 Subject: [PATCH 48/68] rustc: move ty/print.rs to ty/print/mod.rs. --- src/librustc/ty/{print.rs => print/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/librustc/ty/{print.rs => print/mod.rs} (100%) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print/mod.rs similarity index 100% rename from src/librustc/ty/print.rs rename to src/librustc/ty/print/mod.rs From 9ff30f13e388f4496f67d900500e12e87c529bbb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 21:33:31 +0200 Subject: [PATCH 49/68] rustc: split out the pretty-printing parts of ty::print into a separate module. --- src/librustc/mir/mod.rs | 4 +- src/librustc/ty/print/mod.rs | 904 +-------------------- src/librustc/ty/print/pretty.rs | 1294 +++++++++++++++++++++++++++++++ src/librustc/util/ppaux.rs | 373 +-------- 4 files changed, 1313 insertions(+), 1262 deletions(-) create mode 100644 src/librustc/ty/print/pretty.rs diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 7f34f7421a49e..e42bbbf26e8a3 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2342,7 +2342,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { // When printing regions, add trailing space if necessary. let ns = Namespace::ValueNS; - ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter::new(fmt, ns), |cx| { + ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter::new(fmt, ns), |mut cx| { let region = if cx.config.is_verbose || cx.config.identify_regions { let mut region = region.to_string(); if region.len() > 0 { @@ -2353,7 +2353,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { // Do not even print 'static String::new() }; - write!(cx.printer.fmt, "&{}{}{:?}", region, kind_str, place) + write!(cx.printer, "&{}{}{:?}", region, kind_str, place) }) } diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 083434922425c..2b747c034ffed 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,146 +1,21 @@ -use hir::def::Namespace; use hir::map::DefPathData; -use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use middle::region; +use hir::def_id::{CrateNum, DefId}; use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use ty::subst::{Kind, Subst, Substs, UnpackedKind}; -use middle::cstore::{ExternCrate, ExternCrateSource}; -use syntax::ast; -use syntax::symbol::{keywords, Symbol}; +use ty::subst::{Subst, Substs}; use rustc_data_structures::fx::FxHashSet; use syntax::symbol::InternedString; -use std::cell::Cell; -use std::fmt::{self, Write as _}; use std::iter; use std::ops::Deref; -thread_local! { - static FORCE_IMPL_FILENAME_LINE: Cell = Cell::new(false); - static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); -} - -/// Force us to name impls with just the filename/line number. We -/// normally try to use types. But at some points, notably while printing -/// cycle errors, this can result in extra or suboptimal error output, -/// so this variable disables that check. -pub fn with_forced_impl_filename_line R, R>(f: F) -> R { - FORCE_IMPL_FILENAME_LINE.with(|force| { - let old = force.get(); - force.set(true); - let result = f(); - force.set(old); - result - }) -} - -/// Add the `crate::` prefix to paths where appropriate. -pub fn with_crate_prefix R, R>(f: F) -> R { - SHOULD_PREFIX_WITH_CRATE.with(|flag| { - let old = flag.get(); - flag.set(true); - let result = f(); - flag.set(old); - result - }) -} +// `pretty` is a separate module only for organization. +mod pretty; +pub use self::pretty::*; // FIXME(eddyb) this module uses `pub(crate)` for things used only // from `ppaux` - when that is removed, they can be re-privatized. -/// The "region highlights" are used to control region printing during -/// specific error messages. When a "region highlight" is enabled, it -/// gives an alternate way to print specific regions. For now, we -/// always print those regions using a number, so something like `'0`. -/// -/// Regions not selected by the region highlight mode are presently -/// unaffected. -#[derive(Copy, Clone, Default)] -pub struct RegionHighlightMode { - /// If enabled, when we see the selected region, use `"'N"` - /// instead of the ordinary behavior. - highlight_regions: [Option<(ty::RegionKind, usize)>; 3], - - /// If enabled, when printing a "free region" that originated from - /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily - /// have names print as normal. - /// - /// This is used when you have a signature like `fn foo(x: &u32, - /// y: &'a u32)` and we want to give a name to the region of the - /// reference `x`. - highlight_bound_region: Option<(ty::BoundRegion, usize)>, -} - -impl RegionHighlightMode { - /// If `region` and `number` are both `Some`, invoke - /// `highlighting_region`. - pub fn maybe_highlighting_region( - &mut self, - region: Option>, - number: Option, - ) { - if let Some(k) = region { - if let Some(n) = number { - self.highlighting_region(k, n); - } - } - } - - /// Highlight the region inference variable `vid` as `'N`. - pub fn highlighting_region( - &mut self, - region: ty::Region<'_>, - number: usize, - ) { - let num_slots = self.highlight_regions.len(); - let first_avail_slot = self.highlight_regions.iter_mut() - .filter(|s| s.is_none()) - .next() - .unwrap_or_else(|| { - bug!( - "can only highlight {} placeholders at a time", - num_slots, - ) - }); - *first_avail_slot = Some((*region, number)); - } - - /// Convenience wrapper for `highlighting_region` - pub fn highlighting_region_vid( - &mut self, - vid: ty::RegionVid, - number: usize, - ) { - self.highlighting_region(&ty::ReVar(vid), number) - } - - /// Returns `Some(n)` with the number to use for the given region, - /// if any. - fn region_highlighted(&self, region: ty::Region<'_>) -> Option { - self - .highlight_regions - .iter() - .filter_map(|h| match h { - Some((r, n)) if r == region => Some(*n), - _ => None, - }) - .next() - } - - /// Highlight the given bound region. - /// We can only highlight one bound region at a time. See - /// the field `highlight_bound_region` for more detailed notes. - pub fn highlighting_bound_region( - &mut self, - br: ty::BoundRegion, - number: usize, - ) { - assert!(self.highlight_bound_region.is_none()); - self.highlight_bound_region = Some((br, number)); - } -} - struct LateBoundRegionNameCollector(FxHashSet); impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { @@ -158,13 +33,13 @@ pub(crate) struct PrintConfig { pub(crate) is_debug: bool, pub(crate) is_verbose: bool, pub(crate) identify_regions: bool, - pub(crate) used_region_names: Option>, - pub(crate) region_index: usize, - pub(crate) binder_depth: usize, + used_region_names: Option>, + region_index: usize, + binder_depth: usize, } impl PrintConfig { - pub(crate) fn new(tcx: TyCtxt<'_, '_, '_>) -> Self { + fn new(tcx: TyCtxt<'_, '_, '_>) -> Self { PrintConfig { is_debug: false, is_verbose: tcx.sess.verbose(), @@ -207,7 +82,7 @@ impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { pub(crate) fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) } - pub(crate) fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) + fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) where T: TypeFoldable<'tcx> { let mut collector = LateBoundRegionNameCollector(Default::default()); @@ -320,108 +195,6 @@ pub trait Printer: Sized { ) -> Result; } -/// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter: - Printer< - Error = fmt::Error, - Path = Self, - Region = Self, - Type = Self, - > + - fmt::Write -{ - /// Enter a nested print context, for pretty-printing - /// nested components in some larger context. - fn nest<'a, 'gcx, 'tcx, E>( - self: PrintCx<'a, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result, E> { - let printer = f(PrintCx { - tcx: self.tcx, - printer: self.printer, - config: self.config, - })?; - Ok(PrintCx { - tcx: self.tcx, - printer, - config: self.config, - }) - } - - /// Like `print_def_path` but for value paths. - fn print_value_path( - self: PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - ) -> Result { - self.print_def_path(def_id, substs, iter::empty()) - } - - /// Print `<...>` around what `f` prints. - fn generic_delimiters<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result; - - /// Return `true` if the region should be printed in path generic args - /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`. - fn always_print_region_in_paths( - self: &PrintCx<'_, '_, '_, Self>, - _region: ty::Region<'_>, - ) -> bool { - false - } - - // HACK(eddyb) Trying to print a lifetime might not print anything, which - // may need special handling in the caller (of `ty::RegionKind::print`). - // To avoid printing to a temporary string (which isn't even supported), - // the `print_region_outputs_anything` method can instead be used to - // determine this, ahead of time. - // - // NB: this must be kept in sync with the implementation of `print_region`. - fn print_region_outputs_anything( - self: &PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> bool; -} - -macro_rules! nest { - ($cx:ident, $closure:expr) => { - $cx = $cx.nest($closure)? - } -} - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always - // (but also some things just print a `DefId` generally so maybe we need this?) - fn guess_def_namespace(self, def_id: DefId) -> Namespace { - match self.def_key(def_id).disambiguated_data.data { - DefPathData::ValueNs(..) | - DefPathData::EnumVariant(..) | - DefPathData::Field(..) | - DefPathData::AnonConst | - DefPathData::ClosureExpr | - DefPathData::StructCtor => Namespace::ValueNS, - - DefPathData::MacroDef(..) => Namespace::MacroNS, - - _ => Namespace::TypeNS, - } - } - - /// Returns a string identifying this def-id. This string is - /// suitable for user output. - pub fn def_path_str(self, def_id: DefId) -> String { - let ns = self.guess_def_namespace(def_id); - debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); - let mut s = String::new(); - let _ = PrintCx::with(self, FmtPrinter::new(&mut s, ns), |cx| { - cx.print_def_path(def_id, None, iter::empty()) - }); - s - } -} - impl PrintCx<'a, 'gcx, 'tcx, P> { pub fn default_print_def_path( self, @@ -589,660 +362,3 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Float(_) => None, } } - -pub struct FmtPrinter { - pub(crate) fmt: F, - empty: bool, - in_value: bool, - pub region_highlight_mode: RegionHighlightMode, -} - -impl FmtPrinter { - pub fn new(fmt: F, ns: Namespace) -> Self { - FmtPrinter { - fmt, - empty: true, - in_value: ns == Namespace::ValueNS, - region_highlight_mode: RegionHighlightMode::default(), - } - } -} - -impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { - /// If possible, this returns a global path resolving to `def_id` that is visible - /// from at least one local module and returns true. If the crate defining `def_id` is - /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path( - mut self, - def_id: DefId, - ) -> Result<(P, bool), P::Error> { - debug!("try_print_visible_def_path: def_id={:?}", def_id); - - // If `def_id` is a direct or injected extern crate, return the - // path to the crate followed by the path to the item within the crate. - if def_id.index == CRATE_DEF_INDEX { - let cnum = def_id.krate; - - if cnum == LOCAL_CRATE { - return Ok((self.path_crate(cnum)?, true)); - } - - // In local mode, when we encounter a crate other than - // LOCAL_CRATE, execution proceeds in one of two ways: - // - // 1. for a direct dependency, where user added an - // `extern crate` manually, we put the `extern - // crate` as the parent. So you wind up with - // something relative to the current crate. - // 2. for an extern inferred from a path or an indirect crate, - // where there is no explicit `extern crate`, we just prepend - // the crate name. - match *self.tcx.extern_crate(def_id) { - Some(ExternCrate { - src: ExternCrateSource::Extern(def_id), - direct: true, - span, - .. - }) => { - debug!("try_print_visible_def_path: def_id={:?}", def_id); - return Ok((if !span.is_dummy() { - self.print_def_path(def_id, None, iter::empty())? - } else { - self.path_crate(cnum)? - }, true)); - } - None => { - return Ok((self.path_crate(cnum)?, true)); - } - _ => {}, - } - } - - if def_id.is_local() { - return Ok((self.printer, false)); - } - - let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); - - let mut cur_def_key = self.tcx.def_key(def_id); - debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); - - // For a UnitStruct or TupleStruct we want the name of its parent rather than . - if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { - let parent = DefId { - krate: def_id.krate, - index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), - }; - - cur_def_key = self.tcx.def_key(parent); - } - - let visible_parent = match visible_parent_map.get(&def_id).cloned() { - Some(parent) => parent, - None => return Ok((self.printer, false)), - }; - // HACK(eddyb) this uses `nest` to avoid knowing ahead of time whether - // the entire path will succeed or not. To support printers that do not - // implement `PrettyPrinter`, a `Vec` or linked list on the stack would - // need to be built, before starting to print anything. - let mut prefix_success = false; - nest!(self, |cx| { - let (printer, success) = cx.try_print_visible_def_path(visible_parent)?; - prefix_success = success; - Ok(printer) - }); - if !prefix_success { - return Ok((self.printer, false)); - }; - let actual_parent = self.tcx.parent(def_id); - - let data = cur_def_key.disambiguated_data.data; - debug!( - "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}", - data, visible_parent, actual_parent, - ); - - let symbol = match data { - // In order to output a path that could actually be imported (valid and visible), - // we need to handle re-exports correctly. - // - // For example, take `std::os::unix::process::CommandExt`, this trait is actually - // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). - // - // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is - // private so the "true" path to `CommandExt` isn't accessible. - // - // In this case, the `visible_parent_map` will look something like this: - // - // (child) -> (parent) - // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` - // `std::sys::unix::ext::process` -> `std::sys::unix::ext` - // `std::sys::unix::ext` -> `std::os` - // - // This is correct, as the visible parent of `std::sys::unix::ext` is in fact - // `std::os`. - // - // When printing the path to `CommandExt` and looking at the `cur_def_key` that - // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go - // to the parent - resulting in a mangled path like - // `std::os::ext::process::CommandExt`. - // - // Instead, we must detect that there was a re-export and instead print `unix` - // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To - // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with - // the visible parent (`std::os`). If these do not match, then we iterate over - // the children of the visible parent (as was done when computing - // `visible_parent_map`), looking for the specific child we currently have and then - // have access to the re-exported name. - DefPathData::Module(actual_name) | - DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { - visible_parent - .and_then(|parent| { - self.tcx.item_children(parent) - .iter() - .find(|child| child.def.def_id() == cur_def) - .map(|child| child.ident.as_str()) - }) - .unwrap_or_else(|| actual_name.as_str()) - } - _ => { - data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { - // Re-exported `extern crate` (#43189). - if let DefPathData::CrateRoot = data { - self.tcx.original_crate_name(def_id.krate).as_str() - } else { - Symbol::intern("").as_str() - } - }) - }, - }; - debug!("try_print_visible_def_path: symbol={:?}", symbol); - Ok((self.path_append(|cx| Ok(cx.printer), &symbol)?, true)) - } - - pub fn pretty_path_qualified( - self, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - if trait_ref.is_none() { - // Inherent impls. Try to print `Foo::bar` for an inherent - // impl on `Foo`, but fallback to `::bar` if self-type is - // anything other than a simple path. - match self_ty.sty { - ty::Adt(..) | ty::Foreign(_) | - ty::Bool | ty::Char | ty::Str | - ty::Int(_) | ty::Uint(_) | ty::Float(_) => { - return self_ty.print_display(self); - } - - _ => {} - } - } - - self.generic_delimiters(|mut cx| { - nest!(cx, |cx| self_ty.print_display(cx)); - if let Some(trait_ref) = trait_ref { - write!(cx.printer, " as ")?; - nest!(cx, |cx| trait_ref.print_display(cx)); - } - Ok(cx.printer) - }) - } - - pub fn pretty_path_append_impl( - mut self, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, P>, - ) -> Result, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - nest!(self, print_prefix); - - self.generic_delimiters(|mut cx| { - write!(cx.printer, "impl ")?; - if let Some(trait_ref) = trait_ref { - nest!(cx, |cx| trait_ref.print_display(cx)); - write!(cx.printer, " for ")?; - } - nest!(cx, |cx| self_ty.print_display(cx)); - - Ok(cx.printer) - }) - } - - pub fn pretty_path_generic_args( - mut self, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, P>, - ) -> Result, - params: &[ty::GenericParamDef], - substs: &'tcx Substs<'tcx>, - projections: impl Iterator>, - ) -> Result { - nest!(self, |cx| print_prefix(cx)); - - // Don't print `'_` if there's no printed region. - let print_regions = params.iter().any(|param| { - match substs[param.index as usize].unpack() { - UnpackedKind::Lifetime(r) => { - self.always_print_region_in_paths(r) || - self.print_region_outputs_anything(r) - } - _ => false, - } - }); - - // Don't print args that are the defaults of their respective parameters. - let num_supplied_defaults = if self.config.is_verbose { - 0 - } else { - params.iter().rev().take_while(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => false, - ty::GenericParamDefKind::Type { has_default, .. } => { - has_default && substs[param.index as usize] == Kind::from( - self.tcx.type_of(param.def_id).subst(self.tcx, substs) - ) - } - } - }).count() - }; - - let params = ¶ms[..params.len() - num_supplied_defaults]; - let mut args = params.iter().map(|param| { - substs[param.index as usize].unpack() - }).filter(|arg| { - match arg { - UnpackedKind::Lifetime(_) => print_regions, - _ => true, - } - }); - let arg0 = args.next(); - - let mut projections = projections; - let projection0 = projections.next(); - - if arg0.is_none() && projection0.is_none() { - return Ok(self.printer); - } - - self.generic_delimiters(|mut cx| { - let mut empty = true; - let mut maybe_comma = |cx: &mut Self| { - if empty { - empty = false; - Ok(()) - } else { - write!(cx.printer, ", ") - } - }; - - for arg in arg0.into_iter().chain(args) { - maybe_comma(&mut cx)?; - - match arg { - UnpackedKind::Lifetime(region) => { - if !cx.print_region_outputs_anything(region) { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - write!(cx.printer, "'_")?; - } else { - nest!(cx, |cx| region.print_display(cx)); - } - } - UnpackedKind::Type(ty) => { - nest!(cx, |cx| ty.print_display(cx)); - } - } - } - - for projection in projection0.into_iter().chain(projections) { - maybe_comma(&mut cx)?; - - write!(cx.printer, "{}=", - cx.tcx.associated_item(projection.item_def_id).ident)?; - nest!(cx, |cx| projection.ty.print_display(cx)); - } - - Ok(cx.printer) - }) - } -} - -impl fmt::Write for FmtPrinter { - fn write_str(&mut self, s: &str) -> fmt::Result { - self.empty &= s.is_empty(); - self.fmt.write_str(s) - } -} - -impl Printer for FmtPrinter { - type Error = fmt::Error; - - type Path = Self; - type Region = Self; - type Type = Self; - - fn print_def_path( - mut self: PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - projections: impl Iterator>, - ) -> Result { - // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` - // both here and in `default_print_def_path`. - let generics = substs.map(|_| self.tcx.generics_of(def_id)); - if generics.as_ref().and_then(|g| g.parent).is_none() { - let mut visible_path_success = false; - nest!(self, |cx| { - let (printer, success) = cx.try_print_visible_def_path(def_id)?; - visible_path_success = success; - Ok(printer) - }); - if visible_path_success { - return if let (Some(generics), Some(substs)) = (generics, substs) { - let has_own_self = generics.has_self && generics.parent_count == 0; - let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(|cx| Ok(cx.printer), params, substs, projections) - } else { - Ok(self.printer) - }; - } - } - - let key = self.tcx.def_key(def_id); - if let DefPathData::Impl = key.disambiguated_data.data { - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = - !def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; - - if !use_types { - // If no type info is available, fall back to - // pretty printing some span information. This should - // only occur very early in the compiler pipeline. - let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let span = self.tcx.def_span(def_id); - return self.path_append( - |cx| cx.print_def_path(parent_def_id, None, iter::empty()), - &format!("", span), - ); - } - } - - self.default_print_def_path(def_id, substs, projections) - } - - fn print_region( - mut self: PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> Result { - // Watch out for region highlights. - let highlight = self.printer.region_highlight_mode; - if let Some(n) = highlight.region_highlighted(region) { - write!(self.printer, "'{}", n)?; - return Ok(self.printer); - } - - if self.config.is_verbose { - return region.print_debug(self); - } - - // These printouts are concise. They do not contain all the information - // the user might want to diagnose an error, but there is basically no way - // to fit that into a short string. Hence the recommendation to use - // `explain_region()` or `note_and_explain_region()`. - match *region { - ty::ReEarlyBound(ref data) => { - if data.name != "'_" { - write!(self.printer, "{}", data.name)?; - } - } - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { - write!(self.printer, "{}", name)?; - return Ok(self.printer); - } - } - - if let Some((region, counter)) = highlight.highlight_bound_region { - if br == region { - write!(self.printer, "'{}", counter)?; - } - } - } - ty::ReScope(scope) if self.config.identify_regions => { - match scope.data { - region::ScopeData::Node => - write!(self.printer, "'{}s", scope.item_local_id().as_usize())?, - region::ScopeData::CallSite => - write!(self.printer, "'{}cs", scope.item_local_id().as_usize())?, - region::ScopeData::Arguments => - write!(self.printer, "'{}as", scope.item_local_id().as_usize())?, - region::ScopeData::Destruction => - write!(self.printer, "'{}ds", scope.item_local_id().as_usize())?, - region::ScopeData::Remainder(first_statement_index) => write!(self.printer, - "'{}_{}rs", - scope.item_local_id().as_usize(), - first_statement_index.index() - )?, - } - } - ty::ReVar(region_vid) if self.config.identify_regions => { - write!(self.printer, "{:?}", region_vid)?; - } - ty::ReVar(_) => {} - ty::ReScope(_) | - ty::ReErased => {} - ty::ReStatic => write!(self.printer, "'static")?, - ty::ReEmpty => write!(self.printer, "'")?, - - // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => write!(self.printer, "{:?}", vid)?, - } - - Ok(self.printer) - } - - fn print_type( - self: PrintCx<'_, '_, 'tcx, Self>, - ty: Ty<'tcx>, - ) -> Result { - self.pretty_print_type(ty) - } - - fn path_crate( - mut self: PrintCx<'_, '_, '_, Self>, - cnum: CrateNum, - ) -> Result { - if cnum == LOCAL_CRATE { - if self.tcx.sess.rust_2018() { - // We add the `crate::` keyword on Rust 2018, only when desired. - if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - write!(self.printer, "{}", keywords::Crate.name())?; - } - } - Ok(self.printer) - } else { - write!(self.printer, "{}", self.tcx.crate_name(cnum))?; - Ok(self.printer) - } - } - fn path_qualified( - self: PrintCx<'_, '_, 'tcx, Self>, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - self.pretty_path_qualified(self_ty, trait_ref) - } - - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - self.pretty_path_append_impl(|cx| { - let mut printer = print_prefix(cx)?; - - // HACK(eddyb) this accounts for `generic_delimiters` - // printing `::<` instead of `<` if `in_value` is set. - if !printer.empty && !printer.in_value { - write!(printer, "::")?; - } - - Ok(printer) - }, self_ty, trait_ref) - } - fn path_append<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, - text: &str, - ) -> Result { - let mut printer = print_prefix(self)?; - - // FIXME(eddyb) `text` should never be empty, but it - // currently is for `extern { ... }` "foreign modules". - if !text.is_empty() { - if !printer.empty { - write!(printer, "::")?; - } - write!(printer, "{}", text)?; - } - - Ok(printer) - } - fn path_generic_args<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, - params: &[ty::GenericParamDef], - substs: &'tcx Substs<'tcx>, - projections: impl Iterator>, - ) -> Result { - self.pretty_path_generic_args(print_prefix, params, substs, projections) - } -} - -impl PrettyPrinter for FmtPrinter { - fn nest<'a, 'gcx, 'tcx, E>( - mut self: PrintCx<'a, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result, E> { - let was_empty = std::mem::replace(&mut self.printer.empty, true); - let mut printer = f(PrintCx { - tcx: self.tcx, - printer: self.printer, - config: self.config, - })?; - printer.empty &= was_empty; - Ok(PrintCx { - tcx: self.tcx, - printer, - config: self.config, - }) - } - - fn print_value_path( - mut self: PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - ) -> Result { - let was_in_value = std::mem::replace(&mut self.printer.in_value, true); - let mut printer = self.print_def_path(def_id, substs, iter::empty())?; - printer.in_value = was_in_value; - - Ok(printer) - } - - fn generic_delimiters<'gcx, 'tcx>( - mut self: PrintCx<'_, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result { - if !self.printer.empty && self.printer.in_value { - write!(self.printer, "::<")?; - } else { - write!(self.printer, "<")?; - } - - let was_in_value = std::mem::replace(&mut self.printer.in_value, false); - let mut printer = f(self)?; - printer.in_value = was_in_value; - - write!(printer, ">")?; - Ok(printer) - } - - fn always_print_region_in_paths( - self: &PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> bool { - *region != ty::ReErased - } - - fn print_region_outputs_anything( - self: &PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> bool { - let highlight = self.printer.region_highlight_mode; - if highlight.region_highlighted(region).is_some() { - return true; - } - - if self.config.is_verbose { - return true; - } - - match *region { - ty::ReEarlyBound(ref data) => { - data.name != "" && data.name != "'_" - } - - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { - return true; - } - } - - if let Some((region, _)) = highlight.highlight_bound_region { - if br == region { - return true; - } - } - - false - } - - ty::ReScope(_) | - ty::ReVar(_) if self.config.identify_regions => true, - - ty::ReVar(_) | - ty::ReScope(_) | - ty::ReErased => false, - - ty::ReStatic | - ty::ReEmpty | - ty::ReClosureBound(_) => true, - } - } -} diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs new file mode 100644 index 0000000000000..6d64f56781ad5 --- /dev/null +++ b/src/librustc/ty/print/pretty.rs @@ -0,0 +1,1294 @@ +use hir; +use hir::def::Namespace; +use hir::map::DefPathData; +use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use middle::region; +use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use ty::subst::{Kind, Subst, Substs, UnpackedKind}; +use middle::cstore::{ExternCrate, ExternCrateSource}; +use syntax::ast; +use syntax::symbol::{keywords, Symbol}; + +use syntax::symbol::InternedString; + +use std::cell::Cell; +use std::fmt::{self, Write as _}; +use std::iter; + +// `pretty` is a separate module only for organization. +use super::*; + +macro_rules! nest { + ($closure:expr) => { + scoped_cx!() = scoped_cx!().nest($closure)? + } +} +macro_rules! print_inner { + (write ($($data:expr),+)) => { + write!(scoped_cx!().printer, $($data),+)? + }; + ($kind:ident ($data:expr)) => { + nest!(|cx| $data.$kind(cx)) + }; +} +macro_rules! p { + ($($kind:ident $data:tt),+) => { + { + $(print_inner!($kind $data));+ + } + }; +} +macro_rules! define_scoped_cx { + ($cx:ident) => { + #[allow(unused_macros)] + macro_rules! scoped_cx { + () => ($cx) + } + }; +} + +thread_local! { + static FORCE_IMPL_FILENAME_LINE: Cell = Cell::new(false); + static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); +} + +/// Force us to name impls with just the filename/line number. We +/// normally try to use types. But at some points, notably while printing +/// cycle errors, this can result in extra or suboptimal error output, +/// so this variable disables that check. +pub fn with_forced_impl_filename_line R, R>(f: F) -> R { + FORCE_IMPL_FILENAME_LINE.with(|force| { + let old = force.get(); + force.set(true); + let result = f(); + force.set(old); + result + }) +} + +/// Add the `crate::` prefix to paths where appropriate. +pub fn with_crate_prefix R, R>(f: F) -> R { + SHOULD_PREFIX_WITH_CRATE.with(|flag| { + let old = flag.get(); + flag.set(true); + let result = f(); + flag.set(old); + result + }) +} + +/// The "region highlights" are used to control region printing during +/// specific error messages. When a "region highlight" is enabled, it +/// gives an alternate way to print specific regions. For now, we +/// always print those regions using a number, so something like `'0`. +/// +/// Regions not selected by the region highlight mode are presently +/// unaffected. +#[derive(Copy, Clone, Default)] +pub struct RegionHighlightMode { + /// If enabled, when we see the selected region, use `"'N"` + /// instead of the ordinary behavior. + highlight_regions: [Option<(ty::RegionKind, usize)>; 3], + + /// If enabled, when printing a "free region" that originated from + /// the given `ty::BoundRegion`, print it as `'1`. Free regions that would ordinarily + /// have names print as normal. + /// + /// This is used when you have a signature like `fn foo(x: &u32, + /// y: &'a u32)` and we want to give a name to the region of the + /// reference `x`. + highlight_bound_region: Option<(ty::BoundRegion, usize)>, +} + +impl RegionHighlightMode { + /// If `region` and `number` are both `Some`, invoke + /// `highlighting_region`. + pub fn maybe_highlighting_region( + &mut self, + region: Option>, + number: Option, + ) { + if let Some(k) = region { + if let Some(n) = number { + self.highlighting_region(k, n); + } + } + } + + /// Highlight the region inference variable `vid` as `'N`. + pub fn highlighting_region( + &mut self, + region: ty::Region<'_>, + number: usize, + ) { + let num_slots = self.highlight_regions.len(); + let first_avail_slot = self.highlight_regions.iter_mut() + .filter(|s| s.is_none()) + .next() + .unwrap_or_else(|| { + bug!( + "can only highlight {} placeholders at a time", + num_slots, + ) + }); + *first_avail_slot = Some((*region, number)); + } + + /// Convenience wrapper for `highlighting_region` + pub fn highlighting_region_vid( + &mut self, + vid: ty::RegionVid, + number: usize, + ) { + self.highlighting_region(&ty::ReVar(vid), number) + } + + /// Returns `Some(n)` with the number to use for the given region, + /// if any. + fn region_highlighted(&self, region: ty::Region<'_>) -> Option { + self + .highlight_regions + .iter() + .filter_map(|h| match h { + Some((r, n)) if r == region => Some(*n), + _ => None, + }) + .next() + } + + /// Highlight the given bound region. + /// We can only highlight one bound region at a time. See + /// the field `highlight_bound_region` for more detailed notes. + pub fn highlighting_bound_region( + &mut self, + br: ty::BoundRegion, + number: usize, + ) { + assert!(self.highlight_bound_region.is_none()); + self.highlight_bound_region = Some((br, number)); + } +} + +/// Trait for printers that pretty-print using `fmt::Write` to the printer. +pub trait PrettyPrinter: + Printer< + Error = fmt::Error, + Path = Self, + Region = Self, + Type = Self, + > + + fmt::Write +{ + /// Enter a nested print context, for pretty-printing + /// nested components in some larger context. + fn nest<'a, 'gcx, 'tcx, E>( + self: PrintCx<'a, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result, E> { + let printer = f(PrintCx { + tcx: self.tcx, + printer: self.printer, + config: self.config, + })?; + Ok(PrintCx { + tcx: self.tcx, + printer, + config: self.config, + }) + } + + /// Like `print_def_path` but for value paths. + fn print_value_path( + self: PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + ) -> Result { + self.print_def_path(def_id, substs, iter::empty()) + } + + /// Print `<...>` around what `f` prints. + fn generic_delimiters<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result; + + /// Return `true` if the region should be printed in path generic args + /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`. + fn always_print_region_in_paths( + self: &PrintCx<'_, '_, '_, Self>, + _region: ty::Region<'_>, + ) -> bool { + false + } + + // HACK(eddyb) Trying to print a lifetime might not print anything, which + // may need special handling in the caller (of `ty::RegionKind::print`). + // To avoid printing to a temporary string (which isn't even supported), + // the `print_region_outputs_anything` method can instead be used to + // determine this, ahead of time. + // + // NB: this must be kept in sync with the implementation of `print_region`. + fn print_region_outputs_anything( + self: &PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> bool; +} + +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always + // (but also some things just print a `DefId` generally so maybe we need this?) + fn guess_def_namespace(self, def_id: DefId) -> Namespace { + match self.def_key(def_id).disambiguated_data.data { + DefPathData::ValueNs(..) | + DefPathData::EnumVariant(..) | + DefPathData::Field(..) | + DefPathData::AnonConst | + DefPathData::ClosureExpr | + DefPathData::StructCtor => Namespace::ValueNS, + + DefPathData::MacroDef(..) => Namespace::MacroNS, + + _ => Namespace::TypeNS, + } + } + + /// Returns a string identifying this def-id. This string is + /// suitable for user output. + pub fn def_path_str(self, def_id: DefId) -> String { + let ns = self.guess_def_namespace(def_id); + debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); + let mut s = String::new(); + let _ = PrintCx::with(self, FmtPrinter::new(&mut s, ns), |cx| { + cx.print_def_path(def_id, None, iter::empty()) + }); + s + } +} + +pub struct FmtPrinter { + fmt: F, + empty: bool, + in_value: bool, + pub region_highlight_mode: RegionHighlightMode, +} + +impl FmtPrinter { + pub fn new(fmt: F, ns: Namespace) -> Self { + FmtPrinter { + fmt, + empty: true, + in_value: ns == Namespace::ValueNS, + region_highlight_mode: RegionHighlightMode::default(), + } + } +} + +impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { + /// If possible, this returns a global path resolving to `def_id` that is visible + /// from at least one local module and returns true. If the crate defining `def_id` is + /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. + fn try_print_visible_def_path( + mut self, + def_id: DefId, + ) -> Result<(P, bool), P::Error> { + define_scoped_cx!(self); + + debug!("try_print_visible_def_path: def_id={:?}", def_id); + + // If `def_id` is a direct or injected extern crate, return the + // path to the crate followed by the path to the item within the crate. + if def_id.index == CRATE_DEF_INDEX { + let cnum = def_id.krate; + + if cnum == LOCAL_CRATE { + return Ok((self.path_crate(cnum)?, true)); + } + + // In local mode, when we encounter a crate other than + // LOCAL_CRATE, execution proceeds in one of two ways: + // + // 1. for a direct dependency, where user added an + // `extern crate` manually, we put the `extern + // crate` as the parent. So you wind up with + // something relative to the current crate. + // 2. for an extern inferred from a path or an indirect crate, + // where there is no explicit `extern crate`, we just prepend + // the crate name. + match *self.tcx.extern_crate(def_id) { + Some(ExternCrate { + src: ExternCrateSource::Extern(def_id), + direct: true, + span, + .. + }) => { + debug!("try_print_visible_def_path: def_id={:?}", def_id); + return Ok((if !span.is_dummy() { + self.print_def_path(def_id, None, iter::empty())? + } else { + self.path_crate(cnum)? + }, true)); + } + None => { + return Ok((self.path_crate(cnum)?, true)); + } + _ => {}, + } + } + + if def_id.is_local() { + return Ok((self.printer, false)); + } + + let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); + + let mut cur_def_key = self.tcx.def_key(def_id); + debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); + + // For a UnitStruct or TupleStruct we want the name of its parent rather than . + if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { + let parent = DefId { + krate: def_id.krate, + index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), + }; + + cur_def_key = self.tcx.def_key(parent); + } + + let visible_parent = match visible_parent_map.get(&def_id).cloned() { + Some(parent) => parent, + None => return Ok((self.printer, false)), + }; + // HACK(eddyb) this uses `nest` to avoid knowing ahead of time whether + // the entire path will succeed or not. To support printers that do not + // implement `PrettyPrinter`, a `Vec` or linked list on the stack would + // need to be built, before starting to print anything. + let mut prefix_success = false; + nest!(|cx| { + let (printer, success) = cx.try_print_visible_def_path(visible_parent)?; + prefix_success = success; + Ok(printer) + }); + if !prefix_success { + return Ok((self.printer, false)); + }; + let actual_parent = self.tcx.parent(def_id); + debug!( + "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}", + visible_parent, actual_parent, + ); + + let data = cur_def_key.disambiguated_data.data; + debug!( + "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}", + data, visible_parent, actual_parent, + ); + + let symbol = match data { + // In order to output a path that could actually be imported (valid and visible), + // we need to handle re-exports correctly. + // + // For example, take `std::os::unix::process::CommandExt`, this trait is actually + // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). + // + // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is + // private so the "true" path to `CommandExt` isn't accessible. + // + // In this case, the `visible_parent_map` will look something like this: + // + // (child) -> (parent) + // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` + // `std::sys::unix::ext::process` -> `std::sys::unix::ext` + // `std::sys::unix::ext` -> `std::os` + // + // This is correct, as the visible parent of `std::sys::unix::ext` is in fact + // `std::os`. + // + // When printing the path to `CommandExt` and looking at the `cur_def_key` that + // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go + // to the parent - resulting in a mangled path like + // `std::os::ext::process::CommandExt`. + // + // Instead, we must detect that there was a re-export and instead print `unix` + // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To + // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with + // the visible parent (`std::os`). If these do not match, then we iterate over + // the children of the visible parent (as was done when computing + // `visible_parent_map`), looking for the specific child we currently have and then + // have access to the re-exported name. + DefPathData::Module(actual_name) | + DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { + visible_parent + .and_then(|parent| { + self.tcx.item_children(parent) + .iter() + .find(|child| child.def.def_id() == cur_def) + .map(|child| child.ident.as_str()) + }) + .unwrap_or_else(|| actual_name.as_str()) + } + _ => { + data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { + // Re-exported `extern crate` (#43189). + if let DefPathData::CrateRoot = data { + self.tcx.original_crate_name(def_id.krate).as_str() + } else { + Symbol::intern("").as_str() + } + }) + }, + }; + debug!("try_print_visible_def_path: symbol={:?}", symbol); + Ok((self.path_append(|cx| Ok(cx.printer), &symbol)?, true)) + } + + pub fn pretty_path_qualified( + self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + if trait_ref.is_none() { + // Inherent impls. Try to print `Foo::bar` for an inherent + // impl on `Foo`, but fallback to `::bar` if self-type is + // anything other than a simple path. + match self_ty.sty { + ty::Adt(..) | ty::Foreign(_) | + ty::Bool | ty::Char | ty::Str | + ty::Int(_) | ty::Uint(_) | ty::Float(_) => { + return self_ty.print_display(self); + } + + _ => {} + } + } + + self.generic_delimiters(|mut cx| { + define_scoped_cx!(cx); + + p!(print_display(self_ty)); + if let Some(trait_ref) = trait_ref { + p!(write(" as "), print_display(trait_ref)); + } + Ok(cx.printer) + }) + } + + pub fn pretty_path_append_impl( + mut self, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, P>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self = self.nest(print_prefix)?; + + self.generic_delimiters(|mut cx| { + define_scoped_cx!(cx); + + p!(write("impl ")); + if let Some(trait_ref) = trait_ref { + p!(print_display(trait_ref), write(" for ")); + } + p!(print_display(self_ty)); + + Ok(cx.printer) + }) + } + + pub fn pretty_path_generic_args( + mut self, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, P>, + ) -> Result, + params: &[ty::GenericParamDef], + substs: &'tcx Substs<'tcx>, + projections: impl Iterator>, + ) -> Result { + self = self.nest(print_prefix)?; + + // Don't print `'_` if there's no printed region. + let print_regions = params.iter().any(|param| { + match substs[param.index as usize].unpack() { + UnpackedKind::Lifetime(r) => { + self.always_print_region_in_paths(r) || + self.print_region_outputs_anything(r) + } + _ => false, + } + }); + + // Don't print args that are the defaults of their respective parameters. + let num_supplied_defaults = if self.config.is_verbose { + 0 + } else { + params.iter().rev().take_while(|param| { + match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default && substs[param.index as usize] == Kind::from( + self.tcx.type_of(param.def_id).subst(self.tcx, substs) + ) + } + } + }).count() + }; + + let params = ¶ms[..params.len() - num_supplied_defaults]; + let mut args = params.iter().map(|param| { + substs[param.index as usize] + }).filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + let arg0 = args.next(); + + let mut projections = projections; + let projection0 = projections.next(); + + if arg0.is_none() && projection0.is_none() { + return Ok(self.printer); + } + + self.generic_delimiters(|mut cx| { + define_scoped_cx!(cx); + + let mut empty = true; + let mut maybe_comma = |cx: &mut Self| { + if empty { + empty = false; + Ok(()) + } else { + write!(cx.printer, ", ") + } + }; + + for arg in arg0.into_iter().chain(args) { + maybe_comma(&mut cx)?; + + if let UnpackedKind::Lifetime(region) = arg.unpack() { + if !cx.print_region_outputs_anything(region) { + // This happens when the value of the region + // parameter is not easily serialized. This may be + // because the user omitted it in the first place, + // or because it refers to some block in the code, + // etc. I'm not sure how best to serialize this. + p!(write("'_")); + + continue; + } + } + + p!(print_display(arg)); + } + + for projection in projection0.into_iter().chain(projections) { + maybe_comma(&mut cx)?; + + p!(write("{}=", cx.tcx.associated_item(projection.item_def_id).ident), + print_display(projection.ty)); + } + + Ok(cx.printer) + }) + } +} + +impl fmt::Write for FmtPrinter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.empty &= s.is_empty(); + self.fmt.write_str(s) + } +} + +impl Printer for FmtPrinter { + type Error = fmt::Error; + + type Path = Self; + type Region = Self; + type Type = Self; + + fn print_def_path( + mut self: PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + projections: impl Iterator>, + ) -> Result { + // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` + // both here and in `default_print_def_path`. + let generics = substs.map(|_| self.tcx.generics_of(def_id)); + if generics.as_ref().and_then(|g| g.parent).is_none() { + let mut visible_path_success = false; + self = self.nest(|cx| { + let (printer, success) = cx.try_print_visible_def_path(def_id)?; + visible_path_success = success; + Ok(printer) + })?; + if visible_path_success { + return if let (Some(generics), Some(substs)) = (generics, substs) { + let has_own_self = generics.has_self && generics.parent_count == 0; + let params = &generics.params[has_own_self as usize..]; + self.path_generic_args(|cx| Ok(cx.printer), params, substs, projections) + } else { + Ok(self.printer) + }; + } + } + + let key = self.tcx.def_key(def_id); + if let DefPathData::Impl = key.disambiguated_data.data { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = + !def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; + + if !use_types { + // If no type info is available, fall back to + // pretty printing some span information. This should + // only occur very early in the compiler pipeline. + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let span = self.tcx.def_span(def_id); + return self.path_append( + |cx| cx.print_def_path(parent_def_id, None, iter::empty()), + &format!("", span), + ); + } + } + + self.default_print_def_path(def_id, substs, projections) + } + + fn print_region( + self: PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> Result { + self.pretty_print_region(region) + } + + fn print_type( + self: PrintCx<'_, '_, 'tcx, Self>, + ty: Ty<'tcx>, + ) -> Result { + self.pretty_print_type(ty) + } + + fn path_crate( + mut self: PrintCx<'_, '_, '_, Self>, + cnum: CrateNum, + ) -> Result { + if cnum == LOCAL_CRATE { + if self.tcx.sess.rust_2018() { + // We add the `crate::` keyword on Rust 2018, only when desired. + if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + write!(self.printer, "{}", keywords::Crate.name())?; + } + } + Ok(self.printer) + } else { + write!(self.printer, "{}", self.tcx.crate_name(cnum))?; + Ok(self.printer) + } + } + fn path_qualified( + self: PrintCx<'_, '_, 'tcx, Self>, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.pretty_path_qualified(self_ty, trait_ref) + } + + fn path_append_impl<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.pretty_path_append_impl(|cx| { + let mut printer = print_prefix(cx)?; + + // HACK(eddyb) this accounts for `generic_delimiters` + // printing `::<` instead of `<` if `in_value` is set. + if !printer.empty && !printer.in_value { + write!(printer, "::")?; + } + + Ok(printer) + }, self_ty, trait_ref) + } + fn path_append<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + text: &str, + ) -> Result { + let mut printer = print_prefix(self)?; + + // FIXME(eddyb) `text` should never be empty, but it + // currently is for `extern { ... }` "foreign modules". + if !text.is_empty() { + if !printer.empty { + write!(printer, "::")?; + } + write!(printer, "{}", text)?; + } + + Ok(printer) + } + fn path_generic_args<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + params: &[ty::GenericParamDef], + substs: &'tcx Substs<'tcx>, + projections: impl Iterator>, + ) -> Result { + self.pretty_path_generic_args(print_prefix, params, substs, projections) + } +} + +impl PrettyPrinter for FmtPrinter { + fn nest<'a, 'gcx, 'tcx, E>( + mut self: PrintCx<'a, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result, E> { + let was_empty = std::mem::replace(&mut self.printer.empty, true); + let mut printer = f(PrintCx { + tcx: self.tcx, + printer: self.printer, + config: self.config, + })?; + printer.empty &= was_empty; + Ok(PrintCx { + tcx: self.tcx, + printer, + config: self.config, + }) + } + + fn print_value_path( + mut self: PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + ) -> Result { + let was_in_value = std::mem::replace(&mut self.printer.in_value, true); + let mut printer = self.print_def_path(def_id, substs, iter::empty())?; + printer.in_value = was_in_value; + + Ok(printer) + } + + fn generic_delimiters<'gcx, 'tcx>( + mut self: PrintCx<'_, 'gcx, 'tcx, Self>, + f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + ) -> Result { + if !self.printer.empty && self.printer.in_value { + write!(self.printer, "::<")?; + } else { + write!(self.printer, "<")?; + } + + let was_in_value = std::mem::replace(&mut self.printer.in_value, false); + let mut printer = f(self)?; + printer.in_value = was_in_value; + + write!(printer, ">")?; + Ok(printer) + } + + fn always_print_region_in_paths( + self: &PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> bool { + *region != ty::ReErased + } + + fn print_region_outputs_anything( + self: &PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> bool { + let highlight = self.printer.region_highlight_mode; + if highlight.region_highlighted(region).is_some() { + return true; + } + + if self.config.is_verbose { + return true; + } + + match *region { + ty::ReEarlyBound(ref data) => { + data.name != "" && data.name != "'_" + } + + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + return true; + } + } + + if let Some((region, _)) = highlight.highlight_bound_region { + if br == region { + return true; + } + } + + false + } + + ty::ReScope(_) | + ty::ReVar(_) if self.config.identify_regions => true, + + ty::ReVar(_) | + ty::ReScope(_) | + ty::ReErased => false, + + ty::ReStatic | + ty::ReEmpty | + ty::ReClosureBound(_) => true, + } + } +} + +// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`. +impl FmtPrinter { + pub fn pretty_print_region( + mut self: PrintCx<'_, '_, '_, Self>, + region: ty::Region<'_>, + ) -> Result { + define_scoped_cx!(self); + + // Watch out for region highlights. + let highlight = self.printer.region_highlight_mode; + if let Some(n) = highlight.region_highlighted(region) { + p!(write("'{}", n)); + return Ok(self.printer); + } + + if self.config.is_verbose { + return region.print_debug(self); + } + + // These printouts are concise. They do not contain all the information + // the user might want to diagnose an error, but there is basically no way + // to fit that into a short string. Hence the recommendation to use + // `explain_region()` or `note_and_explain_region()`. + match *region { + ty::ReEarlyBound(ref data) => { + if data.name != "'_" { + p!(write("{}", data.name)); + } + } + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + p!(write("{}", name)); + return Ok(self.printer); + } + } + + if let Some((region, counter)) = highlight.highlight_bound_region { + if br == region { + p!(write("'{}", counter)); + } + } + } + ty::ReScope(scope) if self.config.identify_regions => { + match scope.data { + region::ScopeData::Node => + p!(write("'{}s", scope.item_local_id().as_usize())), + region::ScopeData::CallSite => + p!(write("'{}cs", scope.item_local_id().as_usize())), + region::ScopeData::Arguments => + p!(write("'{}as", scope.item_local_id().as_usize())), + region::ScopeData::Destruction => + p!(write("'{}ds", scope.item_local_id().as_usize())), + region::ScopeData::Remainder(first_statement_index) => p!(write( + "'{}_{}rs", + scope.item_local_id().as_usize(), + first_statement_index.index() + )), + } + } + ty::ReVar(region_vid) if self.config.identify_regions => { + p!(write("{:?}", region_vid)); + } + ty::ReVar(_) => {} + ty::ReScope(_) | + ty::ReErased => {} + ty::ReStatic => p!(write("'static")), + ty::ReEmpty => p!(write("'")), + + // The user should never encounter these in unsubstituted form. + ty::ReClosureBound(vid) => p!(write("{:?}", vid)), + } + + Ok(self.printer) + } +} + +impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { + pub fn pretty_print_type( + mut self, + ty: Ty<'tcx>, + ) -> Result { + define_scoped_cx!(self); + + match ty.sty { + ty::Bool => p!(write("bool")), + ty::Char => p!(write("char")), + ty::Int(t) => p!(write("{}", t.ty_to_string())), + ty::Uint(t) => p!(write("{}", t.ty_to_string())), + ty::Float(t) => p!(write("{}", t.ty_to_string())), + ty::RawPtr(ref tm) => { + p!(write("*{} ", match tm.mutbl { + hir::MutMutable => "mut", + hir::MutImmutable => "const", + })); + p!(print(tm.ty)) + } + ty::Ref(r, ty, mutbl) => { + p!(write("&")); + if self.print_region_outputs_anything(r) { + p!(print_display(r), write(" ")); + } + p!(print(ty::TypeAndMut { ty, mutbl })) + } + ty::Never => p!(write("!")), + ty::Tuple(ref tys) => { + p!(write("(")); + let mut tys = tys.iter(); + if let Some(&ty) = tys.next() { + p!(print(ty), write(",")); + if let Some(&ty) = tys.next() { + p!(write(" "), print(ty)); + for &ty in tys { + p!(write(", "), print(ty)); + } + } + } + p!(write(")")) + } + ty::FnDef(def_id, substs) => { + let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); + p!(print(sig), write(" {{")); + nest!(|cx| cx.print_value_path(def_id, Some(substs))); + p!(write("}}")) + } + ty::FnPtr(ref bare_fn) => { + p!(print(bare_fn)) + } + ty::Infer(infer_ty) => p!(write("{}", infer_ty)), + ty::Error => p!(write("[type error]")), + ty::Param(ref param_ty) => p!(write("{}", param_ty)), + ty::Bound(debruijn, bound_ty) => { + match bound_ty.kind { + ty::BoundTyKind::Anon => { + if debruijn == ty::INNERMOST { + p!(write("^{}", bound_ty.var.index())) + } else { + p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) + } + } + + ty::BoundTyKind::Param(p) => p!(write("{}", p)), + } + } + ty::Adt(def, substs) => { + nest!(|cx| cx.print_def_path(def.did, Some(substs), iter::empty())); + } + ty::Dynamic(data, r) => { + let print_r = self.print_region_outputs_anything(r); + if print_r { + p!(write("(")); + } + p!(write("dyn "), print(data)); + if print_r { + p!(write(" + "), print_display(r), write(")")); + } + } + ty::Foreign(def_id) => { + nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); + } + ty::Projection(ref data) => p!(print(data)), + ty::UnnormalizedProjection(ref data) => { + p!(write("Unnormalized("), print(data), write(")")) + } + ty::Placeholder(placeholder) => { + p!(write("Placeholder({:?})", placeholder)) + } + ty::Opaque(def_id, substs) => { + if self.config.is_verbose { + p!(write("Opaque({:?}, {:?})", def_id, substs)); + return Ok(self.printer); + } + + let def_key = self.tcx.def_key(def_id); + if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { + p!(write("{}", name)); + let mut substs = substs.iter(); + // FIXME(eddyb) print this with `print_def_path`. + if let Some(first) = substs.next() { + p!(write("::<")); + p!(print_display(first)); + for subst in substs { + p!(write(", "), print_display(subst)); + } + p!(write(">")); + } + return Ok(self.printer); + } + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); + + let mut first = true; + let mut is_sized = false; + p!(write("impl")); + for predicate in bounds.predicates { + if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + is_sized = true; + continue; + } + + p!( + write("{}", if first { " " } else { "+" }), + print(trait_ref)); + first = false; + } + } + if !is_sized { + p!(write("{}?Sized", if first { " " } else { "+" })); + } else if first { + p!(write(" Sized")); + } + } + ty::Str => p!(write("str")), + ty::Generator(did, substs, movability) => { + let upvar_tys = substs.upvar_tys(did, self.tcx); + let witness = substs.witness(did, self.tcx); + if movability == hir::GeneratorMovability::Movable { + p!(write("[generator")); + } else { + p!(write("[static generator")); + } + + // FIXME(eddyb) should use `def_span`. + if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { + p!(write("@{:?}", self.tcx.hir().span(node_id))); + let mut sep = " "; + for (freevar, upvar_ty) in self.tcx.freevars(did) + .as_ref() + .map_or(&[][..], |fv| &fv[..]) + .iter() + .zip(upvar_tys) + { + p!( + write("{}{}:", + sep, + self.tcx.hir().name(freevar.var_id())), + print(upvar_ty)); + sep = ", "; + } + } else { + // cross-crate closure types should only be + // visible in codegen bug reports, I imagine. + p!(write("@{:?}", did)); + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + p!( + write("{}{}:", sep, index), + print(upvar_ty)); + sep = ", "; + } + } + + p!(write(" "), print(witness), write("]")) + }, + ty::GeneratorWitness(types) => { + nest!(|cx| cx.pretty_in_binder(&types)) + } + ty::Closure(did, substs) => { + let upvar_tys = substs.upvar_tys(did, self.tcx); + p!(write("[closure")); + + // FIXME(eddyb) should use `def_span`. + if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { + if self.tcx.sess.opts.debugging_opts.span_free_formats { + p!(write("@{:?}", node_id)); + } else { + p!(write("@{:?}", self.tcx.hir().span(node_id))); + } + let mut sep = " "; + for (freevar, upvar_ty) in self.tcx.freevars(did) + .as_ref() + .map_or(&[][..], |fv| &fv[..]) + .iter() + .zip(upvar_tys) + { + p!( + write("{}{}:", + sep, + self.tcx.hir().name(freevar.var_id())), + print(upvar_ty)); + sep = ", "; + } + } else { + // cross-crate closure types should only be + // visible in codegen bug reports, I imagine. + p!(write("@{:?}", did)); + let mut sep = " "; + for (index, upvar_ty) in upvar_tys.enumerate() { + p!( + write("{}{}:", sep, index), + print(upvar_ty)); + sep = ", "; + } + } + + p!(write("]")) + }, + ty::Array(ty, sz) => { + p!(write("["), print(ty), write("; ")); + match sz { + ty::LazyConst::Unevaluated(_def_id, _substs) => { + p!(write("_")); + } + ty::LazyConst::Evaluated(c) => { + p!(write("{}", c.unwrap_usize(self.tcx))); + } + } + p!(write("]")) + } + ty::Slice(ty) => { + p!(write("["), print(ty), write("]")) + } + } + + Ok(self.printer) + } + + pub fn pretty_fn_sig( + mut self, + inputs: &[Ty<'tcx>], + variadic: bool, + output: Ty<'tcx>, + ) -> Result { + define_scoped_cx!(self); + + p!(write("(")); + let mut inputs = inputs.iter(); + if let Some(&ty) = inputs.next() { + p!(print_display(ty)); + for &ty in inputs { + p!(write(", "), print_display(ty)); + } + if variadic { + p!(write(", ...")); + } + } + p!(write(")")); + if !output.is_unit() { + p!(write(" -> "), print_display(output)); + } + + Ok(self.printer) + } + + pub fn pretty_in_binder(mut self, value: &ty::Binder) -> Result + where T: Print<'tcx, P, Output = P, Error = fmt::Error> + TypeFoldable<'tcx> + { + fn name_by_region_index(index: usize) -> InternedString { + match index { + 0 => Symbol::intern("'r"), + 1 => Symbol::intern("'s"), + i => Symbol::intern(&format!("'t{}", i-2)), + }.as_interned_str() + } + + // Replace any anonymous late-bound regions with named + // variants, using gensym'd 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.config.binder_depth == 0 { + self.prepare_late_bound_region_info(value); + } + + let mut empty = true; + let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { + write!(cx.printer, "{}", if empty { + empty = false; + start + } else { + cont + }) + }; + + // NOTE(eddyb) this must be below `start_or_continue`'s definition + // as that also has a `define_scoped_cx` and that kind of shadowing + // is disallowed (name resolution thinks `scoped_cx!` is ambiguous). + define_scoped_cx!(self); + + let old_region_index = self.config.region_index; + let mut region_index = old_region_index; + let new_value = self.tcx.replace_late_bound_regions(value, |br| { + let _ = start_or_continue(&mut self, "for<", ", "); + let br = match br { + ty::BrNamed(_, name) => { + let _ = write!(self.printer, "{}", name); + br + } + ty::BrAnon(_) | + ty::BrFresh(_) | + ty::BrEnv => { + let name = loop { + let name = name_by_region_index(region_index); + region_index += 1; + if !self.is_name_used(&name) { + break name; + } + }; + let _ = write!(self.printer, "{}", name); + ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) + } + }; + self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) + }).0; + start_or_continue(&mut self, "", "> ")?; + + // Push current state to gcx, and restore after writing new_value. + self.config.binder_depth += 1; + self.config.region_index = region_index; + let result = new_value.print_display(PrintCx { + tcx: self.tcx, + printer: self.printer, + config: self.config, + }); + self.config.region_index = old_region_index; + self.config.binder_depth -= 1; + result + } + + fn is_name_used(&self, name: &InternedString) -> bool { + match self.config.used_region_names { + Some(ref names) => names.contains(name), + None => false, + } + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 43afe8990eadf..c53cf2ab8c4b6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,17 +1,14 @@ +use hir; use hir::def::Namespace; use hir::def_id::DefId; -use ty::subst::{Kind, Subst, Substs, UnpackedKind}; -use ty::{self, Ty, TypeFoldable}; +use ty::subst::{Kind, Substs, UnpackedKind}; +use ty::{self, Ty}; use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use std::fmt::{self, Write as _}; use std::iter; -use std::usize; use rustc_target::spec::abi::Abi; -use syntax::ast::CRATE_NODE_ID; -use syntax::symbol::{Symbol, InternedString}; -use hir; macro_rules! gen_display_debug_body { ( $with:path ) => { @@ -144,117 +141,6 @@ macro_rules! define_scoped_cx { }; } -impl PrintCx<'a, 'gcx, 'tcx, P> { - fn fn_sig( - mut self, - inputs: &[Ty<'tcx>], - variadic: bool, - output: Ty<'tcx>, - ) -> Result { - define_scoped_cx!(self); - - p!(write("(")); - let mut inputs = inputs.iter(); - if let Some(&ty) = inputs.next() { - p!(print_display(ty)); - for &ty in inputs { - p!(write(", "), print_display(ty)); - } - if variadic { - p!(write(", ...")); - } - } - p!(write(")")); - if !output.is_unit() { - p!(write(" -> "), print_display(output)); - } - - Ok(self.printer) - } - - fn in_binder(mut self, value: &ty::Binder) -> Result - where T: Print<'tcx, P, Output = P, Error = fmt::Error> + TypeFoldable<'tcx> - { - fn name_by_region_index(index: usize) -> InternedString { - match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i-2)), - }.as_interned_str() - } - - // Replace any anonymous late-bound regions with named - // variants, using gensym'd 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.config.binder_depth == 0 { - self.prepare_late_bound_region_info(value); - } - - let mut empty = true; - let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - write!(cx.printer, "{}", if empty { - empty = false; - start - } else { - cont - }) - }; - - // NOTE(eddyb) this must be below `start_or_continue`'s definition - // as that also has a `define_scoped_cx` and that kind of shadowing - // is disallowed (name resolution thinks `scoped_cx!` is ambiguous). - define_scoped_cx!(self); - - let old_region_index = self.config.region_index; - let mut region_index = old_region_index; - let new_value = self.tcx.replace_late_bound_regions(value, |br| { - let _ = start_or_continue(&mut self, "for<", ", "); - let br = match br { - ty::BrNamed(_, name) => { - let _ = write!(self.printer, "{}", name); - br - } - ty::BrAnon(_) | - ty::BrFresh(_) | - ty::BrEnv => { - let name = loop { - let name = name_by_region_index(region_index); - region_index += 1; - if !self.is_name_used(&name) { - break name; - } - }; - let _ = write!(self.printer, "{}", name); - ty::BrNamed(self.tcx.hir().local_def_id(CRATE_NODE_ID), name) - } - }; - self.tcx.mk_region(ty::ReLateBound(ty::INNERMOST, br)) - }).0; - start_or_continue(&mut self, "", "> ")?; - - // Push current state to gcx, and restore after writing new_value. - self.config.binder_depth += 1; - self.config.region_index = region_index; - let result = new_value.print_display(PrintCx { - tcx: self.tcx, - printer: self.printer, - config: self.config, - }); - self.config.region_index = old_region_index; - self.config.binder_depth -= 1; - result - } - - fn is_name_used(&self, name: &InternedString) -> bool { - match self.config.used_region_names { - Some(ref names) => names.contains(name), - None => false, - } - } -} - pub fn parameterized( f: &mut F, did: DefId, @@ -284,7 +170,7 @@ define_print! { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); - nest!(|cx| cx.fn_sig(args, false, proj.ty)); + nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); resugared_principal = true; } } @@ -533,7 +419,7 @@ define_print! { } p!(write("fn")); - nest!(|cx| cx.fn_sig(self.inputs(), self.variadic, self.output())); + nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); } debug { p!(write("({:?}; variadic: {})->{:?}", @@ -616,7 +502,7 @@ impl fmt::Debug for ty::FloatVarValue { for<'a> >::Lifted: fmt::Display + TypeFoldable<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(|cx| cx.in_binder(cx.tcx.lift(self) + PrintCx::with_tls_tcx(|cx| cx.pretty_in_binder(cx.tcx.lift(self) .expect("could not lift for printing"))) } }*/ @@ -634,7 +520,7 @@ define_print_multi! { ] (self, cx) { display { - nest!(|cx| cx.in_binder(self)) + nest!(|cx| cx.pretty_in_binder(self)) } } } @@ -650,251 +536,6 @@ define_print! { } } -// FIXME(eddyb) move this to `ty::print`. -impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { - pub fn pretty_print_type( - mut self, - ty: Ty<'tcx>, - ) -> Result { - define_scoped_cx!(self); - - match ty.sty { - ty::Bool => p!(write("bool")), - ty::Char => p!(write("char")), - ty::Int(t) => p!(write("{}", t.ty_to_string())), - ty::Uint(t) => p!(write("{}", t.ty_to_string())), - ty::Float(t) => p!(write("{}", t.ty_to_string())), - ty::RawPtr(ref tm) => { - p!(write("*{} ", match tm.mutbl { - hir::MutMutable => "mut", - hir::MutImmutable => "const", - })); - p!(print(tm.ty)) - } - ty::Ref(r, ty, mutbl) => { - p!(write("&")); - if self.print_region_outputs_anything(r) { - p!(print_display(r), write(" ")); - } - p!(print(ty::TypeAndMut { ty, mutbl })) - } - ty::Never => p!(write("!")), - ty::Tuple(ref tys) => { - p!(write("(")); - let mut tys = tys.iter(); - if let Some(&ty) = tys.next() { - p!(print(ty), write(",")); - if let Some(&ty) = tys.next() { - p!(write(" "), print(ty)); - for &ty in tys { - p!(write(", "), print(ty)); - } - } - } - p!(write(")")) - } - ty::FnDef(def_id, substs) => { - let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); - p!(print(sig), write(" {{")); - nest!(|cx| cx.print_value_path(def_id, Some(substs))); - p!(write("}}")) - } - ty::FnPtr(ref bare_fn) => { - p!(print(bare_fn)) - } - ty::Infer(infer_ty) => p!(write("{}", infer_ty)), - ty::Error => p!(write("[type error]")), - ty::Param(ref param_ty) => p!(write("{}", param_ty)), - ty::Bound(debruijn, bound_ty) => { - match bound_ty.kind { - ty::BoundTyKind::Anon => { - if debruijn == ty::INNERMOST { - p!(write("^{}", bound_ty.var.index())) - } else { - p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) - } - } - - ty::BoundTyKind::Param(p) => p!(write("{}", p)), - } - } - ty::Adt(def, substs) => { - nest!(|cx| cx.print_def_path(def.did, Some(substs), iter::empty())); - } - ty::Dynamic(data, r) => { - let print_r = self.print_region_outputs_anything(r); - if print_r { - p!(write("(")); - } - p!(write("dyn "), print(data)); - if print_r { - p!(write(" + "), print_display(r), write(")")); - } - } - ty::Foreign(def_id) => { - nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); - } - ty::Projection(ref data) => p!(print(data)), - ty::UnnormalizedProjection(ref data) => { - p!(write("Unnormalized("), print(data), write(")")) - } - ty::Placeholder(placeholder) => { - p!(write("Placeholder({:?})", placeholder)) - } - ty::Opaque(def_id, substs) => { - if self.config.is_verbose { - p!(write("Opaque({:?}, {:?})", def_id, substs)); - return Ok(self.printer); - } - - let def_key = self.tcx.def_key(def_id); - if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - p!(write("{}", name)); - let mut substs = substs.iter(); - // FIXME(eddyb) print this with `print_def_path`. - if let Some(first) = substs.next() { - p!(write("::<")); - p!(print_display(first)); - for subst in substs { - p!(write(", "), print_display(subst)); - } - p!(write(">")); - } - return Ok(self.printer); - } - // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, - // by looking up the projections associated with the def_id. - let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); - - let mut first = true; - let mut is_sized = false; - p!(write("impl")); - for predicate in bounds.predicates { - if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { - // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { - is_sized = true; - continue; - } - - p!( - write("{}", if first { " " } else { "+" }), - print(trait_ref)); - first = false; - } - } - if !is_sized { - p!(write("{}?Sized", if first { " " } else { "+" })); - } else if first { - p!(write(" Sized")); - } - } - ty::Str => p!(write("str")), - ty::Generator(did, substs, movability) => { - let upvar_tys = substs.upvar_tys(did, self.tcx); - let witness = substs.witness(did, self.tcx); - if movability == hir::GeneratorMovability::Movable { - p!(write("[generator")); - } else { - p!(write("[static generator")); - } - - // FIXME(eddyb) should use `def_span`. - if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { - p!(write("@{:?}", self.tcx.hir().span(node_id))); - let mut sep = " "; - for (freevar, upvar_ty) in self.tcx.freevars(did) - .as_ref() - .map_or(&[][..], |fv| &fv[..]) - .iter() - .zip(upvar_tys) - { - p!( - write("{}{}:", - sep, - self.tcx.hir().name(freevar.var_id())), - print(upvar_ty)); - sep = ", "; - } - } else { - // cross-crate closure types should only be - // visible in codegen bug reports, I imagine. - p!(write("@{:?}", did)); - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - p!( - write("{}{}:", sep, index), - print(upvar_ty)); - sep = ", "; - } - } - - p!(write(" "), print(witness), write("]")) - }, - ty::GeneratorWitness(types) => { - nest!(|cx| cx.in_binder(&types)) - } - ty::Closure(did, substs) => { - let upvar_tys = substs.upvar_tys(did, self.tcx); - p!(write("[closure")); - - // FIXME(eddyb) should use `def_span`. - if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { - if self.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", node_id)); - } else { - p!(write("@{:?}", self.tcx.hir().span(node_id))); - } - let mut sep = " "; - for (freevar, upvar_ty) in self.tcx.freevars(did) - .as_ref() - .map_or(&[][..], |fv| &fv[..]) - .iter() - .zip(upvar_tys) - { - p!( - write("{}{}:", - sep, - self.tcx.hir().name(freevar.var_id())), - print(upvar_ty)); - sep = ", "; - } - } else { - // cross-crate closure types should only be - // visible in codegen bug reports, I imagine. - p!(write("@{:?}", did)); - let mut sep = " "; - for (index, upvar_ty) in upvar_tys.enumerate() { - p!( - write("{}{}:", sep, index), - print(upvar_ty)); - sep = ", "; - } - } - - p!(write("]")) - }, - ty::Array(ty, sz) => { - p!(write("["), print(ty), write("; ")); - match sz { - ty::LazyConst::Unevaluated(_def_id, _substs) => { - p!(write("_")); - } - ty::LazyConst::Evaluated(c) => { - p!(write("{}", c.unwrap_usize(self.tcx))); - } - } - p!(write("]")) - } - ty::Slice(ty) => { - p!(write("["), print(ty), write("]")) - } - } - - Ok(self.printer) - } -} - define_print! { ('tcx) Ty<'tcx>, (self, cx) { display { From 4e1af5e159f8028b488975f27f18c91f54880190 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 21:45:13 +0200 Subject: [PATCH 50/68] rustc: remove fields from ty::print::PrintConfig available from tcx. --- src/librustc/mir/mod.rs | 28 ++++++++++++++-------------- src/librustc/ty/print/mod.rs | 18 ++---------------- src/librustc/ty/print/pretty.rs | 18 +++++++++++------- src/librustc/util/ppaux.rs | 4 ++-- 4 files changed, 29 insertions(+), 39 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index e42bbbf26e8a3..c7ef37442d05b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2341,20 +2341,20 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; // When printing regions, add trailing space if necessary. - let ns = Namespace::ValueNS; - ty::print::PrintCx::with_tls_tcx(ty::print::FmtPrinter::new(fmt, ns), |mut cx| { - let region = if cx.config.is_verbose || cx.config.identify_regions { - let mut region = region.to_string(); - if region.len() > 0 { - region.push(' '); - } - region - } else { - // Do not even print 'static - String::new() - }; - write!(cx.printer, "&{}{}{:?}", region, kind_str, place) - }) + let print_region = ty::tls::with(|tcx| { + tcx.sess.verbose() || tcx.sess.opts.debugging_opts.identify_regions + }); + let region = if print_region { + let mut region = region.to_string(); + if region.len() > 0 { + region.push(' '); + } + region + } else { + // Do not even print 'static + String::new() + }; + write!(fmt, "&{}{}{:?}", region, kind_str, place) } Aggregate(ref kind, ref places) => { diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 2b747c034ffed..60170877daf55 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -29,28 +29,14 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { } } +#[derive(Default)] pub(crate) struct PrintConfig { pub(crate) is_debug: bool, - pub(crate) is_verbose: bool, - pub(crate) identify_regions: bool, used_region_names: Option>, region_index: usize, binder_depth: usize, } -impl PrintConfig { - fn new(tcx: TyCtxt<'_, '_, '_>) -> Self { - PrintConfig { - is_debug: false, - is_verbose: tcx.sess.verbose(), - identify_regions: tcx.sess.opts.debugging_opts.identify_regions, - used_region_names: None, - region_index: 0, - binder_depth: 0, - } - } -} - pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub printer: P, @@ -75,7 +61,7 @@ impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { f(PrintCx { tcx, printer, - config: &mut PrintConfig::new(tcx), + config: &mut PrintConfig::default(), }) } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 6d64f56781ad5..dd653d60f5d2c 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -518,7 +518,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }); // Don't print args that are the defaults of their respective parameters. - let num_supplied_defaults = if self.config.is_verbose { + let num_supplied_defaults = if self.tcx.sess.verbose() { 0 } else { params.iter().rev().take_while(|param| { @@ -820,10 +820,12 @@ impl PrettyPrinter for FmtPrinter { return true; } - if self.config.is_verbose { + if self.tcx.sess.verbose() { return true; } + let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; + match *region { ty::ReEarlyBound(ref data) => { data.name != "" && data.name != "'_" @@ -848,7 +850,7 @@ impl PrettyPrinter for FmtPrinter { } ty::ReScope(_) | - ty::ReVar(_) if self.config.identify_regions => true, + ty::ReVar(_) if identify_regions => true, ty::ReVar(_) | ty::ReScope(_) | @@ -876,10 +878,12 @@ impl FmtPrinter { return Ok(self.printer); } - if self.config.is_verbose { + if self.tcx.sess.verbose() { return region.print_debug(self); } + let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; + // These printouts are concise. They do not contain all the information // the user might want to diagnose an error, but there is basically no way // to fit that into a short string. Hence the recommendation to use @@ -906,7 +910,7 @@ impl FmtPrinter { } } } - ty::ReScope(scope) if self.config.identify_regions => { + ty::ReScope(scope) if identify_regions => { match scope.data { region::ScopeData::Node => p!(write("'{}s", scope.item_local_id().as_usize())), @@ -923,7 +927,7 @@ impl FmtPrinter { )), } } - ty::ReVar(region_vid) if self.config.identify_regions => { + ty::ReVar(region_vid) if identify_regions => { p!(write("{:?}", region_vid)); } ty::ReVar(_) => {} @@ -1031,7 +1035,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write("Placeholder({:?})", placeholder)) } ty::Opaque(def_id, substs) => { - if self.config.is_verbose { + if self.tcx.sess.verbose() { p!(write("Opaque({:?}, {:?})", def_id, substs)); return Ok(self.printer); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c53cf2ab8c4b6..5a8de876947b0 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -165,7 +165,7 @@ define_print! { // Special-case `Fn(...) -> ...` and resugar it. let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); - if !cx.config.is_verbose && fn_trait_kind.is_some() { + if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() { if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { @@ -455,7 +455,7 @@ impl fmt::Debug for ty::RegionVid { define_print! { () ty::InferTy, (self, cx) { display { - if cx.config.is_verbose { + if cx.tcx.sess.verbose() { return self.print_debug(cx); } match *self { From 2b789be8f9e0dea4b451a17fe8eb8d6f2163504d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 22:14:01 +0200 Subject: [PATCH 51/68] rustc: make util::ppaux private. --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/lib.rs | 2 +- src/librustc/mir/mod.rs | 9 +++++++-- src/librustc/traits/structural_impls.rs | 5 +++-- src/librustc/ty/instance.rs | 9 +++++++-- src/librustc/util/ppaux.rs | 16 +--------------- src/librustc_mir/monomorphize/item.rs | 5 ++--- 7 files changed, 22 insertions(+), 26 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 91aad4ef7a6f3..d256e72aafeaa 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -760,7 +760,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// For generic types with parameters with defaults, remove the parameters corresponding to - /// the defaults. This repeats a lot of the logic found in `PrintCx::parameterized`. + /// the defaults. This repeats a lot of the logic found in `ty::print::pretty`. fn strip_generic_default_params( &self, def_id: DefId, diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f9bf1a061fb29..a1e581fd56eb2 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -154,7 +154,7 @@ pub mod ty; pub mod util { pub mod captures; pub mod common; - pub mod ppaux; + mod ppaux; pub mod nodemap; pub mod time_graph; pub mod profiling; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c7ef37442d05b..facf1e2a22468 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -33,7 +33,7 @@ use ty::{ self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; -use util::ppaux; +use ty::print::{FmtPrinter, Printer, PrintCx}; pub use mir::interpret::AssertMessage; @@ -2378,7 +2378,12 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { let variant_def = &adt_def.variants[variant]; - ppaux::parameterized(fmt, variant_def.did, substs, Namespace::ValueNS)?; + let f = &mut *fmt; + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |cx| { + let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); + cx.print_def_path(variant_def.did, Some(substs), iter::empty())?; + Ok(()) + })?; match variant_def.ctor_kind { CtorKind::Const => Ok(()), diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 2f5df022218fe..1521bed8c52f6 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -165,7 +165,8 @@ impl<'tcx> fmt::Display for traits::WhereClause<'tcx> { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { use traits::WhereClause::*; - // Bypass ppaux because it does not print out anonymous regions. + // Bypass `ty::print` because it does not print out anonymous regions. + // FIXME(eddyb) implement a custom `PrettyPrinter`, or move this to `ty::print`. fn write_region_name<'tcx>( r: ty::Region<'tcx>, fmt: &mut fmt::Formatter<'_> @@ -256,7 +257,7 @@ impl fmt::Display for traits::QuantifierKind { } /// Collect names for regions / types bound by a quantified goal / clause. -/// This collector does not try to do anything clever like in ppaux, it's just used +/// This collector does not try to do anything clever like in `ty::print`, it's just used /// for debug output in tests anyway. struct BoundNamesCollector { // Just sort by name because `BoundRegion::BrNamed` does not have a `BoundVar` index anyway. diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 480d4c6d73a2c..16c244627fb2c 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -2,9 +2,9 @@ use hir::Unsafety; use hir::def::Namespace; use hir::def_id::DefId; use ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt}; +use ty::print::{FmtPrinter, Printer, PrintCx}; use traits; use rustc_target::spec::abi::Abi; -use util::ppaux; use std::fmt; use std::iter; @@ -175,7 +175,12 @@ impl<'tcx> InstanceDef<'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ppaux::parameterized(f, self.def_id(), self.substs, Namespace::ValueNS)?; + PrintCx::with_tls_tcx(FmtPrinter::new(&mut *f, Namespace::ValueNS), |cx| { + let substs = cx.tcx.lift(&self.substs).expect("could not lift for printing"); + cx.print_def_path(self.def_id(), Some(substs), iter::empty())?; + Ok(()) + })?; + match self.def { InstanceDef::Item(_) => Ok(()), InstanceDef::VtableShim(_) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 5a8de876947b0..c572133a126e0 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,6 @@ use hir; use hir::def::Namespace; -use hir::def_id::DefId; -use ty::subst::{Kind, Substs, UnpackedKind}; +use ty::subst::{Kind, UnpackedKind}; use ty::{self, Ty}; use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; @@ -141,19 +140,6 @@ macro_rules! define_scoped_cx { }; } -pub fn parameterized( - f: &mut F, - did: DefId, - substs: &Substs<'_>, - ns: Namespace, -) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, ns), |cx| { - let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.print_def_path(did, Some(substs), iter::empty())?; - Ok(()) - }) -} - define_print! { ('tcx) &'tcx ty::List>, (self, cx) { display { diff --git a/src/librustc_mir/monomorphize/item.rs b/src/librustc_mir/monomorphize/item.rs index 431cc0d52b4c8..caba0705bdfa1 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -215,9 +215,8 @@ impl<'a, 'tcx> MonoItemExt<'a, 'tcx> for MonoItem<'tcx> { // These keys are used by the handwritten auto-tests, so they need to be // predictable and human-readable. // -// Note: A lot of this could looks very similar to what's already in the -// ppaux module. It would be good to refactor things so we only have one -// parameterizable implementation for printing types. +// Note: A lot of this could looks very similar to what's already in `ty::print`. +// FIXME(eddyb) implement a custom `PrettyPrinter` for this. /// Same as `unique_type_name()` but with the result pushed onto the given /// `output` parameter. From 206b0f21fe7ff9d8341005b80bb48c6e3066b5ad Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 19 Jan 2019 03:25:51 +0200 Subject: [PATCH 52/68] rustc: disconnect all the Debug functionality from ty::print. --- src/librustc/ty/print/mod.rs | 26 --- src/librustc/ty/print/pretty.rs | 34 ++-- src/librustc/util/ppaux.rs | 281 ++++++++++++++------------------ 3 files changed, 136 insertions(+), 205 deletions(-) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 60170877daf55..c7b898b7c5136 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -31,7 +31,6 @@ impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { #[derive(Default)] pub(crate) struct PrintConfig { - pub(crate) is_debug: bool, used_region_names: Option>, region_index: usize, binder_depth: usize, @@ -83,31 +82,6 @@ pub trait Print<'tcx, P> { type Error; fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result; - fn print_display( - &self, - cx: PrintCx<'_, '_, 'tcx, P>, - ) -> Result { - let old_debug = cx.config.is_debug; - cx.config.is_debug = false; - let result = self.print(PrintCx { - tcx: cx.tcx, - printer: cx.printer, - config: cx.config, - }); - cx.config.is_debug = old_debug; - result - } - fn print_debug(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { - let old_debug = cx.config.is_debug; - cx.config.is_debug = true; - let result = self.print(PrintCx { - tcx: cx.tcx, - printer: cx.printer, - config: cx.config, - }); - cx.config.is_debug = old_debug; - result - } } pub trait Printer: Sized { diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index dd653d60f5d2c..0071f638587d9 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -454,7 +454,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ty::Adt(..) | ty::Foreign(_) | ty::Bool | ty::Char | ty::Str | ty::Int(_) | ty::Uint(_) | ty::Float(_) => { - return self_ty.print_display(self); + return self_ty.print(self); } _ => {} @@ -464,9 +464,9 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { self.generic_delimiters(|mut cx| { define_scoped_cx!(cx); - p!(print_display(self_ty)); + p!(print(self_ty)); if let Some(trait_ref) = trait_ref { - p!(write(" as "), print_display(trait_ref)); + p!(write(" as "), print(trait_ref)); } Ok(cx.printer) }) @@ -487,9 +487,9 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write("impl ")); if let Some(trait_ref) = trait_ref { - p!(print_display(trait_ref), write(" for ")); + p!(print(trait_ref), write(" for ")); } - p!(print_display(self_ty)); + p!(print(self_ty)); Ok(cx.printer) }) @@ -580,14 +580,14 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - p!(print_display(arg)); + p!(print(arg)); } for projection in projection0.into_iter().chain(projections) { maybe_comma(&mut cx)?; p!(write("{}=", cx.tcx.associated_item(projection.item_def_id).ident), - print_display(projection.ty)); + print(projection.ty)); } Ok(cx.printer) @@ -879,7 +879,8 @@ impl FmtPrinter { } if self.tcx.sess.verbose() { - return region.print_debug(self); + p!(write("{:?}", region)); + return Ok(self.printer); } let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; @@ -967,7 +968,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ty::Ref(r, ty, mutbl) => { p!(write("&")); if self.print_region_outputs_anything(r) { - p!(print_display(r), write(" ")); + p!(print(r), write(" ")); } p!(print(ty::TypeAndMut { ty, mutbl })) } @@ -1021,7 +1022,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(write("dyn "), print(data)); if print_r { - p!(write(" + "), print_display(r), write(")")); + p!(write(" + "), print(r), write(")")); } } ty::Foreign(def_id) => { @@ -1035,6 +1036,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write("Placeholder({:?})", placeholder)) } ty::Opaque(def_id, substs) => { + // FIXME(eddyb) print this with `print_def_path`. if self.tcx.sess.verbose() { p!(write("Opaque({:?}, {:?})", def_id, substs)); return Ok(self.printer); @@ -1047,9 +1049,9 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // FIXME(eddyb) print this with `print_def_path`. if let Some(first) = substs.next() { p!(write("::<")); - p!(print_display(first)); + p!(print(first)); for subst in substs { - p!(write(", "), print_display(subst)); + p!(write(", "), print(subst)); } p!(write(">")); } @@ -1198,9 +1200,9 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write("(")); let mut inputs = inputs.iter(); if let Some(&ty) = inputs.next() { - p!(print_display(ty)); + p!(print(ty)); for &ty in inputs { - p!(write(", "), print_display(ty)); + p!(write(", "), print(ty)); } if variadic { p!(write(", ...")); @@ -1208,7 +1210,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(write(")")); if !output.is_unit() { - p!(write(" -> "), print_display(output)); + p!(write(" -> "), print(output)); } Ok(self.printer) @@ -1279,7 +1281,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // Push current state to gcx, and restore after writing new_value. self.config.binder_depth += 1; self.config.region_index = region_index; - let result = new_value.print_display(PrintCx { + let result = new_value.print(PrintCx { tcx: self.tcx, printer: self.printer, config: self.config, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c572133a126e0..9b402d6b766b6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,108 +9,64 @@ use std::iter; use rustc_target::spec::abi::Abi; -macro_rules! gen_display_debug_body { - ( $with:path ) => { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - $with(&cx.tcx.lift(self).expect("could not lift for printing"), cx)?; - Ok(()) - }) - } - }; -} -macro_rules! gen_display_debug { - ( ($($x:tt)+) $target:ty, display yes ) => { - impl<$($x)+> fmt::Display for $target { - gen_display_debug_body! { Print::print_display } - } - }; - ( () $target:ty, display yes ) => { - impl fmt::Display for $target { - gen_display_debug_body! { Print::print_display } - } - }; - ( ($($x:tt)+) $target:ty, debug yes ) => { - impl<$($x)+> fmt::Debug for $target { - gen_display_debug_body! { Print::print_debug } - } - }; - ( () $target:ty, debug yes ) => { - impl fmt::Debug for $target { - gen_display_debug_body! { Print::print_debug } - } - }; - ( $generic:tt $target:ty, $t:ident no ) => {}; -} -macro_rules! gen_print_impl { - ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { - impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target { +macro_rules! define_print { + (@display $target:ty, ($self:ident, $cx:ident) $disp:block) => { + impl Print<'tcx, P> for $target { type Output = P; type Error = fmt::Error; fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { #[allow(unused_mut)] let mut $cx = $cx; - let _: () = { - define_scoped_cx!($cx); - - if $cx.config.is_debug $dbg - else $disp - }; + define_scoped_cx!($cx); + let _: () = $disp; + #[allow(unreachable_code)] Ok($cx.printer) } } - }; - ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { - impl Print<'tcx, P> for $target { - type Output = P; - type Error = fmt::Error; - fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { - #[allow(unused_mut)] - let mut $cx = $cx; - let _: () = { - define_scoped_cx!($cx); - if $cx.config.is_debug $dbg - else $disp - }; - Ok($cx.printer) + impl fmt::Display for $target { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; + Ok(()) + }) } } }; - ( $generic:tt $target:ty, - $vars:tt $gendisp:ident $disp:block $gendbg:ident $dbg:block ) => { - gen_print_impl! { $generic $target, $vars $disp $dbg } - gen_display_debug! { $generic $target, display $gendisp } - gen_display_debug! { $generic $target, debug $gendbg } - } -} -macro_rules! define_print { - ( $generic:tt $target:ty, - $vars:tt { display $disp:block debug $dbg:block } ) => { - gen_print_impl! { $generic $target, $vars yes $disp yes $dbg } - }; - ( $generic:tt $target:ty, - $vars:tt { debug $dbg:block display $disp:block } ) => { - gen_print_impl! { $generic $target, $vars yes $disp yes $dbg } + + (@debug $target:ty, ($self:ident, $cx:ident) $dbg:block) => { + impl fmt::Debug for $target { + fn fmt(&$self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |$cx| { + #[allow(unused_mut)] + let mut $cx = $cx; + define_scoped_cx!($cx); + let _: () = $dbg; + let _ = $cx; + Ok(()) + }) + } + } }; - ( $generic:tt $target:ty, - $vars:tt { debug $dbg:block } ) => { - gen_print_impl! { $generic $target, $vars no { - bug!(concat!("display not implemented for ", stringify!($target))); - } yes $dbg } + + ([$($target:ty),+] $vars:tt $def:tt) => { + $(define_print!($target, $vars $def);)+ }; - ( $generic:tt $target:ty, - ($self:ident, $cx:ident) { display $disp:block } ) => { - gen_print_impl! { $generic $target, ($self, $cx) yes $disp no { - write!($cx.printer, "{:?}", $self)? - } } + + ($target:ty, $vars:tt { + display $disp:block + debug $dbg:block + }) => { + define_print!(@display $target, $vars $disp); + define_print!(@debug $target, $vars $dbg); }; -} -macro_rules! define_print_multi { - ( [ $($generic:tt $target:ty),* ] $vars:tt $def:tt ) => { - $(define_print! { $generic $target, $vars $def })* + ($target:ty, $vars:tt { + display $disp:block + }) => { + define_print!(@display $target, $vars $disp); }; } + macro_rules! nest { ($closure:expr) => { scoped_cx!() = scoped_cx!().nest($closure)? @@ -141,7 +97,7 @@ macro_rules! define_scoped_cx { } define_print! { - ('tcx) &'tcx ty::List>, (self, cx) { + &'tcx ty::List>, (self, cx) { display { // Generate the main trait ref, including associated types. let mut first = true; @@ -264,7 +220,7 @@ impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { } define_print! { - ('tcx) &'tcx ty::List>, (self, cx) { + &'tcx ty::List>, (self, cx) { display { p!(write("{{")); let mut tys = self.iter(); @@ -280,7 +236,7 @@ define_print! { } define_print! { - ('tcx) ty::TypeAndMut<'tcx>, (self, cx) { + ty::TypeAndMut<'tcx>, (self, cx) { display { p!( write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), @@ -290,26 +246,27 @@ define_print! { } define_print! { - ('tcx) ty::ExistentialTraitRef<'tcx>, (self, cx) { + ty::ExistentialTraitRef<'tcx>, (self, cx) { display { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); let trait_ref = *ty::Binder::bind(*self) .with_self_ty(cx.tcx, dummy_self) .skip_binder(); - p!(print_display(trait_ref)) - } - debug { - p!(print_display(self)) + p!(print(trait_ref)) } } } -define_print! { - ('tcx) ty::adjustment::Adjustment<'tcx>, (self, cx) { - debug { - p!(write("{:?} -> ", self.kind), print(self.target)) - } +impl fmt::Debug for ty::ExistentialTraitRef<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Debug for ty::adjustment::Adjustment<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?} -> {}", self.kind, self.target) } } @@ -328,7 +285,7 @@ impl fmt::Debug for ty::BoundRegion { } define_print! { - () ty::RegionKind, (self, cx) { + ty::RegionKind, (self, cx) { display { return cx.print_region(self); } @@ -348,7 +305,7 @@ define_print! { p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region)) } - ty::ReFree(ref fr) => p!(print_debug(fr)), + ty::ReFree(ref fr) => p!(write("{:?}", fr)), ty::ReScope(id) => { p!(write("ReScope({:?})", id)) @@ -372,29 +329,25 @@ define_print! { } } -define_print! { - () ty::FreeRegion, (self, cx) { - debug { - p!(write("ReFree({:?}, {:?})", self.scope, self.bound_region)) - } +impl fmt::Debug for ty::FreeRegion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) } } -define_print! { - () ty::Variance, (self, cx) { - debug { - cx.printer.write_str(match *self { - ty::Covariant => "+", - ty::Contravariant => "-", - ty::Invariant => "o", - ty::Bivariant => "*", - })? - } +impl fmt::Debug for ty::Variance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match *self { + ty::Covariant => "+", + ty::Contravariant => "-", + ty::Invariant => "o", + ty::Bivariant => "*", + }) } } define_print! { - ('tcx) ty::FnSig<'tcx>, (self, cx) { + ty::FnSig<'tcx>, (self, cx) { display { if self.unsafety == hir::Unsafety::Unsafe { p!(write("unsafe ")); @@ -439,10 +392,11 @@ impl fmt::Debug for ty::RegionVid { } define_print! { - () ty::InferTy, (self, cx) { + ty::InferTy, (self, cx) { display { if cx.tcx.sess.verbose() { - return self.print_debug(cx); + p!(write("{:?}", self)); + return Ok(cx.printer); } match *self { ty::TyVar(_) => p!(write("_")), @@ -493,16 +447,16 @@ impl fmt::Debug for ty::FloatVarValue { } }*/ -define_print_multi! { +define_print! { [ - ('tcx) ty::Binder<&'tcx ty::List>>, - ('tcx) ty::Binder>, - ('tcx) ty::Binder>, - ('tcx) ty::Binder>, - ('tcx) ty::Binder>, - ('tcx) ty::Binder>, - ('tcx) ty::Binder, ty::Region<'tcx>>>, - ('tcx) ty::Binder, ty::Region<'tcx>>> + ty::Binder<&'tcx ty::List>>, + ty::Binder>, + ty::Binder>, + ty::Binder>, + ty::Binder>, + ty::Binder>, + ty::Binder, ty::Region<'tcx>>>, + ty::Binder, ty::Region<'tcx>>> ] (self, cx) { display { @@ -512,29 +466,35 @@ define_print_multi! { } define_print! { - ('tcx) ty::TraitRef<'tcx>, (self, cx) { + ty::TraitRef<'tcx>, (self, cx) { display { nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); } debug { - nest!(|cx| cx.path_qualified(self.self_ty(), Some(*self))); + // HACK(eddyb) this is used across the compiler to print + // a `TraitRef` qualified (with the Self type explicit), + // instead of having a different way to make that choice. + p!(write("<{} as {}>", self.self_ty(), self)) } } } define_print! { - ('tcx) Ty<'tcx>, (self, cx) { + Ty<'tcx>, (self, cx) { display { return cx.print_type(self); } - debug { - p!(print_display(self)) - } + } +} + +impl fmt::Debug for Ty<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) } } define_print! { - () ty::ParamTy, (self, cx) { + ty::ParamTy, (self, cx) { display { p!(write("{}", self.name)) } @@ -545,10 +505,10 @@ define_print! { } // Similar problem to `Binder`, can't define a generic impl. -define_print_multi! { +define_print! { [ - ('tcx) ty::OutlivesPredicate, ty::Region<'tcx>>, - ('tcx) ty::OutlivesPredicate, ty::Region<'tcx>> + ty::OutlivesPredicate, ty::Region<'tcx>>, + ty::OutlivesPredicate, ty::Region<'tcx>> ] (self, cx) { display { @@ -558,7 +518,7 @@ define_print_multi! { } define_print! { - ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) { + ty::SubtypePredicate<'tcx>, (self, cx) { display { p!(print(self.a), write(" <: "), print(self.b)) } @@ -566,35 +526,30 @@ define_print! { } define_print! { - ('tcx) ty::TraitPredicate<'tcx>, (self, cx) { + ty::TraitPredicate<'tcx>, (self, cx) { + display { + p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + } debug { p!(write("TraitPredicate({:?})", self.trait_ref)) } - display { - p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) - } } } define_print! { - ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) { - debug { - p!( - write("ProjectionPredicate("), - print(self.projection_ty), - write(", "), - print(self.ty), - write(")")) - } + ty::ProjectionPredicate<'tcx>, (self, cx) { display { p!(print(self.projection_ty), write(" == "), print(self.ty)) } + debug { + p!(write("ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty)) + } } } define_print! { - ('tcx) ty::ProjectionTy<'tcx>, (self, cx) { + ty::ProjectionTy<'tcx>, (self, cx) { display { nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); } @@ -602,7 +557,7 @@ define_print! { } define_print! { - () ty::ClosureKind, (self, cx) { + ty::ClosureKind, (self, cx) { display { match *self { ty::ClosureKind::Fn => p!(write("Fn")), @@ -614,7 +569,7 @@ define_print! { } define_print! { - ('tcx) ty::Predicate<'tcx>, (self, cx) { + ty::Predicate<'tcx>, (self, cx) { display { match *self { ty::Predicate::Trait(ref data) => p!(print(data)), @@ -642,12 +597,12 @@ define_print! { } debug { match *self { - ty::Predicate::Trait(ref a) => p!(print(a)), - ty::Predicate::Subtype(ref pair) => p!(print(pair)), - ty::Predicate::RegionOutlives(ref pair) => p!(print(pair)), - ty::Predicate::TypeOutlives(ref pair) => p!(print(pair)), - ty::Predicate::Projection(ref pair) => p!(print(pair)), - ty::Predicate::WellFormed(ty) => p!(print(ty)), + ty::Predicate::Trait(ref a) => p!(write("{:?}", a)), + ty::Predicate::Subtype(ref pair) => p!(write("{:?}", pair)), + ty::Predicate::RegionOutlives(ref pair) => p!(write("{:?}", pair)), + ty::Predicate::TypeOutlives(ref pair) => p!(write("{:?}", pair)), + ty::Predicate::Projection(ref pair) => p!(write("{:?}", pair)), + ty::Predicate::WellFormed(ty) => p!(write("WellFormed({:?})", ty)), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("ObjectSafe({:?})", trait_def_id)) } @@ -664,7 +619,7 @@ define_print! { } define_print! { - ('tcx) Kind<'tcx>, (self, cx) { + Kind<'tcx>, (self, cx) { display { match self.unpack() { UnpackedKind::Lifetime(lt) => p!(print(lt)), @@ -673,8 +628,8 @@ define_print! { } debug { match self.unpack() { - UnpackedKind::Lifetime(lt) => p!(print(lt)), - UnpackedKind::Type(ty) => p!(print(ty)), + UnpackedKind::Lifetime(lt) => p!(write("{:?}", lt)), + UnpackedKind::Type(ty) => p!(write("{:?}", ty)), } } } From ff3ae324de70ee597772571dbf87ea5cd6a3729e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 19 Jan 2019 06:33:44 +0200 Subject: [PATCH 53/68] rustc: move Debug impls from ppaux to ty::structural_impls. --- src/librustc/ty/structural_impls.rs | 257 +++++++++++++++++++++++++ src/librustc/ty/subst.rs | 10 + src/librustc/util/ppaux.rs | 283 +--------------------------- 3 files changed, 274 insertions(+), 276 deletions(-) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index e8f5d9306f6be..2728f94ff141a 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -3,16 +3,273 @@ //! hand, though we've recently added some macros (e.g., //! `BraceStructLiftImpl!`) to help with the tedium. +use hir::def::Namespace; use mir::ProjectionKind; use mir::interpret::ConstValue; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use ty::print::{FmtPrinter, PrintCx, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use smallvec::SmallVec; use mir::interpret; +use std::fmt; +use std::iter; use std::rc::Rc; +impl fmt::Debug for ty::GenericParamDef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let type_name = match self.kind { + ty::GenericParamDefKind::Lifetime => "Lifetime", + ty::GenericParamDefKind::Type {..} => "Type", + }; + write!(f, "{}({}, {:?}, {})", + type_name, + self.name, + self.def_id, + self.index) + } +} + +impl fmt::Debug for ty::TraitDef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.print_def_path(self.def_id, None, iter::empty())?; + Ok(()) + }) + } +} + +impl fmt::Debug for ty::AdtDef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.print_def_path(self.did, None, iter::empty())?; + Ok(()) + }) + } +} + +impl fmt::Debug for ty::ClosureUpvar<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ClosureUpvar({:?},{:?})", + self.def, + self.ty) + } +} + +impl fmt::Debug for ty::UpvarId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let name = ty::tls::with(|tcx| { + tcx.hir().name(tcx.hir().hir_to_node_id(self.var_path.hir_id)) + }); + write!(f, "UpvarId({:?};`{}`;{:?})", + self.var_path.hir_id, + name, + self.closure_expr_id) + } +} + +impl fmt::Debug for ty::UpvarBorrow<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "UpvarBorrow({:?}, {:?})", + self.kind, self.region) + } +} + +impl fmt::Debug for ty::ExistentialTraitRef<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Debug for ty::adjustment::Adjustment<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?} -> {}", self.kind, self.target) + } +} + +impl fmt::Debug for ty::BoundRegion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), + ty::BrFresh(n) => write!(f, "BrFresh({:?})", n), + ty::BrNamed(did, name) => { + write!(f, "BrNamed({:?}:{:?}, {})", + did.krate, did.index, name) + } + ty::BrEnv => write!(f, "BrEnv"), + } + } +} + +impl fmt::Debug for ty::RegionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::ReEarlyBound(ref data) => { + write!(f, "ReEarlyBound({}, {})", + data.index, + data.name) + } + + ty::ReClosureBound(ref vid) => { + write!(f, "ReClosureBound({:?})", vid) + } + + ty::ReLateBound(binder_id, ref bound_region) => { + write!(f, "ReLateBound({:?}, {:?})", binder_id, bound_region) + } + + ty::ReFree(ref fr) => fr.fmt(f), + + ty::ReScope(id) => write!(f, "ReScope({:?})", id), + + ty::ReStatic => write!(f, "ReStatic"), + + ty::ReVar(ref vid) => vid.fmt(f), + + ty::RePlaceholder(placeholder) => { + write!(f, "RePlaceholder({:?})", placeholder) + } + + ty::ReEmpty => write!(f, "ReEmpty"), + + ty::ReErased => write!(f, "ReErased"), + } + } +} + +impl fmt::Debug for ty::FreeRegion { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) + } +} + +impl fmt::Debug for ty::Variance { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match *self { + ty::Covariant => "+", + ty::Contravariant => "-", + ty::Invariant => "o", + ty::Bivariant => "*", + }) + } +} + +impl fmt::Debug for ty::FnSig<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "({:?}; variadic: {})->{:?}", + self.inputs(), self.variadic, self.output()) + } +} + +impl fmt::Debug for ty::TyVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}t", self.index) + } +} + +impl fmt::Debug for ty::IntVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}i", self.index) + } +} + +impl fmt::Debug for ty::FloatVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}f", self.index) + } +} + +impl fmt::Debug for ty::RegionVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "'_#{}r", self.index()) + } +} + +impl fmt::Debug for ty::InferTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::TyVar(ref v) => v.fmt(f), + ty::IntVar(ref v) => v.fmt(f), + ty::FloatVar(ref v) => v.fmt(f), + ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), + ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), + ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v), + } + } +} + +impl fmt::Debug for ty::IntVarValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::IntType(ref v) => v.fmt(f), + ty::UintType(ref v) => v.fmt(f), + } + } +} + +impl fmt::Debug for ty::FloatVarValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl fmt::Debug for ty::TraitRef<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // HACK(eddyb) this is used across the compiler to print + // a `TraitRef` qualified (with the Self type explicit), + // instead of having a different way to make that choice. + write!(f, "<{} as {}>", self.self_ty(), self) + } +} + +impl fmt::Debug for Ty<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(self, f) + } +} + +impl fmt::Debug for ty::ParamTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}/#{}", self.name, self.idx) + } +} + +impl fmt::Debug for ty::TraitPredicate<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TraitPredicate({:?})", self.trait_ref) + } +} + +impl fmt::Debug for ty::ProjectionPredicate<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty) + } +} + +impl fmt::Debug for ty::Predicate<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self { + ty::Predicate::Trait(ref a) => a.fmt(f), + ty::Predicate::Subtype(ref pair) => pair.fmt(f), + ty::Predicate::RegionOutlives(ref pair) => pair.fmt(f), + ty::Predicate::TypeOutlives(ref pair) => pair.fmt(f), + ty::Predicate::Projection(ref pair) => pair.fmt(f), + ty::Predicate::WellFormed(ty) => write!(f, "WellFormed({:?})", ty), + ty::Predicate::ObjectSafe(trait_def_id) => { + write!(f, "ObjectSafe({:?})", trait_def_id) + } + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { + write!(f, "ClosureKind({:?}, {:?}, {:?})", + closure_def_id, closure_substs, kind) + } + ty::Predicate::ConstEvaluatable(def_id, substs) => { + write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs) + } + } + } +} + /////////////////////////////////////////////////////////////////////////// // Atomic structs // diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index b0234df96e1b9..c628b1f85343b 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -10,6 +10,7 @@ use syntax_pos::{Span, DUMMY_SP}; use smallvec::SmallVec; use core::intrinsics; +use std::fmt; use std::cmp::Ordering; use std::marker::PhantomData; use std::mem; @@ -60,6 +61,15 @@ impl<'tcx> UnpackedKind<'tcx> { } } +impl fmt::Debug for Kind<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.unpack() { + UnpackedKind::Lifetime(lt) => lt.fmt(f), + UnpackedKind::Type(ty) => ty.fmt(f), + } + } +} + impl<'tcx> Ord for Kind<'tcx> { fn cmp(&self, other: &Kind<'_>) -> Ordering { self.unpack().cmp(&other.unpack()) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9b402d6b766b6..02ef97996822f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -2,15 +2,19 @@ use hir; use hir::def::Namespace; use ty::subst::{Kind, UnpackedKind}; use ty::{self, Ty}; -use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; +use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; -use std::fmt::{self, Write as _}; +use std::fmt; use std::iter; use rustc_target::spec::abi::Abi; macro_rules! define_print { - (@display $target:ty, ($self:ident, $cx:ident) $disp:block) => { + ([$($target:ty),+] $vars:tt $def:tt) => { + $(define_print!($target, $vars $def);)+ + }; + + ($target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { impl Print<'tcx, P> for $target { type Output = P; type Error = fmt::Error; @@ -33,38 +37,6 @@ macro_rules! define_print { } } }; - - (@debug $target:ty, ($self:ident, $cx:ident) $dbg:block) => { - impl fmt::Debug for $target { - fn fmt(&$self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |$cx| { - #[allow(unused_mut)] - let mut $cx = $cx; - define_scoped_cx!($cx); - let _: () = $dbg; - let _ = $cx; - Ok(()) - }) - } - } - }; - - ([$($target:ty),+] $vars:tt $def:tt) => { - $(define_print!($target, $vars $def);)+ - }; - - ($target:ty, $vars:tt { - display $disp:block - debug $dbg:block - }) => { - define_print!(@display $target, $vars $disp); - define_print!(@debug $target, $vars $dbg); - }; - ($target:ty, $vars:tt { - display $disp:block - }) => { - define_print!(@display $target, $vars $disp); - }; } macro_rules! nest { @@ -159,66 +131,6 @@ define_print! { } } -impl fmt::Debug for ty::GenericParamDef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let type_name = match self.kind { - ty::GenericParamDefKind::Lifetime => "Lifetime", - ty::GenericParamDefKind::Type {..} => "Type", - }; - write!(f, "{}({}, {:?}, {})", - type_name, - self.name, - self.def_id, - self.index) - } -} - -impl fmt::Debug for ty::TraitDef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.print_def_path(self.def_id, None, iter::empty())?; - Ok(()) - }) - } -} - -impl fmt::Debug for ty::AdtDef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.print_def_path(self.did, None, iter::empty())?; - Ok(()) - }) - } -} - -impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ClosureUpvar({:?},{:?})", - self.def, - self.ty) - } -} - -impl fmt::Debug for ty::UpvarId { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |mut cx| { - define_scoped_cx!(cx); - p!(write("UpvarId({:?};`{}`;{:?})", - self.var_path.hir_id, - cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)), - self.closure_expr_id)); - Ok(()) - }) - } -} - -impl<'tcx> fmt::Debug for ty::UpvarBorrow<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "UpvarBorrow({:?}, {:?})", - self.kind, self.region) - } -} - define_print! { &'tcx ty::List>, (self, cx) { display { @@ -258,91 +170,11 @@ define_print! { } } -impl fmt::Debug for ty::ExistentialTraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - -impl fmt::Debug for ty::adjustment::Adjustment<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{:?} -> {}", self.kind, self.target) - } -} - -impl fmt::Debug for ty::BoundRegion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ty::BrAnon(n) => write!(f, "BrAnon({:?})", n), - ty::BrFresh(n) => write!(f, "BrFresh({:?})", n), - ty::BrNamed(did, name) => { - write!(f, "BrNamed({:?}:{:?}, {})", - did.krate, did.index, name) - } - ty::BrEnv => write!(f, "BrEnv"), - } - } -} - define_print! { ty::RegionKind, (self, cx) { display { return cx.print_region(self); } - debug { - match *self { - ty::ReEarlyBound(ref data) => { - p!(write("ReEarlyBound({}, {})", - data.index, - data.name)) - } - - ty::ReClosureBound(ref vid) => { - p!(write("ReClosureBound({:?})", vid)) - } - - ty::ReLateBound(binder_id, ref bound_region) => { - p!(write("ReLateBound({:?}, {:?})", binder_id, bound_region)) - } - - ty::ReFree(ref fr) => p!(write("{:?}", fr)), - - ty::ReScope(id) => { - p!(write("ReScope({:?})", id)) - } - - ty::ReStatic => p!(write("ReStatic")), - - ty::ReVar(ref vid) => { - p!(write("{:?}", vid)); - } - - ty::RePlaceholder(placeholder) => { - p!(write("RePlaceholder({:?})", placeholder)) - } - - ty::ReEmpty => p!(write("ReEmpty")), - - ty::ReErased => p!(write("ReErased")) - } - } - } -} - -impl fmt::Debug for ty::FreeRegion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ReFree({:?}, {:?})", self.scope, self.bound_region) - } -} - -impl fmt::Debug for ty::Variance { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(match *self { - ty::Covariant => "+", - ty::Contravariant => "-", - ty::Invariant => "o", - ty::Bivariant => "*", - }) } } @@ -360,34 +192,6 @@ define_print! { p!(write("fn")); nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); } - debug { - p!(write("({:?}; variadic: {})->{:?}", - self.inputs(), self.variadic, self.output())) - } - } -} - -impl fmt::Debug for ty::TyVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}t", self.index) - } -} - -impl fmt::Debug for ty::IntVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}i", self.index) - } -} - -impl fmt::Debug for ty::FloatVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}f", self.index) - } -} - -impl fmt::Debug for ty::RegionVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "'_#{}r", self.index()) } } @@ -407,31 +211,6 @@ define_print! { ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) } } - debug { - match *self { - ty::TyVar(ref v) => p!(write("{:?}", v)), - ty::IntVar(ref v) => p!(write("{:?}", v)), - ty::FloatVar(ref v) => p!(write("{:?}", v)), - ty::FreshTy(v) => p!(write("FreshTy({:?})", v)), - ty::FreshIntTy(v) => p!(write("FreshIntTy({:?})", v)), - ty::FreshFloatTy(v) => p!(write("FreshFloatTy({:?})", v)) - } - } - } -} - -impl fmt::Debug for ty::IntVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match *self { - ty::IntType(ref v) => v.fmt(f), - ty::UintType(ref v) => v.fmt(f), - } - } -} - -impl fmt::Debug for ty::FloatVarValue { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) } } @@ -470,12 +249,6 @@ define_print! { display { nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); } - debug { - // HACK(eddyb) this is used across the compiler to print - // a `TraitRef` qualified (with the Self type explicit), - // instead of having a different way to make that choice. - p!(write("<{} as {}>", self.self_ty(), self)) - } } } @@ -487,20 +260,11 @@ define_print! { } } -impl fmt::Debug for Ty<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - define_print! { ty::ParamTy, (self, cx) { display { p!(write("{}", self.name)) } - debug { - p!(write("{}/#{}", self.name, self.idx)) - } } } @@ -530,10 +294,6 @@ define_print! { display { p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) } - debug { - p!(write("TraitPredicate({:?})", - self.trait_ref)) - } } } @@ -542,9 +302,6 @@ define_print! { display { p!(print(self.projection_ty), write(" == "), print(self.ty)) } - debug { - p!(write("ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty)) - } } } @@ -595,26 +352,6 @@ define_print! { } } } - debug { - match *self { - ty::Predicate::Trait(ref a) => p!(write("{:?}", a)), - ty::Predicate::Subtype(ref pair) => p!(write("{:?}", pair)), - ty::Predicate::RegionOutlives(ref pair) => p!(write("{:?}", pair)), - ty::Predicate::TypeOutlives(ref pair) => p!(write("{:?}", pair)), - ty::Predicate::Projection(ref pair) => p!(write("{:?}", pair)), - ty::Predicate::WellFormed(ty) => p!(write("WellFormed({:?})", ty)), - ty::Predicate::ObjectSafe(trait_def_id) => { - p!(write("ObjectSafe({:?})", trait_def_id)) - } - ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - p!(write("ClosureKind({:?}, {:?}, {:?})", - closure_def_id, closure_substs, kind)) - } - ty::Predicate::ConstEvaluatable(def_id, substs) => { - p!(write("ConstEvaluatable({:?}, {:?})", def_id, substs)) - } - } - } } } @@ -626,11 +363,5 @@ define_print! { UnpackedKind::Type(ty) => p!(print(ty)), } } - debug { - match self.unpack() { - UnpackedKind::Lifetime(lt) => p!(write("{:?}", lt)), - UnpackedKind::Type(ty) => p!(write("{:?}", ty)), - } - } } } From 093756133541dc12f5cee147cabcece1aaeaf446 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 20 Jan 2019 04:56:48 +0200 Subject: [PATCH 54/68] rustc: remove obsolete hacks from ppaux, relating to normalization under HRTB. --- src/librustc/ty/print/mod.rs | 47 ++++++----- src/librustc/ty/print/pretty.rs | 56 ++++++++++++- src/librustc/ty/structural_impls.rs | 10 --- src/librustc/util/ppaux.rs | 121 +++++++++++++++------------- 4 files changed, 142 insertions(+), 92 deletions(-) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index c7b898b7c5136..e6f8724694c95 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,6 +1,6 @@ use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId}; -use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use ty::{self, DefIdTree, Ty, TyCtxt}; use ty::subst::{Subst, Substs}; use rustc_data_structures::fx::FxHashSet; @@ -16,19 +16,6 @@ pub use self::pretty::*; // FIXME(eddyb) this module uses `pub(crate)` for things used only // from `ppaux` - when that is removed, they can be re-privatized. -struct LateBoundRegionNameCollector(FxHashSet); -impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { - fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { - match *r { - ty::ReLateBound(_, ty::BrNamed(_, name)) => { - self.0.insert(name); - }, - _ => {}, - } - r.super_visit_with(self) - } -} - #[derive(Default)] pub(crate) struct PrintConfig { used_region_names: Option>, @@ -67,14 +54,6 @@ impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { pub(crate) fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) } - fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) - where T: TypeFoldable<'tcx> - { - let mut collector = LateBoundRegionNameCollector(Default::default()); - value.visit_with(&mut collector); - self.config.used_region_names = Some(collector.0); - self.config.region_index = 0; - } } pub trait Print<'tcx, P> { @@ -322,3 +301,27 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { ty::Float(_) => None, } } + +impl Print<'tcx, P> for ty::RegionKind { + type Output = P::Region; + type Error = P::Error; + fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + cx.print_region(self) + } +} + +impl Print<'tcx, P> for ty::Region<'_> { + type Output = P::Region; + type Error = P::Error; + fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + cx.print_region(self) + } +} + +impl Print<'tcx, P> for Ty<'tcx> { + type Output = P::Type; + type Error = P::Error; + fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + cx.print_type(self) + } +} diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 0071f638587d9..6536ba013063c 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -206,6 +206,15 @@ pub trait PrettyPrinter: self.print_def_path(def_id, substs, iter::empty()) } + fn in_binder( + self: PrintCx<'_, '_, 'tcx, Self>, + value: &ty::Binder, + ) -> Result + where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> + { + value.skip_binder().print(self) + } + /// Print `<...>` around what `f` prints. fn generic_delimiters<'gcx, 'tcx>( self: PrintCx<'_, 'gcx, 'tcx, Self>, @@ -786,6 +795,15 @@ impl PrettyPrinter for FmtPrinter { Ok(printer) } + fn in_binder( + self: PrintCx<'_, '_, 'tcx, Self>, + value: &ty::Binder, + ) -> Result + where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> + { + self.pretty_in_binder(value) + } + fn generic_delimiters<'gcx, 'tcx>( mut self: PrintCx<'_, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, @@ -1127,7 +1145,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write(" "), print(witness), write("]")) }, ty::GeneratorWitness(types) => { - nest!(|cx| cx.pretty_in_binder(&types)) + nest!(|cx| cx.in_binder(&types)) } ty::Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, self.tcx); @@ -1246,9 +1264,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }) }; - // NOTE(eddyb) this must be below `start_or_continue`'s definition - // as that also has a `define_scoped_cx` and that kind of shadowing - // is disallowed (name resolution thinks `scoped_cx!` is ambiguous). define_scoped_cx!(self); let old_region_index = self.config.region_index; @@ -1291,6 +1306,29 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { result } + fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) + where T: TypeFoldable<'tcx> + { + + struct LateBoundRegionNameCollector(FxHashSet); + impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { + fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { + match *r { + ty::ReLateBound(_, ty::BrNamed(_, name)) => { + self.0.insert(name); + }, + _ => {}, + } + r.super_visit_with(self) + } + } + + let mut collector = LateBoundRegionNameCollector(Default::default()); + value.visit_with(&mut collector); + self.config.used_region_names = Some(collector.0); + self.config.region_index = 0; + } + fn is_name_used(&self, name: &InternedString) -> bool { match self.config.used_region_names { Some(ref names) => names.contains(name), @@ -1298,3 +1336,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } } + +impl Print<'tcx, P> for ty::Binder + where T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx> +{ + type Output = P; + type Error = P::Error; + fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + cx.in_binder(self) + } +} diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 2728f94ff141a..94f01345fffb4 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -754,16 +754,6 @@ BraceStructLiftImpl! { } } -// FIXME(eddyb) this is like what `CloneTypeFoldableAndLiftImpls!` -// generates, except that macro *also* generates a foldable impl, -// which we don't want (with it we'd risk bypassing `fold_region`). -impl<'tcx> Lift<'tcx> for ty::RegionKind { - type Lifted = ty::RegionKind; - fn lift_to_tcx<'b, 'gcx>(&self, _: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - Some(self.clone()) - } -} - BraceStructLiftImpl! { impl<'a, 'tcx> Lift<'tcx> for ty::Const<'a> { type Lifted = ty::Const<'tcx>; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 02ef97996822f..d68ad4726cc8c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,7 @@ use hir; use hir::def::Namespace; use ty::subst::{Kind, UnpackedKind}; -use ty::{self, Ty}; +use ty::{self, Ty, TyCtxt}; use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; use std::fmt; @@ -9,13 +9,60 @@ use std::iter; use rustc_target::spec::abi::Abi; +pub trait LiftAndPrintToFmt<'tcx> { + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result; +} + +impl LiftAndPrintToFmt<'tcx> for T + where T: ty::Lift<'tcx>, + for<'a, 'b> >::Lifted: + Print<'tcx, FmtPrinter<&'a mut fmt::Formatter<'b>>, Error = fmt::Error> +{ + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; + Ok(()) + }) + } +} + +// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. +impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { + self.print(cx)?; + Ok(()) + }) + } +} + macro_rules! define_print { - ([$($target:ty),+] $vars:tt $def:tt) => { - $(define_print!($target, $vars $def);)+ + (<$($T:ident),*> $target:ty) => { + impl<$($T),*> fmt::Display for $target + where Self: for<'a> LiftAndPrintToFmt<'a> + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| self.lift_and_print_to_fmt(tcx, f)) + } + } }; - ($target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { - impl Print<'tcx, P> for $target { + (<$($T:ident),*> $target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { + impl<$($T,)* P: PrettyPrinter> Print<'tcx, P> for $target + where $($T: Print<'tcx, P, Output = P, Error = P::Error>),* + { type Output = P; type Error = fmt::Error; fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { @@ -28,14 +75,15 @@ macro_rules! define_print { } } - impl fmt::Display for $target { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; - Ok(()) - }) - } - } + define_print!(<$($T),*> $target); + }; + + ($target:ty) => { + define_print!(<> $target); + }; + + ($target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { + define_print!(<> $target, ($self, $cx) { display $disp }); }; } @@ -171,11 +219,7 @@ define_print! { } define_print! { - ty::RegionKind, (self, cx) { - display { - return cx.print_region(self); - } - } + ty::RegionKind } define_print! { @@ -214,34 +258,8 @@ define_print! { } } -// The generic impl doesn't work yet because projections are not -// normalized under HRTB. -/*impl fmt::Display for ty::Binder - where T: fmt::Display + for<'a> ty::Lift<'a>, - for<'a> >::Lifted: fmt::Display + TypeFoldable<'a> -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(|cx| cx.pretty_in_binder(cx.tcx.lift(self) - .expect("could not lift for printing"))) - } -}*/ - define_print! { - [ - ty::Binder<&'tcx ty::List>>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder>, - ty::Binder, ty::Region<'tcx>>>, - ty::Binder, ty::Region<'tcx>>> - ] - (self, cx) { - display { - nest!(|cx| cx.pretty_in_binder(self)) - } - } + ty::Binder } define_print! { @@ -253,11 +271,7 @@ define_print! { } define_print! { - Ty<'tcx>, (self, cx) { - display { - return cx.print_type(self); - } - } + Ty<'tcx> } define_print! { @@ -268,13 +282,8 @@ define_print! { } } -// Similar problem to `Binder`, can't define a generic impl. define_print! { - [ - ty::OutlivesPredicate, ty::Region<'tcx>>, - ty::OutlivesPredicate, ty::Region<'tcx>> - ] - (self, cx) { + ty::OutlivesPredicate, (self, cx) { display { p!(print(self.0), write(" : "), print(self.1)) } From 55b419305ca1bb9ed074b6989dc0e0d231671c45 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 20 Jan 2019 14:00:39 +0200 Subject: [PATCH 55/68] rustc: streamline the Print/fmt::Display impls in ppaux and move them to ty::print::pretty. --- src/librustc/lib.rs | 1 - src/librustc/ty/print/mod.rs | 9 +- src/librustc/ty/print/pretty.rs | 275 +++++++++++++++++++++++ src/librustc/util/ppaux.rs | 376 -------------------------------- 4 files changed, 278 insertions(+), 383 deletions(-) delete mode 100644 src/librustc/util/ppaux.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index a1e581fd56eb2..ce7b228a52709 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -154,7 +154,6 @@ pub mod ty; pub mod util { pub mod captures; pub mod common; - mod ppaux; pub mod nodemap; pub mod time_graph; pub mod profiling; diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index e6f8724694c95..d6ce7d8b5a3d0 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -13,11 +13,8 @@ use std::ops::Deref; mod pretty; pub use self::pretty::*; -// FIXME(eddyb) this module uses `pub(crate)` for things used only -// from `ppaux` - when that is removed, they can be re-privatized. - #[derive(Default)] -pub(crate) struct PrintConfig { +struct PrintConfig { used_region_names: Option>, region_index: usize, binder_depth: usize, @@ -26,7 +23,7 @@ pub(crate) struct PrintConfig { pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, pub printer: P, - pub(crate) config: &'a mut PrintConfig, + config: &'a mut PrintConfig, } // HACK(eddyb) this is solely for `self: PrintCx`, e.g. to @@ -51,7 +48,7 @@ impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { }) } - pub(crate) fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { + pub fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 6536ba013063c..f53224027c08d 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -9,6 +9,7 @@ use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::{keywords, Symbol}; +use rustc_target::spec::abi::Abi; use syntax::symbol::InternedString; use std::cell::Cell; @@ -1346,3 +1347,277 @@ impl Print<'tcx, P> for ty::Binder cx.in_binder(self) } } + +pub trait LiftAndPrintToFmt<'tcx> { + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result; +} + +impl LiftAndPrintToFmt<'tcx> for T + where T: ty::Lift<'tcx>, + for<'a, 'b> >::Lifted: + Print<'tcx, FmtPrinter<&'a mut fmt::Formatter<'b>>, Error = fmt::Error> +{ + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { + cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; + Ok(()) + }) + } +} + +// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. +impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { + fn lift_and_print_to_fmt( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { + self.print(cx)?; + Ok(()) + }) + } +} + +macro_rules! forward_display_to_print { + (<$($T:ident),*> $ty:ty) => { + impl<$($T),*> fmt::Display for $ty + where Self: for<'a> LiftAndPrintToFmt<'a> + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| self.lift_and_print_to_fmt(tcx, f)) + } + } + }; + + ($ty:ty) => { + forward_display_to_print!(<> $ty); + }; +} + +macro_rules! define_print_and_forward_display { + (($self:ident, $cx:ident): <$($T:ident),*> $ty:ty $print:block) => { + impl<$($T,)* P: PrettyPrinter> Print<'tcx, P> for $ty + where $($T: Print<'tcx, P, Output = P, Error = P::Error>),* + { + type Output = P; + type Error = fmt::Error; + fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + #[allow(unused_mut)] + let mut $cx = $cx; + define_scoped_cx!($cx); + let _: () = $print; + #[allow(unreachable_code)] + Ok($cx.printer) + } + } + + forward_display_to_print!(<$($T),*> $ty); + }; + + (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { + $(define_print_and_forward_display!(($self, $cx): <> $ty $print);)+ + }; +} + +forward_display_to_print!(ty::RegionKind); +forward_display_to_print!(Ty<'tcx>); +forward_display_to_print!( ty::Binder); + +define_print_and_forward_display! { + (self, cx): + + ty::OutlivesPredicate { + p!(print(self.0), write(" : "), print(self.1)) + } +} + +define_print_and_forward_display! { + (self, cx): + + &'tcx ty::List> { + // Generate the main trait ref, including associated types. + let mut first = true; + + if let Some(principal) = self.principal() { + let mut resugared_principal = false; + + // Special-case `Fn(...) -> ...` and resugar it. + let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); + if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() { + if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { + let mut projections = self.projection_bounds(); + if let (Some(proj), None) = (projections.next(), projections.next()) { + nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); + nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); + resugared_principal = true; + } + } + } + + if !resugared_principal { + // Use a type that can't appear in defaults of type parameters. + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); + let principal = principal.with_self_ty(cx.tcx, dummy_self); + nest!(|cx| cx.print_def_path( + principal.def_id, + Some(principal.substs), + self.projection_bounds(), + )); + } + first = false; + } + + // Builtin bounds. + // FIXME(eddyb) avoid printing twice (needed to ensure + // that the auto traits are sorted *and* printed via cx). + let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { + (cx.tcx.def_path_str(did), did) + }).collect(); + + // The auto traits come ordered by `DefPathHash`. While + // `DefPathHash` is *stable* in the sense that it depends on + // neither the host nor the phase of the moon, it depends + // "pseudorandomly" on the compiler version and the target. + // + // To avoid that causing instabilities in compiletest + // output, sort the auto-traits alphabetically. + auto_traits.sort(); + + for (_, def_id) in auto_traits { + if !first { + p!(write(" + ")); + } + first = false; + + nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); + } + } + + &'tcx ty::List> { + p!(write("{{")); + let mut tys = self.iter(); + if let Some(&ty) = tys.next() { + p!(print(ty)); + for &ty in tys { + p!(write(", "), print(ty)); + } + } + p!(write("}}")) + } + + ty::TypeAndMut<'tcx> { + p!(write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), + print(self.ty)) + } + + ty::ExistentialTraitRef<'tcx> { + let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); + + let trait_ref = *ty::Binder::bind(*self) + .with_self_ty(cx.tcx, dummy_self) + .skip_binder(); + p!(print(trait_ref)) + } + + ty::FnSig<'tcx> { + if self.unsafety == hir::Unsafety::Unsafe { + p!(write("unsafe ")); + } + + if self.abi != Abi::Rust { + p!(write("extern {} ", self.abi)); + } + + p!(write("fn")); + nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); + } + + ty::InferTy { + if cx.tcx.sess.verbose() { + p!(write("{:?}", self)); + return Ok(cx.printer); + } + match *self { + ty::TyVar(_) => p!(write("_")), + ty::IntVar(_) => p!(write("{}", "{integer}")), + ty::FloatVar(_) => p!(write("{}", "{float}")), + ty::FreshTy(v) => p!(write("FreshTy({})", v)), + ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)), + ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) + } + } + + ty::TraitRef<'tcx> { + nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); + } + + ty::ParamTy { + p!(write("{}", self.name)) + } + + ty::SubtypePredicate<'tcx> { + p!(print(self.a), write(" <: "), print(self.b)) + } + + ty::TraitPredicate<'tcx> { + p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + } + + ty::ProjectionPredicate<'tcx> { + p!(print(self.projection_ty), write(" == "), print(self.ty)) + } + + ty::ProjectionTy<'tcx> { + nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); + } + + ty::ClosureKind { + match *self { + ty::ClosureKind::Fn => p!(write("Fn")), + ty::ClosureKind::FnMut => p!(write("FnMut")), + ty::ClosureKind::FnOnce => p!(write("FnOnce")), + } + } + + ty::Predicate<'tcx> { + match *self { + ty::Predicate::Trait(ref data) => p!(print(data)), + ty::Predicate::Subtype(ref predicate) => p!(print(predicate)), + ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)), + ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)), + ty::Predicate::Projection(ref predicate) => p!(print(predicate)), + ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), + ty::Predicate::ObjectSafe(trait_def_id) => { + p!(write("the trait `")); + nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty())); + p!(write("` is object-safe")) + } + ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { + p!(write("the closure `")); + nest!(|cx| cx.print_value_path(closure_def_id, None)); + p!(write("` implements the trait `{}`", kind)) + } + ty::Predicate::ConstEvaluatable(def_id, substs) => { + p!(write("the constant `")); + nest!(|cx| cx.print_value_path(def_id, Some(substs))); + p!(write("` can be evaluated")) + } + } + } + + Kind<'tcx> { + match self.unpack() { + UnpackedKind::Lifetime(lt) => p!(print(lt)), + UnpackedKind::Type(ty) => p!(print(ty)), + } + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs deleted file mode 100644 index d68ad4726cc8c..0000000000000 --- a/src/librustc/util/ppaux.rs +++ /dev/null @@ -1,376 +0,0 @@ -use hir; -use hir::def::Namespace; -use ty::subst::{Kind, UnpackedKind}; -use ty::{self, Ty, TyCtxt}; -use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; - -use std::fmt; -use std::iter; - -use rustc_target::spec::abi::Abi; - -pub trait LiftAndPrintToFmt<'tcx> { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result; -} - -impl LiftAndPrintToFmt<'tcx> for T - where T: ty::Lift<'tcx>, - for<'a, 'b> >::Lifted: - Print<'tcx, FmtPrinter<&'a mut fmt::Formatter<'b>>, Error = fmt::Error> -{ - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; - Ok(()) - }) - } -} - -// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. -impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { - self.print(cx)?; - Ok(()) - }) - } -} - -macro_rules! define_print { - (<$($T:ident),*> $target:ty) => { - impl<$($T),*> fmt::Display for $target - where Self: for<'a> LiftAndPrintToFmt<'a> - { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| self.lift_and_print_to_fmt(tcx, f)) - } - } - }; - - (<$($T:ident),*> $target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { - impl<$($T,)* P: PrettyPrinter> Print<'tcx, P> for $target - where $($T: Print<'tcx, P, Output = P, Error = P::Error>),* - { - type Output = P; - type Error = fmt::Error; - fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { - #[allow(unused_mut)] - let mut $cx = $cx; - define_scoped_cx!($cx); - let _: () = $disp; - #[allow(unreachable_code)] - Ok($cx.printer) - } - } - - define_print!(<$($T),*> $target); - }; - - ($target:ty) => { - define_print!(<> $target); - }; - - ($target:ty, ($self:ident, $cx:ident) { display $disp:block }) => { - define_print!(<> $target, ($self, $cx) { display $disp }); - }; -} - -macro_rules! nest { - ($closure:expr) => { - scoped_cx!() = scoped_cx!().nest($closure)? - } -} -macro_rules! print_inner { - (write ($($data:expr),+)) => { - write!(scoped_cx!().printer, $($data),+)? - }; - ($kind:ident ($data:expr)) => { - nest!(|cx| $data.$kind(cx)) - }; -} -macro_rules! p { - ($($kind:ident $data:tt),+) => { - { - $(print_inner!($kind $data));+ - } - }; -} -macro_rules! define_scoped_cx { - ($cx:ident) => { - #[allow(unused_macros)] - macro_rules! scoped_cx { - () => ($cx) - } - }; -} - -define_print! { - &'tcx ty::List>, (self, cx) { - display { - // Generate the main trait ref, including associated types. - let mut first = true; - - if let Some(principal) = self.principal() { - let mut resugared_principal = false; - - // Special-case `Fn(...) -> ...` and resugar it. - let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); - if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { - let mut projections = self.projection_bounds(); - if let (Some(proj), None) = (projections.next(), projections.next()) { - nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); - nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); - resugared_principal = true; - } - } - } - - if !resugared_principal { - // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let principal = principal.with_self_ty(cx.tcx, dummy_self); - nest!(|cx| cx.print_def_path( - principal.def_id, - Some(principal.substs), - self.projection_bounds(), - )); - } - first = false; - } - - // Builtin bounds. - // FIXME(eddyb) avoid printing twice (needed to ensure - // that the auto traits are sorted *and* printed via cx). - let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { - (cx.tcx.def_path_str(did), did) - }).collect(); - - // The auto traits come ordered by `DefPathHash`. While - // `DefPathHash` is *stable* in the sense that it depends on - // neither the host nor the phase of the moon, it depends - // "pseudorandomly" on the compiler version and the target. - // - // To avoid that causing instabilities in compiletest - // output, sort the auto-traits alphabetically. - auto_traits.sort(); - - for (_, def_id) in auto_traits { - if !first { - p!(write(" + ")); - } - first = false; - - nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); - } - } - } -} - -define_print! { - &'tcx ty::List>, (self, cx) { - display { - p!(write("{{")); - let mut tys = self.iter(); - if let Some(&ty) = tys.next() { - p!(print(ty)); - for &ty in tys { - p!(write(", "), print(ty)); - } - } - p!(write("}}")) - } - } -} - -define_print! { - ty::TypeAndMut<'tcx>, (self, cx) { - display { - p!( - write("{}", if self.mutbl == hir::MutMutable { "mut " } else { "" }), - print(self.ty)) - } - } -} - -define_print! { - ty::ExistentialTraitRef<'tcx>, (self, cx) { - display { - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - - let trait_ref = *ty::Binder::bind(*self) - .with_self_ty(cx.tcx, dummy_self) - .skip_binder(); - p!(print(trait_ref)) - } - } -} - -define_print! { - ty::RegionKind -} - -define_print! { - ty::FnSig<'tcx>, (self, cx) { - display { - if self.unsafety == hir::Unsafety::Unsafe { - p!(write("unsafe ")); - } - - if self.abi != Abi::Rust { - p!(write("extern {} ", self.abi)); - } - - p!(write("fn")); - nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); - } - } -} - -define_print! { - ty::InferTy, (self, cx) { - display { - if cx.tcx.sess.verbose() { - p!(write("{:?}", self)); - return Ok(cx.printer); - } - match *self { - ty::TyVar(_) => p!(write("_")), - ty::IntVar(_) => p!(write("{}", "{integer}")), - ty::FloatVar(_) => p!(write("{}", "{float}")), - ty::FreshTy(v) => p!(write("FreshTy({})", v)), - ty::FreshIntTy(v) => p!(write("FreshIntTy({})", v)), - ty::FreshFloatTy(v) => p!(write("FreshFloatTy({})", v)) - } - } - } -} - -define_print! { - ty::Binder -} - -define_print! { - ty::TraitRef<'tcx>, (self, cx) { - display { - nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); - } - } -} - -define_print! { - Ty<'tcx> -} - -define_print! { - ty::ParamTy, (self, cx) { - display { - p!(write("{}", self.name)) - } - } -} - -define_print! { - ty::OutlivesPredicate, (self, cx) { - display { - p!(print(self.0), write(" : "), print(self.1)) - } - } -} - -define_print! { - ty::SubtypePredicate<'tcx>, (self, cx) { - display { - p!(print(self.a), write(" <: "), print(self.b)) - } - } -} - -define_print! { - ty::TraitPredicate<'tcx>, (self, cx) { - display { - p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) - } - } -} - -define_print! { - ty::ProjectionPredicate<'tcx>, (self, cx) { - display { - p!(print(self.projection_ty), write(" == "), print(self.ty)) - } - } -} - -define_print! { - ty::ProjectionTy<'tcx>, (self, cx) { - display { - nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); - } - } -} - -define_print! { - ty::ClosureKind, (self, cx) { - display { - match *self { - ty::ClosureKind::Fn => p!(write("Fn")), - ty::ClosureKind::FnMut => p!(write("FnMut")), - ty::ClosureKind::FnOnce => p!(write("FnOnce")), - } - } - } -} - -define_print! { - ty::Predicate<'tcx>, (self, cx) { - display { - match *self { - ty::Predicate::Trait(ref data) => p!(print(data)), - ty::Predicate::Subtype(ref predicate) => p!(print(predicate)), - ty::Predicate::RegionOutlives(ref predicate) => p!(print(predicate)), - ty::Predicate::TypeOutlives(ref predicate) => p!(print(predicate)), - ty::Predicate::Projection(ref predicate) => p!(print(predicate)), - ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), - ty::Predicate::ObjectSafe(trait_def_id) => { - p!(write("the trait `")); - nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty())); - p!(write("` is object-safe")) - } - ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - p!(write("the closure `")); - nest!(|cx| cx.print_value_path(closure_def_id, None)); - p!(write("` implements the trait `{}`", kind)) - } - ty::Predicate::ConstEvaluatable(def_id, substs) => { - p!(write("the constant `")); - nest!(|cx| cx.print_value_path(def_id, Some(substs))); - p!(write("` can be evaluated")) - } - } - } - } -} - -define_print! { - Kind<'tcx>, (self, cx) { - display { - match self.unpack() { - UnpackedKind::Lifetime(lt) => p!(print(lt)), - UnpackedKind::Type(ty) => p!(print(ty)), - } - } - } -} From dda6ae8179f4d18d082f875f51ac1b7fb2dc8766 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 20 Jan 2019 19:46:47 +0200 Subject: [PATCH 56/68] rustc: move ty::print::PrintConfig's fields to FmtPrinter. --- src/librustc/infer/error_reporting/mod.rs | 5 +- .../infer/error_reporting/need_type_info.rs | 4 +- .../nice_region_error/placeholder_error.rs | 22 +- src/librustc/ty/print/mod.rs | 48 ++- src/librustc/ty/print/pretty.rs | 279 +++++++++--------- src/librustc_codegen_utils/symbol_names.rs | 19 +- .../borrow_check/error_reporting.rs | 8 +- src/librustdoc/clean/mod.rs | 6 +- 8 files changed, 195 insertions(+), 196 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index d256e72aafeaa..b020bb4a7f122 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -527,9 +527,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // module we could have false positives if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { - PrintCx::with(self.tcx, AbsolutePathPrinter, |cx| { - cx.print_def_path(def_id, None, iter::empty()) - }) + PrintCx::new(self.tcx, AbsolutePathPrinter) + .print_def_path(def_id, None, iter::empty()) }; // We compare strings because DefPath can be different diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index e2cf351ca2065..15863a044cd6c 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -84,9 +84,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; } - let _ = ty::print::PrintCx::with(self.tcx, printer, |cx| { - ty.print(cx) - }); + let _ = ty.print(ty::print::PrintCx::new(self.tcx, printer)); s } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index eb0ce6757f245..ed415d1268c65 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -250,13 +250,14 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { printer.region_highlight_mode.maybe_highlighting_region(sub_placeholder, has_sub); printer.region_highlight_mode.maybe_highlighting_region(sup_placeholder, has_sup); - let _ = ty::print::PrintCx::with(self.tcx, printer, |mut cx| { - write!(cx.printer, "`")?; + let _ = (|| { + let mut cx = ty::print::PrintCx::new(self.tcx, printer); + write!(cx, "`")?; cx = cx.nest(|cx| expected_trait_ref.self_ty().print(cx))?; - write!(cx.printer, "` must implement `")?; + write!(cx, "` must implement `")?; cx = cx.nest(|cx| expected_trait_ref.print(cx))?; - write!(cx.printer, "`") - }); + write!(cx, "`") + })(); match (has_sub, has_sup) { (Some(n1), Some(n2)) => { @@ -283,13 +284,14 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let mut printer = ty::print::FmtPrinter::new(&mut note, Namespace::TypeNS); printer.region_highlight_mode.maybe_highlighting_region(vid, has_vid); - let _ = ty::print::PrintCx::with(self.tcx, printer, |mut cx| { - write!(cx.printer, "but `")?; + let _ = (|| { + let mut cx = ty::print::PrintCx::new(self.tcx, printer); + write!(cx, "but `")?; cx = cx.nest(|cx| actual_trait_ref.self_ty().print(cx))?; - write!(cx.printer, "` only implements `")?; + write!(cx, "` only implements `")?; cx = cx.nest(|cx| actual_trait_ref.print(cx))?; - write!(cx.printer, "`") - }); + write!(cx, "`") + })(); if let Some(n) = has_vid { let _ = write!(note, diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index d6ce7d8b5a3d0..77a80b0707129 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -4,52 +4,50 @@ use ty::{self, DefIdTree, Ty, TyCtxt}; use ty::subst::{Subst, Substs}; use rustc_data_structures::fx::FxHashSet; -use syntax::symbol::InternedString; use std::iter; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. mod pretty; pub use self::pretty::*; -#[derive(Default)] -struct PrintConfig { - used_region_names: Option>, - region_index: usize, - binder_depth: usize, -} - pub struct PrintCx<'a, 'gcx, 'tcx, P> { pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - pub printer: P, - config: &'a mut PrintConfig, + inner: P, } -// HACK(eddyb) this is solely for `self: PrintCx`, e.g. to -// implement traits on the printer and call the methods on the context. impl

Deref for PrintCx<'_, '_, '_, P> { type Target = P; fn deref(&self) -> &P { - &self.printer + &self.inner + } +} + +impl

DerefMut for PrintCx<'_, '_, '_, P> { + fn deref_mut(&mut self) -> &mut P { + &mut self.inner } } impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { - pub fn with( - tcx: TyCtxt<'a, 'gcx, 'tcx>, - printer: P, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, P>) -> R, - ) -> R { - f(PrintCx { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, inner: P) -> Self { + PrintCx { tcx, - printer, - config: &mut PrintConfig::default(), - }) + inner, + } + } + + pub fn with_tls_tcx(inner: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { + ty::tls::with(|tcx| f(PrintCx::new(tcx, inner))) + } + + pub fn into_inner(self) -> P { + self.inner } - pub fn with_tls_tcx(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { - ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) + pub fn ok(self) -> Result { + Ok(self.into_inner()) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index f53224027c08d..9355564337ee4 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -15,6 +15,7 @@ use syntax::symbol::InternedString; use std::cell::Cell; use std::fmt::{self, Write as _}; use std::iter; +use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. use super::*; @@ -26,7 +27,7 @@ macro_rules! nest { } macro_rules! print_inner { (write ($($data:expr),+)) => { - write!(scoped_cx!().printer, $($data),+)? + write!(scoped_cx!(), $($data),+)? }; ($kind:ident ($data:expr)) => { nest!(|cx| $data.$kind(cx)) @@ -186,16 +187,7 @@ pub trait PrettyPrinter: self: PrintCx<'a, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result, E> { - let printer = f(PrintCx { - tcx: self.tcx, - printer: self.printer, - config: self.config, - })?; - Ok(PrintCx { - tcx: self.tcx, - printer, - config: self.config, - }) + Ok(PrintCx::new(self.tcx, f(self)?)) } /// Like `print_def_path` but for value paths. @@ -244,6 +236,12 @@ pub trait PrettyPrinter: ) -> bool; } +impl fmt::Write for PrintCx<'_, '_, '_, P> { + fn write_str(&mut self, s: &str) -> fmt::Result { + (**self).write_str(s) + } +} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always // (but also some things just print a `DefId` generally so maybe we need this?) @@ -268,31 +266,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let ns = self.guess_def_namespace(def_id); debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); - let _ = PrintCx::with(self, FmtPrinter::new(&mut s, ns), |cx| { - cx.print_def_path(def_id, None, iter::empty()) - }); + let _ = PrintCx::new(self, FmtPrinter::new(&mut s, ns)) + .print_def_path(def_id, None, iter::empty()); s } } -pub struct FmtPrinter { - fmt: F, - empty: bool, - in_value: bool, - pub region_highlight_mode: RegionHighlightMode, -} - -impl FmtPrinter { - pub fn new(fmt: F, ns: Namespace) -> Self { - FmtPrinter { - fmt, - empty: true, - in_value: ns == Namespace::ValueNS, - region_highlight_mode: RegionHighlightMode::default(), - } - } -} - impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is @@ -346,7 +325,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } if def_id.is_local() { - return Ok((self.printer, false)); + return self.ok().map(|path| (path, false)); } let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); @@ -366,7 +345,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let visible_parent = match visible_parent_map.get(&def_id).cloned() { Some(parent) => parent, - None => return Ok((self.printer, false)), + None => return self.ok().map(|path| (path, false)), }; // HACK(eddyb) this uses `nest` to avoid knowing ahead of time whether // the entire path will succeed or not. To support printers that do not @@ -374,12 +353,12 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // need to be built, before starting to print anything. let mut prefix_success = false; nest!(|cx| { - let (printer, success) = cx.try_print_visible_def_path(visible_parent)?; + let (path, success) = cx.try_print_visible_def_path(visible_parent)?; prefix_success = success; - Ok(printer) + Ok(path) }); if !prefix_success { - return Ok((self.printer, false)); + return self.ok().map(|path| (path, false)); }; let actual_parent = self.tcx.parent(def_id); debug!( @@ -448,7 +427,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }, }; debug!("try_print_visible_def_path: symbol={:?}", symbol); - Ok((self.path_append(|cx| Ok(cx.printer), &symbol)?, true)) + Ok((self.path_append(|cx| cx.ok(), &symbol)?, true)) } pub fn pretty_path_qualified( @@ -478,7 +457,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { if let Some(trait_ref) = trait_ref { p!(write(" as "), print(trait_ref)); } - Ok(cx.printer) + cx.ok() }) } @@ -501,7 +480,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(print(self_ty)); - Ok(cx.printer) + cx.ok() }) } @@ -558,7 +537,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let projection0 = projections.next(); if arg0.is_none() && projection0.is_none() { - return Ok(self.printer); + return self.ok(); } self.generic_delimiters(|mut cx| { @@ -570,7 +549,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { empty = false; Ok(()) } else { - write!(cx.printer, ", ") + write!(cx, ", ") } }; @@ -600,11 +579,54 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { print(projection.ty)); } - Ok(cx.printer) + cx.ok() }) } } +// HACK(eddyb) boxed to avoid moving around a large struct by-value. +pub struct FmtPrinter(Box>); + +pub struct FmtPrinterData { + fmt: F, + + empty: bool, + in_value: bool, + + used_region_names: FxHashSet, + region_index: usize, + binder_depth: usize, + + pub region_highlight_mode: RegionHighlightMode, +} + +impl Deref for FmtPrinter { + type Target = FmtPrinterData; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for FmtPrinter { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl FmtPrinter { + pub fn new(fmt: F, ns: Namespace) -> Self { + FmtPrinter(Box::new(FmtPrinterData { + fmt, + empty: true, + in_value: ns == Namespace::ValueNS, + used_region_names: Default::default(), + region_index: 0, + binder_depth: 0, + region_highlight_mode: RegionHighlightMode::default(), + })) + } +} + impl fmt::Write for FmtPrinter { fn write_str(&mut self, s: &str) -> fmt::Result { self.empty &= s.is_empty(); @@ -631,17 +653,17 @@ impl Printer for FmtPrinter { if generics.as_ref().and_then(|g| g.parent).is_none() { let mut visible_path_success = false; self = self.nest(|cx| { - let (printer, success) = cx.try_print_visible_def_path(def_id)?; + let (path, success) = cx.try_print_visible_def_path(def_id)?; visible_path_success = success; - Ok(printer) + Ok(path) })?; if visible_path_success { return if let (Some(generics), Some(substs)) = (generics, substs) { let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; - self.path_generic_args(|cx| Ok(cx.printer), params, substs, projections) + self.path_generic_args(|cx| cx.ok(), params, substs, projections) } else { - Ok(self.printer) + self.ok() }; } } @@ -695,14 +717,13 @@ impl Printer for FmtPrinter { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - write!(self.printer, "{}", keywords::Crate.name())?; + write!(self, "{}", keywords::Crate.name())?; } } - Ok(self.printer) } else { - write!(self.printer, "{}", self.tcx.crate_name(cnum))?; - Ok(self.printer) + write!(self, "{}", self.tcx.crate_name(cnum))?; } + self.ok() } fn path_qualified( self: PrintCx<'_, '_, 'tcx, Self>, @@ -721,15 +742,15 @@ impl Printer for FmtPrinter { trait_ref: Option>, ) -> Result { self.pretty_path_append_impl(|cx| { - let mut printer = print_prefix(cx)?; + let mut path = print_prefix(cx)?; // HACK(eddyb) this accounts for `generic_delimiters` // printing `::<` instead of `<` if `in_value` is set. - if !printer.empty && !printer.in_value { - write!(printer, "::")?; + if !path.empty && !path.in_value { + write!(path, "::")?; } - Ok(printer) + Ok(path) }, self_ty, trait_ref) } fn path_append<'gcx, 'tcx>( @@ -739,18 +760,18 @@ impl Printer for FmtPrinter { ) -> Result, text: &str, ) -> Result { - let mut printer = print_prefix(self)?; + let mut path = print_prefix(self)?; // FIXME(eddyb) `text` should never be empty, but it // currently is for `extern { ... }` "foreign modules". if !text.is_empty() { - if !printer.empty { - write!(printer, "::")?; + if !path.empty { + write!(path, "::")?; } - write!(printer, "{}", text)?; + write!(path, "{}", text)?; } - Ok(printer) + Ok(path) } fn path_generic_args<'gcx, 'tcx>( self: PrintCx<'_, 'gcx, 'tcx, Self>, @@ -770,18 +791,11 @@ impl PrettyPrinter for FmtPrinter { mut self: PrintCx<'a, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result, E> { - let was_empty = std::mem::replace(&mut self.printer.empty, true); - let mut printer = f(PrintCx { - tcx: self.tcx, - printer: self.printer, - config: self.config, - })?; - printer.empty &= was_empty; - Ok(PrintCx { - tcx: self.tcx, - printer, - config: self.config, - }) + let tcx = self.tcx; + let was_empty = std::mem::replace(&mut self.empty, true); + let mut inner = f(self)?; + inner.empty &= was_empty; + Ok(PrintCx::new(tcx, inner)) } fn print_value_path( @@ -789,11 +803,11 @@ impl PrettyPrinter for FmtPrinter { def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ) -> Result { - let was_in_value = std::mem::replace(&mut self.printer.in_value, true); - let mut printer = self.print_def_path(def_id, substs, iter::empty())?; - printer.in_value = was_in_value; + let was_in_value = std::mem::replace(&mut self.in_value, true); + let mut path = self.print_def_path(def_id, substs, iter::empty())?; + path.in_value = was_in_value; - Ok(printer) + Ok(path) } fn in_binder( @@ -809,18 +823,18 @@ impl PrettyPrinter for FmtPrinter { mut self: PrintCx<'_, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result { - if !self.printer.empty && self.printer.in_value { - write!(self.printer, "::<")?; + if !self.empty && self.in_value { + write!(self, "::<")?; } else { - write!(self.printer, "<")?; + write!(self, "<")?; } - let was_in_value = std::mem::replace(&mut self.printer.in_value, false); - let mut printer = f(self)?; - printer.in_value = was_in_value; + let was_in_value = std::mem::replace(&mut self.in_value, false); + let mut inner = f(self)?; + inner.in_value = was_in_value; - write!(printer, ">")?; - Ok(printer) + write!(inner, ">")?; + Ok(inner) } fn always_print_region_in_paths( @@ -834,7 +848,7 @@ impl PrettyPrinter for FmtPrinter { self: &PrintCx<'_, '_, '_, Self>, region: ty::Region<'_>, ) -> bool { - let highlight = self.printer.region_highlight_mode; + let highlight = self.region_highlight_mode; if highlight.region_highlighted(region).is_some() { return true; } @@ -891,15 +905,15 @@ impl FmtPrinter { define_scoped_cx!(self); // Watch out for region highlights. - let highlight = self.printer.region_highlight_mode; + let highlight = self.region_highlight_mode; if let Some(n) = highlight.region_highlighted(region) { p!(write("'{}", n)); - return Ok(self.printer); + return self.ok(); } if self.tcx.sess.verbose() { p!(write("{:?}", region)); - return Ok(self.printer); + return self.ok(); } let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; @@ -920,7 +934,7 @@ impl FmtPrinter { if let ty::BrNamed(_, name) = br { if name != "" && name != "'_" { p!(write("{}", name)); - return Ok(self.printer); + return self.ok(); } } @@ -960,7 +974,7 @@ impl FmtPrinter { ty::ReClosureBound(vid) => p!(write("{:?}", vid)), } - Ok(self.printer) + self.ok() } } @@ -1058,7 +1072,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // FIXME(eddyb) print this with `print_def_path`. if self.tcx.sess.verbose() { p!(write("Opaque({:?}, {:?})", def_id, substs)); - return Ok(self.printer); + return self.ok(); } let def_key = self.tcx.def_key(def_id); @@ -1074,7 +1088,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(write(">")); } - return Ok(self.printer); + return self.ok(); } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. @@ -1205,7 +1219,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - Ok(self.printer) + self.ok() } pub fn pretty_fn_sig( @@ -1232,11 +1246,18 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write(" -> "), print(output)); } - Ok(self.printer) + self.ok() } +} - pub fn pretty_in_binder(mut self, value: &ty::Binder) -> Result - where T: Print<'tcx, P, Output = P, Error = fmt::Error> + TypeFoldable<'tcx> +// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, +// `region_index` and `used_region_names`. +impl FmtPrinter { + pub fn pretty_in_binder( + mut self: PrintCx<'_, '_, 'tcx, Self>, + value: &ty::Binder, + ) -> Result + where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx> { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -1251,13 +1272,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // 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.config.binder_depth == 0 { + if self.binder_depth == 0 { self.prepare_late_bound_region_info(value); } let mut empty = true; let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - write!(cx.printer, "{}", if empty { + write!(cx, "{}", if empty { empty = false; start } else { @@ -1267,13 +1288,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { define_scoped_cx!(self); - let old_region_index = self.config.region_index; + let old_region_index = self.region_index; let mut region_index = old_region_index; let new_value = self.tcx.replace_late_bound_regions(value, |br| { let _ = start_or_continue(&mut self, "for<", ", "); let br = match br { ty::BrNamed(_, name) => { - let _ = write!(self.printer, "{}", name); + let _ = write!(self, "{}", name); br } ty::BrAnon(_) | @@ -1282,11 +1303,11 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let name = loop { let name = name_by_region_index(region_index); region_index += 1; - if !self.is_name_used(&name) { + if !self.used_region_names.contains(&name) { break name; } }; - let _ = write!(self.printer, "{}", name); + let _ = write!(self, "{}", name); ty::BrNamed(DefId::local(CRATE_DEF_INDEX), name) } }; @@ -1294,25 +1315,20 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }).0; start_or_continue(&mut self, "", "> ")?; - // Push current state to gcx, and restore after writing new_value. - self.config.binder_depth += 1; - self.config.region_index = region_index; - let result = new_value.print(PrintCx { - tcx: self.tcx, - printer: self.printer, - config: self.config, - }); - self.config.region_index = old_region_index; - self.config.binder_depth -= 1; - result + self.binder_depth += 1; + self.region_index = region_index; + let mut inner = new_value.print(self)?; + inner.region_index = old_region_index; + inner.binder_depth -= 1; + Ok(inner) } fn prepare_late_bound_region_info(&mut self, value: &ty::Binder) - where T: TypeFoldable<'tcx> + where T: TypeFoldable<'tcx> { - struct LateBoundRegionNameCollector(FxHashSet); - impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector { + struct LateBoundRegionNameCollector<'a>(&'a mut FxHashSet); + impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_> { fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { match *r { ty::ReLateBound(_, ty::BrNamed(_, name)) => { @@ -1324,17 +1340,10 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - let mut collector = LateBoundRegionNameCollector(Default::default()); + self.used_region_names.clear(); + let mut collector = LateBoundRegionNameCollector(&mut self.used_region_names); value.visit_with(&mut collector); - self.config.used_region_names = Some(collector.0); - self.config.region_index = 0; - } - - fn is_name_used(&self, name: &InternedString) -> bool { - match self.config.used_region_names { - Some(ref names) => names.contains(name), - None => false, - } + self.region_index = 0; } } @@ -1366,10 +1375,10 @@ impl LiftAndPrintToFmt<'tcx> for T tcx: TyCtxt<'_, '_, 'tcx>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.tcx.lift(self).expect("could not lift for printing").print(cx)?; - Ok(()) - }) + tcx.lift(self) + .expect("could not lift for printing") + .print(PrintCx::new(tcx, FmtPrinter::new(f, Namespace::TypeNS)))?; + Ok(()) } } @@ -1380,10 +1389,8 @@ impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { tcx: TyCtxt<'_, '_, 'tcx>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - PrintCx::with(tcx, FmtPrinter::new(f, Namespace::TypeNS), |cx| { - self.print(cx)?; - Ok(()) - }) + self.print(PrintCx::new(tcx, FmtPrinter::new(f, Namespace::TypeNS)))?; + Ok(()) } } @@ -1416,7 +1423,7 @@ macro_rules! define_print_and_forward_display { define_scoped_cx!($cx); let _: () = $print; #[allow(unreachable_code)] - Ok($cx.printer) + $cx.ok() } } @@ -1544,7 +1551,7 @@ define_print_and_forward_display! { ty::InferTy { if cx.tcx.sess.verbose() { p!(write("{:?}", self)); - return Ok(cx.printer); + return cx.ok(); } match *self { ty::TyVar(_) => p!(write("_")), diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 593aef546fdb8..0fd53a9ecf9db 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -222,11 +222,10 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - PrintCx::with(tcx, SymbolPath::new(), |cx| { - cx.print_def_path(def_id, None, iter::empty()) - .unwrap() - .into_interned() - }) + PrintCx::new(tcx, SymbolPath::new()) + .print_def_path(def_id, None, iter::empty()) + .unwrap() + .into_interned() } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { @@ -416,7 +415,7 @@ impl Printer for SymbolPath { self: PrintCx<'_, '_, '_, Self>, _region: ty::Region<'_>, ) -> Result { - Ok(self.printer) + self.ok() } fn print_type( @@ -441,8 +440,8 @@ impl Printer for SymbolPath { mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { - self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?; - Ok(self.printer) + self.write_str(&self.tcx.original_crate_name(cnum).as_str())?; + self.ok() } fn path_qualified( self: PrintCx<'_, '_, 'tcx, Self>, @@ -525,10 +524,10 @@ impl PrettyPrinter for SymbolPath { mut self: PrintCx<'_, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result { - write!(self.printer, "<")?; + write!(self, "<")?; let kept_within_component = - mem::replace(&mut self.printer.keep_within_component, true); + mem::replace(&mut self.keep_within_component, true); let mut path = f(self)?; path.keep_within_component = kept_within_component; diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 09f6379cb18f5..9bcecaa489483 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -2323,9 +2323,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => {} } - let _ = ty::print::PrintCx::with(self.infcx.tcx, printer, |cx| { - ty.print(cx) - }); + let _ = ty.print(ty::print::PrintCx::new(self.infcx.tcx, printer)); s } @@ -2350,9 +2348,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => bug!("ty for annotation of borrow region is not a reference"), }; - let _ = ty::print::PrintCx::with(self.infcx.tcx, printer, |cx| { - region.print(cx) - }); + let _ = region.print(ty::print::PrintCx::new(self.infcx.tcx, printer)); s } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 340fffd4595da..c8dd376992dee 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4132,9 +4132,9 @@ where F: Fn(DefId) -> Def { } } - let names = PrintCx::with(tcx, AbsolutePathPrinter, |cx| { - cx.print_def_path(def_id, None, iter::empty()).unwrap() - }); + let names = PrintCx::new(tcx, AbsolutePathPrinter) + .print_def_path(def_id, None, iter::empty()) + .unwrap(); hir::Path { span: DUMMY_SP, From ca9666e0fcffd100f5495be5f79f655205c6e813 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 23 Jan 2019 18:39:05 +0200 Subject: [PATCH 57/68] rustc: always hide defaulted generic args, even in verbose mode. --- src/librustc/ty/print/mod.rs | 30 +++++++++++++++++++++---- src/librustc/ty/print/pretty.rs | 23 ++----------------- src/test/ui/substs-ppaux.rs | 2 +- src/test/ui/substs-ppaux.verbose.stderr | 2 +- 4 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 77a80b0707129..6137cde0e5224 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,7 +1,7 @@ use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId}; use ty::{self, DefIdTree, Ty, TyCtxt}; -use ty::subst::{Subst, Substs}; +use ty::subst::{Kind, Subst, Substs}; use rustc_data_structures::fx::FxHashSet; @@ -129,7 +129,7 @@ pub trait Printer: Sized { ) -> Result; } -impl PrintCx<'a, 'gcx, 'tcx, P> { +impl PrintCx<'_, 'gcx, 'tcx, P> { pub fn default_print_def_path( self, def_id: DefId, @@ -197,8 +197,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { }; if let (Some(generics), Some(substs)) = (generics, substs) { - let has_own_self = generics.has_self && generics.parent_count == 0; - let params = &generics.params[has_own_self as usize..]; + let params = self.generic_params_to_print(generics, substs); self.path_generic_args(print_path, params, substs, projections) } else { print_path(self) @@ -207,6 +206,29 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } } + pub fn generic_params_to_print( + &self, + generics: &'a ty::Generics, + substs: &'tcx Substs<'tcx>, + ) -> &'a [ty::GenericParamDef] { + // Don't print args for `Self` parameters (of traits). + let has_own_self = generics.has_self && generics.parent_count == 0; + let params = &generics.params[has_own_self as usize..]; + + // Don't print args that are the defaults of their respective parameters. + let num_supplied_defaults = params.iter().rev().take_while(|param| { + match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default && substs[param.index as usize] == Kind::from( + self.tcx.type_of(param.def_id).subst(self.tcx, substs) + ) + } + } + }).count(); + ¶ms[..params.len() - num_supplied_defaults] + } + fn default_print_impl_path( self, impl_def_id: DefId, diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 9355564337ee4..cafa65e0fa5e3 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -505,24 +505,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { _ => false, } }); - - // Don't print args that are the defaults of their respective parameters. - let num_supplied_defaults = if self.tcx.sess.verbose() { - 0 - } else { - params.iter().rev().take_while(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => false, - ty::GenericParamDefKind::Type { has_default, .. } => { - has_default && substs[param.index as usize] == Kind::from( - self.tcx.type_of(param.def_id).subst(self.tcx, substs) - ) - } - } - }).count() - }; - - let params = ¶ms[..params.len() - num_supplied_defaults]; let mut args = params.iter().map(|param| { substs[param.index as usize] }).filter(|arg| { @@ -659,8 +641,7 @@ impl Printer for FmtPrinter { })?; if visible_path_success { return if let (Some(generics), Some(substs)) = (generics, substs) { - let has_own_self = generics.has_self && generics.parent_count == 0; - let params = &generics.params[has_own_self as usize..]; + let params = self.generic_params_to_print(generics, substs); self.path_generic_args(|cx| cx.ok(), params, substs, projections) } else { self.ok() @@ -778,7 +759,7 @@ impl Printer for FmtPrinter { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - params: &[ty::GenericParamDef], + mut params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, projections: impl Iterator>, ) -> Result { diff --git a/src/test/ui/substs-ppaux.rs b/src/test/ui/substs-ppaux.rs index 7ad7ccb54448f..129ebd43594ce 100644 --- a/src/test/ui/substs-ppaux.rs +++ b/src/test/ui/substs-ppaux.rs @@ -25,7 +25,7 @@ fn foo<'z>() where &'z (): Sized { let x: () = >::bar::<'static, char>; //[verbose]~^ ERROR mismatched types //[verbose]~| expected type `()` - //[verbose]~| found type `fn() {>::bar::}` + //[verbose]~| found type `fn() {>::bar::}` //[normal]~^^^^ ERROR mismatched types //[normal]~| expected type `()` //[normal]~| found type `fn() {>::bar::<'static, char>}` diff --git a/src/test/ui/substs-ppaux.verbose.stderr b/src/test/ui/substs-ppaux.verbose.stderr index 9d8a555dffe16..86936475f8c14 100644 --- a/src/test/ui/substs-ppaux.verbose.stderr +++ b/src/test/ui/substs-ppaux.verbose.stderr @@ -14,7 +14,7 @@ LL | let x: () = >::bar::<'static, char>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected (), found fn item | = note: expected type `()` - found type `fn() {>::bar::}` + found type `fn() {>::bar::}` error[E0308]: mismatched types --> $DIR/substs-ppaux.rs:33:17 From f8e402964c86de94ebabefa1a38d8436bc4681ce Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 23 Jan 2019 19:36:39 +0200 Subject: [PATCH 58/68] rustc: print elided regions as '_ instead of nothing, and use a separate check when optional. --- src/librustc/infer/error_reporting/mod.rs | 10 +++- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc/ty/error.rs | 2 +- src/librustc/ty/print/pretty.rs | 58 +++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 2 +- .../ui/issues/issue-20831-debruijn.stderr | 4 +- .../regions/regions-addr-of-upvar-self.stderr | 2 +- ...ons-return-ref-to-upvar-issue-17403.stderr | 2 +- 8 files changed, 42 insertions(+), 40 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b020bb4a7f122..4cc61d9721ca9 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -824,11 +824,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { mutbl: hir::Mutability, s: &mut DiagnosticStyledString, ) { - let r = &r.to_string(); + let mut r = r.to_string(); + if r == "'_" { + r.clear(); + } else { + r.push(' '); + } s.push_highlighted(format!( - "&{}{}{}", + "&{}{}", r, - if r == "" { "" } else { " " }, if mutbl == hir::MutMutable { "mut " } else { "" } )); s.push_normal(ty.to_string()); diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 4746802b8e28a..23232abb1a7f6 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -411,7 +411,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option< w.push('<'); w.push_str(&substs.iter() .map(|k| k.to_string()) - .filter(|k| !k.is_empty()) + .filter(|k| k != "'_") .collect::>().join(", ")); w.push('>'); } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 00e3de826d551..afb9f5cf3d406 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -171,7 +171,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { let tymut_string = tymut.to_string(); if tymut_string == "_" || //unknown type name, tymut_string.len() > 10 || //name longer than saying "reference", - region.to_string() != "" //... or a complex type + region.to_string() != "'_" //... or a complex type { format!("{}reference", match mutbl { hir::Mutability::MutMutable => "mutable ", diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index cafa65e0fa5e3..66cf38c5d2916 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -223,14 +223,10 @@ pub trait PrettyPrinter: false } - // HACK(eddyb) Trying to print a lifetime might not print anything, which - // may need special handling in the caller (of `ty::RegionKind::print`). - // To avoid printing to a temporary string (which isn't even supported), - // the `print_region_outputs_anything` method can instead be used to - // determine this, ahead of time. - // - // NB: this must be kept in sync with the implementation of `print_region`. - fn print_region_outputs_anything( + /// Return `true` if the region should be printed in + /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`. + /// This is typically the case for all non-`'_` regions. + fn region_should_not_be_omitted( self: &PrintCx<'_, '_, '_, Self>, region: ty::Region<'_>, ) -> bool; @@ -500,7 +496,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { match substs[param.index as usize].unpack() { UnpackedKind::Lifetime(r) => { self.always_print_region_in_paths(r) || - self.print_region_outputs_anything(r) + self.region_should_not_be_omitted(r) } _ => false, } @@ -538,19 +534,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { for arg in arg0.into_iter().chain(args) { maybe_comma(&mut cx)?; - if let UnpackedKind::Lifetime(region) = arg.unpack() { - if !cx.print_region_outputs_anything(region) { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - p!(write("'_")); - - continue; - } - } - p!(print(arg)); } @@ -759,7 +742,7 @@ impl Printer for FmtPrinter { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - mut params: &[ty::GenericParamDef], + params: &[ty::GenericParamDef], substs: &'tcx Substs<'tcx>, projections: impl Iterator>, ) -> Result { @@ -825,7 +808,7 @@ impl PrettyPrinter for FmtPrinter { *region != ty::ReErased } - fn print_region_outputs_anything( + fn region_should_not_be_omitted( self: &PrintCx<'_, '_, '_, Self>, region: ty::Region<'_>, ) -> bool { @@ -905,8 +888,9 @@ impl FmtPrinter { // `explain_region()` or `note_and_explain_region()`. match *region { ty::ReEarlyBound(ref data) => { - if data.name != "'_" { + if data.name != "" { p!(write("{}", data.name)); + return self.ok(); } } ty::ReLateBound(_, br) | @@ -922,6 +906,7 @@ impl FmtPrinter { if let Some((region, counter)) = highlight.highlight_bound_region { if br == region { p!(write("'{}", counter)); + return self.ok(); } } } @@ -941,20 +926,33 @@ impl FmtPrinter { first_statement_index.index() )), } + return self.ok(); } ty::ReVar(region_vid) if identify_regions => { p!(write("{:?}", region_vid)); + return self.ok(); } ty::ReVar(_) => {} ty::ReScope(_) | ty::ReErased => {} - ty::ReStatic => p!(write("'static")), - ty::ReEmpty => p!(write("'")), + ty::ReStatic => { + p!(write("'static")); + return self.ok(); + } + ty::ReEmpty => { + p!(write("'")); + return self.ok(); + } // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => p!(write("{:?}", vid)), + ty::ReClosureBound(vid) => { + p!(write("{:?}", vid)); + return self.ok(); + } } + p!(write("'_")); + self.ok() } } @@ -981,7 +979,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } ty::Ref(r, ty, mutbl) => { p!(write("&")); - if self.print_region_outputs_anything(r) { + if self.region_should_not_be_omitted(r) { p!(print(r), write(" ")); } p!(print(ty::TypeAndMut { ty, mutbl })) @@ -1030,7 +1028,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { nest!(|cx| cx.print_def_path(def.did, Some(substs), iter::empty())); } ty::Dynamic(data, r) => { - let print_r = self.print_region_outputs_anything(r); + let print_r = self.region_should_not_be_omitted(r); if print_r { p!(write("(")); } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 0fd53a9ecf9db..3597222dcbd0f 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -513,7 +513,7 @@ impl Printer for SymbolPath { } impl PrettyPrinter for SymbolPath { - fn print_region_outputs_anything( + fn region_should_not_be_omitted( self: &PrintCx<'_, '_, '_, Self>, _region: ty::Region<'_>, ) -> bool { diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr index fa7704cf17e3f..fd8f7674696c7 100644 --- a/src/test/ui/issues/issue-20831-debruijn.stderr +++ b/src/test/ui/issues/issue-20831-debruijn.stderr @@ -11,7 +11,7 @@ LL | | } | |_____^ lifetime mismatch | = note: expected type `'a` - found type `` + found type `'_` note: the anonymous lifetime #2 defined on the method body at 28:5... --> $DIR/issue-20831-debruijn.rs:28:5 | @@ -42,7 +42,7 @@ LL | | } | |_____^ lifetime mismatch | = note: expected type `'a` - found type `` + found type `'_` note: the lifetime 'a as defined on the impl at 26:6... --> $DIR/issue-20831-debruijn.rs:26:6 | diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.stderr index 97470aae54a0b..a4814debb360f 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let p: &'static mut usize = &mut self.food; //~ ERROR cannot infer | ^^^^^^^^^^^^^^ | -note: first, the lifetime cannot outlive the lifetime as defined on the body at 9:18... +note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 9:18... --> $DIR/regions-addr-of-upvar-self.rs:9:18 | LL | let _f = || { diff --git a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr index e4b14811d9075..4d35677d51bcb 100644 --- a/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr +++ b/src/test/ui/regions/regions-return-ref-to-upvar-issue-17403.stderr @@ -4,7 +4,7 @@ error[E0495]: cannot infer an appropriate lifetime for borrow expression due to LL | let mut f = || &mut x; //~ ERROR cannot infer | ^^^^^^ | -note: first, the lifetime cannot outlive the lifetime as defined on the body at 7:21... +note: first, the lifetime cannot outlive the lifetime '_ as defined on the body at 7:21... --> $DIR/regions-return-ref-to-upvar-issue-17403.rs:7:21 | LL | let mut f = || &mut x; //~ ERROR cannot infer From ac3c32cab59a75d8d6942360e49ea59090953ff4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 24 Jan 2019 19:52:43 +0200 Subject: [PATCH 59/68] rustc: make `pretty_path_generic_args`' task as simple as possible. --- src/librustc/infer/error_reporting/mod.rs | 5 +- src/librustc/ty/print/mod.rs | 17 +-- src/librustc/ty/print/pretty.rs | 118 +++++++++------------ src/librustc_codegen_utils/symbol_names.rs | 13 ++- src/librustdoc/clean/mod.rs | 5 +- 5 files changed, 70 insertions(+), 88 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4cc61d9721ca9..4d667a7456ab8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -447,7 +447,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { use hir::def_id::CrateNum; use ty::print::{PrintCx, Printer}; - use ty::subst::Substs; + use ty::subst::Kind; struct AbsolutePathPrinter; @@ -514,8 +514,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - _params: &[ty::GenericParamDef], - _substs: &'tcx Substs<'tcx>, + _args: impl Iterator> + Clone, _projections: impl Iterator>, ) -> Result { print_prefix(self) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 6137cde0e5224..916cdf06610d6 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -123,8 +123,7 @@ pub trait Printer: Sized { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - params: &[ty::GenericParamDef], - substs: &'tcx Substs<'tcx>, + args: impl Iterator> + Clone, projections: impl Iterator>, ) -> Result; } @@ -197,8 +196,8 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { }; if let (Some(generics), Some(substs)) = (generics, substs) { - let params = self.generic_params_to_print(generics, substs); - self.path_generic_args(print_path, params, substs, projections) + let args = self.generic_args_to_print(generics, substs); + self.path_generic_args(print_path, args, projections) } else { print_path(self) } @@ -206,11 +205,11 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { } } - pub fn generic_params_to_print( + pub fn generic_args_to_print( &self, - generics: &'a ty::Generics, + generics: &'tcx ty::Generics, substs: &'tcx Substs<'tcx>, - ) -> &'a [ty::GenericParamDef] { + ) -> impl Iterator> + Clone { // Don't print args for `Self` parameters (of traits). let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; @@ -226,7 +225,9 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { } } }).count(); - ¶ms[..params.len() - num_supplied_defaults] + params[..params.len() - num_supplied_defaults].iter().map(move |param| { + substs[param.index as usize] + }) } fn default_print_impl_path( diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 66cf38c5d2916..39b18d18e617c 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -208,21 +208,30 @@ pub trait PrettyPrinter: value.skip_binder().print(self) } + /// Print comma-separated elements. + fn comma_sep( + mut self: PrintCx<'_, '_, 'tcx, Self>, + mut elems: impl Iterator, + comma: &str, + ) -> Result + where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + { + if let Some(first) = elems.next() { + self = self.nest(|cx| first.print(cx))?; + for elem in elems { + self.write_str(comma)?; + self = self.nest(|cx| elem.print(cx))?; + } + } + self.ok() + } + /// Print `<...>` around what `f` prints. fn generic_delimiters<'gcx, 'tcx>( self: PrintCx<'_, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result; - /// Return `true` if the region should be printed in path generic args - /// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`. - fn always_print_region_in_paths( - self: &PrintCx<'_, '_, '_, Self>, - _region: ty::Region<'_>, - ) -> bool { - false - } - /// Return `true` if the region should be printed in /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`. /// This is typically the case for all non-`'_` regions. @@ -485,66 +494,25 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, P>, ) -> Result, - params: &[ty::GenericParamDef], - substs: &'tcx Substs<'tcx>, - projections: impl Iterator>, + mut args: impl Iterator>, + mut projections: impl Iterator>, ) -> Result { self = self.nest(print_prefix)?; - // Don't print `'_` if there's no printed region. - let print_regions = params.iter().any(|param| { - match substs[param.index as usize].unpack() { - UnpackedKind::Lifetime(r) => { - self.always_print_region_in_paths(r) || - self.region_should_not_be_omitted(r) - } - _ => false, - } - }); - let mut args = params.iter().map(|param| { - substs[param.index as usize] - }).filter(|arg| { - match arg.unpack() { - UnpackedKind::Lifetime(_) => print_regions, - _ => true, - } - }); let arg0 = args.next(); - - let mut projections = projections; let projection0 = projections.next(); - if arg0.is_none() && projection0.is_none() { return self.ok(); } + let args = arg0.into_iter().chain(args); + let projections = projection0.into_iter().chain(projections); self.generic_delimiters(|mut cx| { - define_scoped_cx!(cx); - - let mut empty = true; - let mut maybe_comma = |cx: &mut Self| { - if empty { - empty = false; - Ok(()) - } else { - write!(cx, ", ") - } - }; - - for arg in arg0.into_iter().chain(args) { - maybe_comma(&mut cx)?; - - p!(print(arg)); + cx = cx.nest(|cx| cx.comma_sep(args, ", "))?; + if arg0.is_some() && projection0.is_some() { + write!(cx, ", ")?; } - - for projection in projection0.into_iter().chain(projections) { - maybe_comma(&mut cx)?; - - p!(write("{}=", cx.tcx.associated_item(projection.item_def_id).ident), - print(projection.ty)); - } - - cx.ok() + cx.comma_sep(projections, ", ") }) } } @@ -624,8 +592,8 @@ impl Printer for FmtPrinter { })?; if visible_path_success { return if let (Some(generics), Some(substs)) = (generics, substs) { - let params = self.generic_params_to_print(generics, substs); - self.path_generic_args(|cx| cx.ok(), params, substs, projections) + let args = self.generic_args_to_print(generics, substs); + self.path_generic_args(|cx| cx.ok(), args, projections) } else { self.ok() }; @@ -742,11 +710,23 @@ impl Printer for FmtPrinter { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - params: &[ty::GenericParamDef], - substs: &'tcx Substs<'tcx>, + args: impl Iterator> + Clone, projections: impl Iterator>, ) -> Result { - self.pretty_path_generic_args(print_prefix, params, substs, projections) + // Don't print `'_` if there's no unerased regions. + let print_regions = args.clone().any(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + let args = args.filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + self.pretty_path_generic_args(print_prefix, args, projections) } } @@ -801,13 +781,6 @@ impl PrettyPrinter for FmtPrinter { Ok(inner) } - fn always_print_region_in_paths( - self: &PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> bool { - *region != ty::ReErased - } - fn region_should_not_be_omitted( self: &PrintCx<'_, '_, '_, Self>, region: ty::Region<'_>, @@ -1488,6 +1461,11 @@ define_print_and_forward_display! { } } + ty::ExistentialProjection<'tcx> { + let name = cx.tcx.associated_item(self.item_def_id).ident; + p!(write("{}=", name), print(self.ty)) + } + &'tcx ty::List> { p!(write("{{")); let mut tys = self.iter(); diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 3597222dcbd0f..0767841cb9f0d 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -94,7 +94,7 @@ use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; use rustc::ty::print::{PrettyPrinter, PrintCx, Printer}; use rustc::ty::query::Providers; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Kind, Substs, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::util::common::record_time; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -504,11 +504,16 @@ impl Printer for SymbolPath { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - params: &[ty::GenericParamDef], - substs: &'tcx Substs<'tcx>, + args: impl Iterator> + Clone, projections: impl Iterator>, ) -> Result { - self.pretty_path_generic_args(print_prefix, params, substs, projections) + let args = args.filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => false, + _ => true, + } + }); + self.pretty_path_generic_args(print_prefix, args, projections) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c8dd376992dee..06325d2138f15 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -20,7 +20,7 @@ use rustc::mir::interpret::GlobalId; use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc::ty::subst::Substs; +use rustc::ty::subst::{Kind, Substs}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; use rustc::ty::layout::VariantIdx; @@ -4124,8 +4124,7 @@ where F: Fn(DefId) -> Def { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - _params: &[ty::GenericParamDef], - _substs: &'tcx Substs<'tcx>, + _args: impl Iterator> + Clone, _projections: impl Iterator>, ) -> Result { print_prefix(self) From 6b42110e85b7b7fac66642da56e1c78eb1f508d6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 24 Jan 2019 20:47:02 +0200 Subject: [PATCH 60/68] rustc: don't thread existential projections through path_generic_args. --- src/librustc/infer/error_reporting/mod.rs | 15 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/print/mod.rs | 46 ++-- src/librustc/ty/print/pretty.rs | 268 ++++++++++++--------- src/librustc/ty/structural_impls.rs | 5 +- src/librustc_codegen_utils/symbol_names.rs | 54 ++++- src/librustdoc/clean/mod.rs | 15 +- 8 files changed, 251 insertions(+), 156 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4d667a7456ab8..b9082a906cc34 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -55,7 +55,7 @@ use hir; use hir::def_id::DefId; use hir::Node; use middle::region; -use std::{cmp, fmt, iter}; +use std::{cmp, fmt}; use syntax::ast::DUMMY_NODE_ID; use syntax_pos::{Pos, Span}; use traits::{ObligationCause, ObligationCauseCode}; @@ -459,6 +459,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Path = Vec; type Region = !; type Type = !; + type DynExistential = !; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -474,6 +475,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Err(NonTrivialPath) } + fn print_dyn_existential<'tcx>( + self: PrintCx<'_, '_, 'tcx, Self>, + _predicates: &'tcx ty::List>, + ) -> Result { + Err(NonTrivialPath) + } + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -514,8 +522,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - _args: impl Iterator> + Clone, - _projections: impl Iterator>, + _args: &[Kind<'tcx>], ) -> Result { print_prefix(self) } @@ -527,7 +534,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { PrintCx::new(self.tcx, AbsolutePathPrinter) - .print_def_path(def_id, None, iter::empty()) + .print_def_path(def_id, None) }; // We compare strings because DefPath can be different diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index facf1e2a22468..aa43e35e070a9 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2381,7 +2381,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let f = &mut *fmt; PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.print_def_path(variant_def.did, Some(substs), iter::empty())?; + cx.print_def_path(variant_def.did, Some(substs))?; Ok(()) })?; diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 16c244627fb2c..983b6e532d66e 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -177,7 +177,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with_tls_tcx(FmtPrinter::new(&mut *f, Namespace::ValueNS), |cx| { let substs = cx.tcx.lift(&self.substs).expect("could not lift for printing"); - cx.print_def_path(self.def_id(), Some(substs), iter::empty())?; + cx.print_def_path(self.def_id(), Some(substs))?; Ok(()) })?; diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 916cdf06610d6..0caf98bbdfd5b 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -5,7 +5,6 @@ use ty::subst::{Kind, Subst, Substs}; use rustc_data_structures::fx::FxHashSet; -use std::iter; use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. @@ -64,14 +63,14 @@ pub trait Printer: Sized { type Path; type Region; type Type; + type DynExistential; fn print_def_path( self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - projections: impl Iterator>, ) -> Result { - self.default_print_def_path(def_id, substs, projections) + self.default_print_def_path(def_id, substs) } fn print_impl_path( self: PrintCx<'_, '_, 'tcx, Self>, @@ -93,6 +92,11 @@ pub trait Printer: Sized { ty: Ty<'tcx>, ) -> Result; + fn print_dyn_existential( + self: PrintCx<'_, '_, 'tcx, Self>, + predicates: &'tcx ty::List>, + ) -> Result; + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -123,8 +127,7 @@ pub trait Printer: Sized { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - args: impl Iterator> + Clone, - projections: impl Iterator>, + args: &[Kind<'tcx>], ) -> Result; } @@ -133,7 +136,6 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { self, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - projections: impl Iterator>, ) -> Result { debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs); let key = self.tcx.def_key(def_id); @@ -175,10 +177,10 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { let trait_ref = ty::TraitRef::new(parent_def_id, substs); cx.path_qualified(trait_ref.self_ty(), Some(trait_ref)) } else { - cx.print_def_path(parent_def_id, substs, iter::empty()) + cx.print_def_path(parent_def_id, substs) } } else { - cx.print_def_path(parent_def_id, None, iter::empty()) + cx.print_def_path(parent_def_id, None) } }; let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| { @@ -197,7 +199,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { if let (Some(generics), Some(substs)) = (generics, substs) { let args = self.generic_args_to_print(generics, substs); - self.path_generic_args(print_path, args, projections) + self.path_generic_args(print_path, args) } else { print_path(self) } @@ -209,13 +211,16 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { &self, generics: &'tcx ty::Generics, substs: &'tcx Substs<'tcx>, - ) -> impl Iterator> + Clone { + ) -> &'tcx [Kind<'tcx>] { + let mut own_params = generics.parent_count..generics.count(); + // Don't print args for `Self` parameters (of traits). - let has_own_self = generics.has_self && generics.parent_count == 0; - let params = &generics.params[has_own_self as usize..]; + if generics.has_self && own_params.start == 0 { + own_params.start = 1; + } // Don't print args that are the defaults of their respective parameters. - let num_supplied_defaults = params.iter().rev().take_while(|param| { + own_params.end -= generics.params.iter().rev().take_while(|param| { match param.kind { ty::GenericParamDefKind::Lifetime => false, ty::GenericParamDefKind::Type { has_default, .. } => { @@ -225,9 +230,8 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { } } }).count(); - params[..params.len() - num_supplied_defaults].iter().map(move |param| { - substs[param.index as usize] - }) + + &substs[own_params] } fn default_print_impl_path( @@ -260,7 +264,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { // trait-type, then fallback to a format that identifies // the module more clearly. self.path_append_impl( - |cx| cx.print_def_path(parent_def_id, None, iter::empty()), + |cx| cx.print_def_path(parent_def_id, None), self_ty, impl_trait_ref, ) @@ -343,3 +347,11 @@ impl Print<'tcx, P> for Ty<'tcx> { cx.print_type(self) } } + +impl Print<'tcx, P> for &'tcx ty::List> { + type Output = P::DynExistential; + type Error = P::Error; + fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + cx.print_dyn_existential(self) + } +} diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 39b18d18e617c..fe554338e1b96 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -14,7 +14,6 @@ use syntax::symbol::InternedString; use std::cell::Cell; use std::fmt::{self, Write as _}; -use std::iter; use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. @@ -178,6 +177,7 @@ pub trait PrettyPrinter: Path = Self, Region = Self, Type = Self, + DynExistential = Self, > + fmt::Write { @@ -196,7 +196,7 @@ pub trait PrettyPrinter: def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ) -> Result { - self.print_def_path(def_id, substs, iter::empty()) + self.print_def_path(def_id, substs) } fn in_binder( @@ -212,14 +212,13 @@ pub trait PrettyPrinter: fn comma_sep( mut self: PrintCx<'_, '_, 'tcx, Self>, mut elems: impl Iterator, - comma: &str, ) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> { if let Some(first) = elems.next() { self = self.nest(|cx| first.print(cx))?; for elem in elems { - self.write_str(comma)?; + self.write_str(", ")?; self = self.nest(|cx| elem.print(cx))?; } } @@ -272,7 +271,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); let _ = PrintCx::new(self, FmtPrinter::new(&mut s, ns)) - .print_def_path(def_id, None, iter::empty()); + .print_def_path(def_id, None); s } } @@ -317,7 +316,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); return Ok((if !span.is_dummy() { - self.print_def_path(def_id, None, iter::empty())? + self.print_def_path(def_id, None)? } else { self.path_crate(cnum)? }, true)); @@ -488,33 +487,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { cx.ok() }) } - - pub fn pretty_path_generic_args( - mut self, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, P>, - ) -> Result, - mut args: impl Iterator>, - mut projections: impl Iterator>, - ) -> Result { - self = self.nest(print_prefix)?; - - let arg0 = args.next(); - let projection0 = projections.next(); - if arg0.is_none() && projection0.is_none() { - return self.ok(); - } - let args = arg0.into_iter().chain(args); - let projections = projection0.into_iter().chain(projections); - - self.generic_delimiters(|mut cx| { - cx = cx.nest(|cx| cx.comma_sep(args, ", "))?; - if arg0.is_some() && projection0.is_some() { - write!(cx, ", ")?; - } - cx.comma_sep(projections, ", ") - }) - } } // HACK(eddyb) boxed to avoid moving around a large struct by-value. @@ -573,12 +545,12 @@ impl Printer for FmtPrinter { type Path = Self; type Region = Self; type Type = Self; + type DynExistential = Self; fn print_def_path( mut self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - projections: impl Iterator>, ) -> Result { // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. @@ -593,7 +565,7 @@ impl Printer for FmtPrinter { if visible_path_success { return if let (Some(generics), Some(substs)) = (generics, substs) { let args = self.generic_args_to_print(generics, substs); - self.path_generic_args(|cx| cx.ok(), args, projections) + self.path_generic_args(|cx| cx.ok(), args) } else { self.ok() }; @@ -618,13 +590,13 @@ impl Printer for FmtPrinter { let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; let span = self.tcx.def_span(def_id); return self.path_append( - |cx| cx.print_def_path(parent_def_id, None, iter::empty()), + |cx| cx.print_def_path(parent_def_id, None), &format!("", span), ); } } - self.default_print_def_path(def_id, substs, projections) + self.default_print_def_path(def_id, substs) } fn print_region( @@ -641,6 +613,13 @@ impl Printer for FmtPrinter { self.pretty_print_type(ty) } + fn print_dyn_existential( + self: PrintCx<'_, '_, 'tcx, Self>, + predicates: &'tcx ty::List>, + ) -> Result { + self.pretty_print_dyn_existential(predicates) + } + fn path_crate( mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -706,27 +685,33 @@ impl Printer for FmtPrinter { Ok(path) } fn path_generic_args<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, + mut self: PrintCx<'_, 'gcx, 'tcx, Self>, print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - args: impl Iterator> + Clone, - projections: impl Iterator>, + args: &[Kind<'tcx>], ) -> Result { + self = self.nest(print_prefix)?; + // Don't print `'_` if there's no unerased regions. - let print_regions = args.clone().any(|arg| { + let print_regions = args.iter().any(|arg| { match arg.unpack() { UnpackedKind::Lifetime(r) => *r != ty::ReErased, _ => false, } }); - let args = args.filter(|arg| { + let args = args.iter().cloned().filter(|arg| { match arg.unpack() { UnpackedKind::Lifetime(_) => print_regions, _ => true, } }); - self.pretty_path_generic_args(print_prefix, args, projections) + + if args.clone().next().is_some() { + self.generic_delimiters(|cx| cx.comma_sep(args)) + } else { + self.ok() + } } } @@ -748,7 +733,7 @@ impl PrettyPrinter for FmtPrinter { substs: Option<&'tcx Substs<'tcx>>, ) -> Result { let was_in_value = std::mem::replace(&mut self.in_value, true); - let mut path = self.print_def_path(def_id, substs, iter::empty())?; + let mut path = self.print_def_path(def_id, substs)?; path.in_value = was_in_value; Ok(path) @@ -998,7 +983,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Adt(def, substs) => { - nest!(|cx| cx.print_def_path(def.did, Some(substs), iter::empty())); + nest!(|cx| cx.print_def_path(def.did, Some(substs))); } ty::Dynamic(data, r) => { let print_r = self.region_should_not_be_omitted(r); @@ -1011,7 +996,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Foreign(def_id) => { - nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); + nest!(|cx| cx.print_def_path(def_id, None)); } ty::Projection(ref data) => p!(print(data)), ty::UnnormalizedProjection(ref data) => { @@ -1174,6 +1159,105 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { self.ok() } + fn pretty_print_dyn_existential( + mut self, + predicates: &'tcx ty::List>, + ) -> Result { + define_scoped_cx!(self); + + // Generate the main trait ref, including associated types. + let mut first = true; + + if let Some(principal) = predicates.principal() { + nest!(|cx| cx.print_def_path(principal.def_id, None)); + + let mut resugared = false; + + // Special-case `Fn(...) -> ...` and resugar it. + let fn_trait_kind = self.tcx.lang_items().fn_trait_kind(principal.def_id); + if !self.tcx.sess.verbose() && fn_trait_kind.is_some() { + if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { + let mut projections = predicates.projection_bounds(); + if let (Some(proj), None) = (projections.next(), projections.next()) { + nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); + resugared = true; + } + } + } + + // HACK(eddyb) this duplicates `FmtPrinter`'s `path_generic_args`, + // in order to place the projections inside the `<...>`. + if !resugared { + // Use a type that can't appear in defaults of type parameters. + let dummy_self = self.tcx.mk_infer(ty::FreshTy(0)); + let principal = principal.with_self_ty(self.tcx, dummy_self); + + let args = self.generic_args_to_print( + self.tcx.generics_of(principal.def_id), + principal.substs, + ); + + // Don't print `'_` if there's no unerased regions. + let print_regions = args.iter().any(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + let mut args = args.iter().cloned().filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + let mut projections = predicates.projection_bounds(); + + let arg0 = args.next(); + let projection0 = projections.next(); + if arg0.is_some() || projection0.is_some() { + let args = arg0.into_iter().chain(args); + let projections = projection0.into_iter().chain(projections); + + nest!(|cx| cx.generic_delimiters(|mut cx| { + cx = cx.nest(|cx| cx.comma_sep(args))?; + if arg0.is_some() && projection0.is_some() { + write!(cx, ", ")?; + } + cx.comma_sep(projections) + })); + } + } + first = false; + } + + // Builtin bounds. + // FIXME(eddyb) avoid printing twice (needed to ensure + // that the auto traits are sorted *and* printed via cx). + let mut auto_traits: Vec<_> = predicates.auto_traits().map(|did| { + (self.tcx.def_path_str(did), did) + }).collect(); + + // The auto traits come ordered by `DefPathHash`. While + // `DefPathHash` is *stable* in the sense that it depends on + // neither the host nor the phase of the moon, it depends + // "pseudorandomly" on the compiler version and the target. + // + // To avoid that causing instabilities in compiletest + // output, sort the auto-traits alphabetically. + auto_traits.sort(); + + for (_, def_id) in auto_traits { + if !first { + p!(write(" + ")); + } + first = false; + + nest!(|cx| cx.print_def_path(def_id, None)); + } + + self.ok() + } + pub fn pretty_fn_sig( mut self, inputs: &[Ty<'tcx>], @@ -1389,6 +1473,7 @@ macro_rules! define_print_and_forward_display { forward_display_to_print!(ty::RegionKind); forward_display_to_print!(Ty<'tcx>); +forward_display_to_print!(&'tcx ty::List>); forward_display_to_print!( ty::Binder); define_print_and_forward_display! { @@ -1402,70 +1487,6 @@ define_print_and_forward_display! { define_print_and_forward_display! { (self, cx): - &'tcx ty::List> { - // Generate the main trait ref, including associated types. - let mut first = true; - - if let Some(principal) = self.principal() { - let mut resugared_principal = false; - - // Special-case `Fn(...) -> ...` and resugar it. - let fn_trait_kind = cx.tcx.lang_items().fn_trait_kind(principal.def_id); - if !cx.tcx.sess.verbose() && fn_trait_kind.is_some() { - if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { - let mut projections = self.projection_bounds(); - if let (Some(proj), None) = (projections.next(), projections.next()) { - nest!(|cx| cx.print_def_path(principal.def_id, None, iter::empty())); - nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); - resugared_principal = true; - } - } - } - - if !resugared_principal { - // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let principal = principal.with_self_ty(cx.tcx, dummy_self); - nest!(|cx| cx.print_def_path( - principal.def_id, - Some(principal.substs), - self.projection_bounds(), - )); - } - first = false; - } - - // Builtin bounds. - // FIXME(eddyb) avoid printing twice (needed to ensure - // that the auto traits are sorted *and* printed via cx). - let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { - (cx.tcx.def_path_str(did), did) - }).collect(); - - // The auto traits come ordered by `DefPathHash`. While - // `DefPathHash` is *stable* in the sense that it depends on - // neither the host nor the phase of the moon, it depends - // "pseudorandomly" on the compiler version and the target. - // - // To avoid that causing instabilities in compiletest - // output, sort the auto-traits alphabetically. - auto_traits.sort(); - - for (_, def_id) in auto_traits { - if !first { - p!(write(" + ")); - } - first = false; - - nest!(|cx| cx.print_def_path(def_id, None, iter::empty())); - } - } - - ty::ExistentialProjection<'tcx> { - let name = cx.tcx.associated_item(self.item_def_id).ident; - p!(write("{}=", name), print(self.ty)) - } - &'tcx ty::List> { p!(write("{{")); let mut tys = self.iter(); @@ -1484,14 +1505,27 @@ define_print_and_forward_display! { } ty::ExistentialTraitRef<'tcx> { + // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - - let trait_ref = *ty::Binder::bind(*self) - .with_self_ty(cx.tcx, dummy_self) - .skip_binder(); + let trait_ref = self.with_self_ty(cx.tcx, dummy_self); p!(print(trait_ref)) } + ty::ExistentialProjection<'tcx> { + let name = cx.tcx.associated_item(self.item_def_id).ident; + p!(write("{}=", name), print(self.ty)) + } + + ty::ExistentialPredicate<'tcx> { + match *self { + ty::ExistentialPredicate::Trait(x) => p!(print(x)), + ty::ExistentialPredicate::Projection(x) => p!(print(x)), + ty::ExistentialPredicate::AutoTrait(def_id) => { + nest!(|cx| cx.print_def_path(def_id, None)) + } + } + } + ty::FnSig<'tcx> { if self.unsafety == hir::Unsafety::Unsafe { p!(write("unsafe ")); @@ -1521,7 +1555,7 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs), iter::empty())); + nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs))); } ty::ParamTy { @@ -1541,7 +1575,7 @@ define_print_and_forward_display! { } ty::ProjectionTy<'tcx> { - nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs), iter::empty())); + nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs))); } ty::ClosureKind { @@ -1562,7 +1596,7 @@ define_print_and_forward_display! { ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("the trait `")); - nest!(|cx| cx.print_def_path(trait_def_id, None, iter::empty())); + nest!(|cx| cx.print_def_path(trait_def_id, None)); p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 94f01345fffb4..54c27485875e2 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -14,7 +14,6 @@ use smallvec::SmallVec; use mir::interpret; use std::fmt; -use std::iter; use std::rc::Rc; impl fmt::Debug for ty::GenericParamDef { @@ -34,7 +33,7 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.print_def_path(self.def_id, None, iter::empty())?; + cx.print_def_path(self.def_id, None)?; Ok(()) }) } @@ -43,7 +42,7 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.print_def_path(self.did, None, iter::empty())?; + cx.print_def_path(self.did, None)?; Ok(()) }) } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 0767841cb9f0d..eae786d04d95b 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -92,7 +92,7 @@ use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::print::{PrettyPrinter, PrintCx, Printer}; +use rustc::ty::print::{PrettyPrinter, PrintCx, Printer, Print}; use rustc::ty::query::Providers; use rustc::ty::subst::{Kind, Substs, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -104,7 +104,6 @@ use rustc_mir::monomorphize::Instance; use syntax_pos::symbol::Symbol; use std::fmt::{self, Write}; -use std::iter; use std::mem::{self, discriminant}; pub fn provide(providers: &mut Providers) { @@ -223,7 +222,7 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { PrintCx::new(tcx, SymbolPath::new()) - .print_def_path(def_id, None, iter::empty()) + .print_def_path(def_id, None) .unwrap() .into_interned() } @@ -410,6 +409,7 @@ impl Printer for SymbolPath { type Path = Self; type Region = Self; type Type = Self; + type DynExistential = Self; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -430,12 +430,27 @@ impl Printer for SymbolPath { ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, ty::ClosureSubsts { substs }) | ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { - self.print_def_path(def_id, Some(substs), iter::empty()) + self.print_def_path(def_id, Some(substs)) } _ => self.pretty_print_type(ty), } } + fn print_dyn_existential( + mut self: PrintCx<'_, '_, 'tcx, Self>, + predicates: &'tcx ty::List>, + ) -> Result { + let mut first = false; + for p in predicates { + if !first { + write!(self, "+")?; + } + first = false; + self = self.nest(|cx| p.print(cx))?; + } + self.ok() + } + fn path_crate( mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -500,20 +515,26 @@ impl Printer for SymbolPath { Ok(path) } fn path_generic_args<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, + mut self: PrintCx<'_, 'gcx, 'tcx, Self>, print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - args: impl Iterator> + Clone, - projections: impl Iterator>, + args: &[Kind<'tcx>], ) -> Result { - let args = args.filter(|arg| { + self = self.nest(print_prefix)?; + + let args = args.iter().cloned().filter(|arg| { match arg.unpack() { UnpackedKind::Lifetime(_) => false, _ => true, } }); - self.pretty_path_generic_args(print_prefix, args, projections) + + if args.clone().next().is_some() { + self.generic_delimiters(|cx| cx.comma_sep(args)) + } else { + self.ok() + } } } @@ -524,6 +545,21 @@ impl PrettyPrinter for SymbolPath { ) -> bool { false } + fn comma_sep( + mut self: PrintCx<'_, '_, 'tcx, Self>, + mut elems: impl Iterator, + ) -> Result + where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + { + if let Some(first) = elems.next() { + self = self.nest(|cx| first.print(cx))?; + for elem in elems { + self.write_str(",")?; + self = self.nest(|cx| elem.print(cx))?; + } + } + self.ok() + } fn generic_delimiters<'gcx, 'tcx>( mut self: PrintCx<'_, 'gcx, 'tcx, Self>, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 06325d2138f15..28d0d1e310be0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -39,7 +39,7 @@ use std::fmt; use std::hash::{Hash, Hasher}; use std::default::Default; use std::{mem, slice, vec}; -use std::iter::{self, FromIterator, once}; +use std::iter::{FromIterator, once}; use std::rc::Rc; use std::str::FromStr; use std::cell::RefCell; @@ -4055,6 +4055,7 @@ where F: Fn(DefId) -> Def { type Path = Vec; type Region = (); type Type = (); + type DynExistential = (); fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -4070,6 +4071,13 @@ where F: Fn(DefId) -> Def { Ok(()) } + fn print_dyn_existential<'tcx>( + self: PrintCx<'_, '_, 'tcx, Self>, + _predicates: &'tcx ty::List>, + ) -> Result { + Ok(()) + } + fn path_crate( self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, @@ -4124,15 +4132,14 @@ where F: Fn(DefId) -> Def { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - _args: impl Iterator> + Clone, - _projections: impl Iterator>, + _args: &[Kind<'tcx>], ) -> Result { print_prefix(self) } } let names = PrintCx::new(tcx, AbsolutePathPrinter) - .print_def_path(def_id, None, iter::empty()) + .print_def_path(def_id, None) .unwrap(); hir::Path { From 3fe1efd09a4148f1306624929425fc7fa86c2289 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 02:34:19 +0200 Subject: [PATCH 61/68] rustc: remove the ability for pretty-printers to override nesting. --- .../nice_region_error/placeholder_error.rs | 14 +- src/librustc/ty/print/pretty.rs | 121 ++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 8 +- 3 files changed, 68 insertions(+), 75 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index ed415d1268c65..cab7702cadfd2 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -8,7 +8,7 @@ use traits::{ObligationCause, ObligationCauseCode}; use ty; use ty::error::ExpectedFound; use ty::subst::Substs; -use ty::print::{Print, PrettyPrinter}; +use ty::print::Print; use util::common::ErrorReported; use std::fmt::Write; @@ -253,9 +253,11 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let _ = (|| { let mut cx = ty::print::PrintCx::new(self.tcx, printer); write!(cx, "`")?; - cx = cx.nest(|cx| expected_trait_ref.self_ty().print(cx))?; + cx = ty::print::PrintCx::new(self.tcx, + expected_trait_ref.self_ty().print(cx)?); write!(cx, "` must implement `")?; - cx = cx.nest(|cx| expected_trait_ref.print(cx))?; + cx = ty::print::PrintCx::new(self.tcx, + expected_trait_ref.print(cx)?); write!(cx, "`") })(); @@ -287,9 +289,11 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let _ = (|| { let mut cx = ty::print::PrintCx::new(self.tcx, printer); write!(cx, "but `")?; - cx = cx.nest(|cx| actual_trait_ref.self_ty().print(cx))?; + cx = ty::print::PrintCx::new(self.tcx, + actual_trait_ref.self_ty().print(cx)?); write!(cx, "` only implements `")?; - cx = cx.nest(|cx| actual_trait_ref.print(cx))?; + cx = ty::print::PrintCx::new(self.tcx, + actual_trait_ref.print(cx)?); write!(cx, "`") })(); diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index fe554338e1b96..e53ecfdad45bb 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -20,8 +20,8 @@ use std::ops::{Deref, DerefMut}; use super::*; macro_rules! nest { - ($closure:expr) => { - scoped_cx!() = scoped_cx!().nest($closure)? + ($e:expr) => { + scoped_cx!() = PrintCx::new(scoped_cx!().tcx, $e?) } } macro_rules! print_inner { @@ -29,7 +29,7 @@ macro_rules! print_inner { write!(scoped_cx!(), $($data),+)? }; ($kind:ident ($data:expr)) => { - nest!(|cx| $data.$kind(cx)) + nest!($data.$kind(scoped_cx!())) }; } macro_rules! p { @@ -181,15 +181,6 @@ pub trait PrettyPrinter: > + fmt::Write { - /// Enter a nested print context, for pretty-printing - /// nested components in some larger context. - fn nest<'a, 'gcx, 'tcx, E>( - self: PrintCx<'a, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result, E> { - Ok(PrintCx::new(self.tcx, f(self)?)) - } - /// Like `print_def_path` but for value paths. fn print_value_path( self: PrintCx<'_, '_, 'tcx, Self>, @@ -215,11 +206,13 @@ pub trait PrettyPrinter: ) -> Result where T: Print<'tcx, Self, Output = Self, Error = Self::Error> { + define_scoped_cx!(self); + if let Some(first) = elems.next() { - self = self.nest(|cx| first.print(cx))?; + nest!(first.print(self)); for elem in elems { self.write_str(", ")?; - self = self.nest(|cx| elem.print(cx))?; + nest!(elem.print(self)); } } self.ok() @@ -355,9 +348,9 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // the entire path will succeed or not. To support printers that do not // implement `PrettyPrinter`, a `Vec` or linked list on the stack would // need to be built, before starting to print anything. - let mut prefix_success = false; - nest!(|cx| { - let (path, success) = cx.try_print_visible_def_path(visible_parent)?; + let prefix_success; + nest!({ + let (path, success) = self.try_print_visible_def_path(visible_parent)?; prefix_success = success; Ok(path) }); @@ -473,7 +466,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - self = self.nest(print_prefix)?; + self = PrintCx::new(self.tcx, print_prefix(self)?); self.generic_delimiters(|mut cx| { define_scoped_cx!(cx); @@ -495,7 +488,7 @@ pub struct FmtPrinter(Box>); pub struct FmtPrinterData { fmt: F, - empty: bool, + empty_path: bool, in_value: bool, used_region_names: FxHashSet, @@ -522,7 +515,7 @@ impl FmtPrinter { pub fn new(fmt: F, ns: Namespace) -> Self { FmtPrinter(Box::new(FmtPrinterData { fmt, - empty: true, + empty_path: false, in_value: ns == Namespace::ValueNS, used_region_names: Default::default(), region_index: 0, @@ -534,7 +527,6 @@ impl FmtPrinter { impl fmt::Write for FmtPrinter { fn write_str(&mut self, s: &str) -> fmt::Result { - self.empty &= s.is_empty(); self.fmt.write_str(s) } } @@ -552,16 +544,18 @@ impl Printer for FmtPrinter { def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ) -> Result { + define_scoped_cx!(self); + // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. let generics = substs.map(|_| self.tcx.generics_of(def_id)); if generics.as_ref().and_then(|g| g.parent).is_none() { - let mut visible_path_success = false; - self = self.nest(|cx| { - let (path, success) = cx.try_print_visible_def_path(def_id)?; + let visible_path_success; + nest!({ + let (path, success) = self.try_print_visible_def_path(def_id)?; visible_path_success = success; Ok(path) - })?; + }); if visible_path_success { return if let (Some(generics), Some(substs)) = (generics, substs) { let args = self.generic_args_to_print(generics, substs); @@ -624,15 +618,18 @@ impl Printer for FmtPrinter { mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { + self.empty_path = true; if cnum == LOCAL_CRATE { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { write!(self, "{}", keywords::Crate.name())?; + self.empty_path = false; } } } else { write!(self, "{}", self.tcx.crate_name(cnum))?; + self.empty_path = false; } self.ok() } @@ -641,7 +638,9 @@ impl Printer for FmtPrinter { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - self.pretty_path_qualified(self_ty, trait_ref) + let mut path = self.pretty_path_qualified(self_ty, trait_ref)?; + path.empty_path = false; + Ok(path) } fn path_append_impl<'gcx, 'tcx>( @@ -652,17 +651,16 @@ impl Printer for FmtPrinter { self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { - self.pretty_path_append_impl(|cx| { + let mut path = self.pretty_path_append_impl(|cx| { let mut path = print_prefix(cx)?; - - // HACK(eddyb) this accounts for `generic_delimiters` - // printing `::<` instead of `<` if `in_value` is set. - if !path.empty && !path.in_value { + if !path.empty_path { write!(path, "::")?; } Ok(path) - }, self_ty, trait_ref) + }, self_ty, trait_ref)?; + path.empty_path = false; + Ok(path) } fn path_append<'gcx, 'tcx>( self: PrintCx<'_, 'gcx, 'tcx, Self>, @@ -676,10 +674,11 @@ impl Printer for FmtPrinter { // FIXME(eddyb) `text` should never be empty, but it // currently is for `extern { ... }` "foreign modules". if !text.is_empty() { - if !path.empty { + if !path.empty_path { write!(path, "::")?; } write!(path, "{}", text)?; + path.empty_path = false; } Ok(path) @@ -691,7 +690,9 @@ impl Printer for FmtPrinter { ) -> Result, args: &[Kind<'tcx>], ) -> Result { - self = self.nest(print_prefix)?; + define_scoped_cx!(self); + + nest!(print_prefix(self)); // Don't print `'_` if there's no unerased regions. let print_regions = args.iter().any(|arg| { @@ -708,6 +709,9 @@ impl Printer for FmtPrinter { }); if args.clone().next().is_some() { + if self.in_value { + write!(self, "::")?; + } self.generic_delimiters(|cx| cx.comma_sep(args)) } else { self.ok() @@ -716,17 +720,6 @@ impl Printer for FmtPrinter { } impl PrettyPrinter for FmtPrinter { - fn nest<'a, 'gcx, 'tcx, E>( - mut self: PrintCx<'a, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result, E> { - let tcx = self.tcx; - let was_empty = std::mem::replace(&mut self.empty, true); - let mut inner = f(self)?; - inner.empty &= was_empty; - Ok(PrintCx::new(tcx, inner)) - } - fn print_value_path( mut self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, @@ -752,11 +745,7 @@ impl PrettyPrinter for FmtPrinter { mut self: PrintCx<'_, 'gcx, 'tcx, Self>, f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, ) -> Result { - if !self.empty && self.in_value { - write!(self, "::<")?; - } else { - write!(self, "<")?; - } + write!(self, "<")?; let was_in_value = std::mem::replace(&mut self.in_value, false); let mut inner = f(self)?; @@ -960,7 +949,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ty::FnDef(def_id, substs) => { let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); p!(print(sig), write(" {{")); - nest!(|cx| cx.print_value_path(def_id, Some(substs))); + nest!(self.print_value_path(def_id, Some(substs))); p!(write("}}")) } ty::FnPtr(ref bare_fn) => { @@ -983,7 +972,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Adt(def, substs) => { - nest!(|cx| cx.print_def_path(def.did, Some(substs))); + nest!(self.print_def_path(def.did, Some(substs))); } ty::Dynamic(data, r) => { let print_r = self.region_should_not_be_omitted(r); @@ -996,7 +985,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Foreign(def_id) => { - nest!(|cx| cx.print_def_path(def_id, None)); + nest!(self.print_def_path(def_id, None)); } ty::Projection(ref data) => p!(print(data)), ty::UnnormalizedProjection(ref data) => { @@ -1097,7 +1086,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write(" "), print(witness), write("]")) }, ty::GeneratorWitness(types) => { - nest!(|cx| cx.in_binder(&types)) + nest!(self.in_binder(&types)) } ty::Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, self.tcx); @@ -1169,7 +1158,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let mut first = true; if let Some(principal) = predicates.principal() { - nest!(|cx| cx.print_def_path(principal.def_id, None)); + nest!(self.print_def_path(principal.def_id, None)); let mut resugared = false; @@ -1179,7 +1168,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - nest!(|cx| cx.pretty_fn_sig(args, false, proj.ty)); + nest!(self.pretty_fn_sig(args, false, proj.ty)); resugared = true; } } @@ -1218,8 +1207,8 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let args = arg0.into_iter().chain(args); let projections = projection0.into_iter().chain(projections); - nest!(|cx| cx.generic_delimiters(|mut cx| { - cx = cx.nest(|cx| cx.comma_sep(args))?; + nest!(self.generic_delimiters(|mut cx| { + cx = PrintCx::new(cx.tcx, cx.comma_sep(args)?); if arg0.is_some() && projection0.is_some() { write!(cx, ", ")?; } @@ -1252,7 +1241,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } first = false; - nest!(|cx| cx.print_def_path(def_id, None)); + nest!(self.print_def_path(def_id, None)); } self.ok() @@ -1521,7 +1510,7 @@ define_print_and_forward_display! { ty::ExistentialPredicate::Trait(x) => p!(print(x)), ty::ExistentialPredicate::Projection(x) => p!(print(x)), ty::ExistentialPredicate::AutoTrait(def_id) => { - nest!(|cx| cx.print_def_path(def_id, None)) + nest!(cx.print_def_path(def_id, None)) } } } @@ -1536,7 +1525,7 @@ define_print_and_forward_display! { } p!(write("fn")); - nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); + nest!(cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); } ty::InferTy { @@ -1555,7 +1544,7 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - nest!(|cx| cx.print_def_path(self.def_id, Some(self.substs))); + nest!(cx.print_def_path(self.def_id, Some(self.substs))); } ty::ParamTy { @@ -1575,7 +1564,7 @@ define_print_and_forward_display! { } ty::ProjectionTy<'tcx> { - nest!(|cx| cx.print_def_path(self.item_def_id, Some(self.substs))); + nest!(cx.print_def_path(self.item_def_id, Some(self.substs))); } ty::ClosureKind { @@ -1596,17 +1585,17 @@ define_print_and_forward_display! { ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("the trait `")); - nest!(|cx| cx.print_def_path(trait_def_id, None)); + nest!(cx.print_def_path(trait_def_id, None)); p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { p!(write("the closure `")); - nest!(|cx| cx.print_value_path(closure_def_id, None)); + nest!(cx.print_value_path(closure_def_id, None)); p!(write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { p!(write("the constant `")); - nest!(|cx| cx.print_value_path(def_id, Some(substs))); + nest!(cx.print_value_path(def_id, Some(substs))); p!(write("` can be evaluated")) } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index eae786d04d95b..2337d8f6ea407 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -446,7 +446,7 @@ impl Printer for SymbolPath { write!(self, "+")?; } first = false; - self = self.nest(|cx| p.print(cx))?; + self = PrintCx::new(self.tcx, p.print(self)?); } self.ok() } @@ -521,7 +521,7 @@ impl Printer for SymbolPath { ) -> Result, args: &[Kind<'tcx>], ) -> Result { - self = self.nest(print_prefix)?; + self = PrintCx::new(self.tcx, print_prefix(self)?); let args = args.iter().cloned().filter(|arg| { match arg.unpack() { @@ -552,10 +552,10 @@ impl PrettyPrinter for SymbolPath { where T: Print<'tcx, Self, Output = Self, Error = Self::Error> { if let Some(first) = elems.next() { - self = self.nest(|cx| first.print(cx))?; + self = PrintCx::new(self.tcx, first.print(self)?); for elem in elems { self.write_str(",")?; - self = self.nest(|cx| elem.print(cx))?; + self = PrintCx::new(self.tcx, elem.print(self)?); } } self.ok() From 87c38df7012a11ce87be2f821cdfd58c7a734e93 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 12:11:50 +0200 Subject: [PATCH 62/68] rustc: remove PrintCx from ty::Print and rely on printers carrying TyCtxt. --- src/librustc/infer/error_reporting/mod.rs | 54 +- .../infer/error_reporting/need_type_info.rs | 4 +- .../nice_region_error/placeholder_error.rs | 20 +- src/librustc/mir/mod.rs | 9 +- src/librustc/ty/instance.rs | 9 +- src/librustc/ty/print/mod.rs | 143 +- src/librustc/ty/print/pretty.rs | 1384 ++++++++--------- src/librustc/ty/structural_impls.rs | 30 +- src/librustc_codegen_utils/symbol_names.rs | 128 +- .../borrow_check/error_reporting.rs | 8 +- src/librustdoc/clean/mod.rs | 57 +- 11 files changed, 892 insertions(+), 954 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b9082a906cc34..5f339c8c3bb0c 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -446,14 +446,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sp: Span, ) { use hir::def_id::CrateNum; - use ty::print::{PrintCx, Printer}; + use ty::print::Printer; use ty::subst::Kind; - struct AbsolutePathPrinter; + struct AbsolutePathPrinter<'a, 'gcx, 'tcx> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + } struct NonTrivialPath; - impl Printer for AbsolutePathPrinter { + impl<'gcx, 'tcx> Printer<'gcx, 'tcx> for AbsolutePathPrinter<'_, 'gcx, 'tcx> { type Error = NonTrivialPath; type Path = Vec; @@ -461,67 +463,65 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Type = !; type DynExistential = !; + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { + self.tcx + } + fn print_region( - self: PrintCx<'_, '_, '_, Self>, + self, _region: ty::Region<'_>, ) -> Result { Err(NonTrivialPath) } - fn print_type<'tcx>( - self: PrintCx<'_, '_, 'tcx, Self>, + fn print_type( + self, _ty: Ty<'tcx>, ) -> Result { Err(NonTrivialPath) } - fn print_dyn_existential<'tcx>( - self: PrintCx<'_, '_, 'tcx, Self>, + fn print_dyn_existential( + self, _predicates: &'tcx ty::List>, ) -> Result { Err(NonTrivialPath) } fn path_crate( - self: PrintCx<'_, '_, '_, Self>, + self, cnum: CrateNum, ) -> Result { Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) } - fn path_qualified<'tcx>( - self: PrintCx<'_, '_, 'tcx, Self>, + fn path_qualified( + self, _self_ty: Ty<'tcx>, _trait_ref: Option>, ) -> Result { Err(NonTrivialPath) } - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - _print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append_impl( + self, + _print_prefix: impl FnOnce(Self) -> Result, _self_ty: Ty<'tcx>, _trait_ref: Option>, ) -> Result { Err(NonTrivialPath) } - fn path_append<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, text: &str, ) -> Result { let mut path = print_prefix(self)?; path.push(text.to_string()); Ok(path) } - fn path_generic_args<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_generic_args( + self, + print_prefix: impl FnOnce(Self) -> Result, _args: &[Kind<'tcx>], ) -> Result { print_prefix(self) @@ -533,7 +533,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // module we could have false positives if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { - PrintCx::new(self.tcx, AbsolutePathPrinter) + AbsolutePathPrinter { tcx: self.tcx } .print_def_path(def_id, None) }; diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 15863a044cd6c..7a178da5c0623 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -80,11 +80,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut s, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS); if let Some(highlight) = highlight { printer.region_highlight_mode = highlight; } - let _ = ty.print(ty::print::PrintCx::new(self.tcx, printer)); + let _ = ty.print(printer); s } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index cab7702cadfd2..e1ea6e7db875f 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -246,18 +246,16 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { { let mut note = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut note, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut note, Namespace::TypeNS); printer.region_highlight_mode.maybe_highlighting_region(sub_placeholder, has_sub); printer.region_highlight_mode.maybe_highlighting_region(sup_placeholder, has_sup); let _ = (|| { - let mut cx = ty::print::PrintCx::new(self.tcx, printer); + let mut cx = printer; write!(cx, "`")?; - cx = ty::print::PrintCx::new(self.tcx, - expected_trait_ref.self_ty().print(cx)?); + cx = expected_trait_ref.self_ty().print(cx)?; write!(cx, "` must implement `")?; - cx = ty::print::PrintCx::new(self.tcx, - expected_trait_ref.print(cx)?); + cx = expected_trait_ref.print(cx)?; write!(cx, "`") })(); @@ -283,17 +281,15 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { { let mut note = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut note, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut note, Namespace::TypeNS); printer.region_highlight_mode.maybe_highlighting_region(vid, has_vid); let _ = (|| { - let mut cx = ty::print::PrintCx::new(self.tcx, printer); + let mut cx = printer; write!(cx, "but `")?; - cx = ty::print::PrintCx::new(self.tcx, - actual_trait_ref.self_ty().print(cx)?); + cx = actual_trait_ref.self_ty().print(cx)?; write!(cx, "` only implements `")?; - cx = ty::print::PrintCx::new(self.tcx, - actual_trait_ref.print(cx)?); + cx = actual_trait_ref.print(cx)?; write!(cx, "`") })(); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index aa43e35e070a9..61dc52074268e 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -33,7 +33,7 @@ use ty::{ self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; -use ty::print::{FmtPrinter, Printer, PrintCx}; +use ty::print::{FmtPrinter, Printer}; pub use mir::interpret::AssertMessage; @@ -2379,9 +2379,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { let variant_def = &adt_def.variants[variant]; let f = &mut *fmt; - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::ValueNS), |cx| { - let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.print_def_path(variant_def.did, Some(substs))?; + ty::tls::with(|tcx| { + let substs = tcx.lift(&substs).expect("could not lift for printing"); + FmtPrinter::new(tcx, f, Namespace::ValueNS) + .print_def_path(variant_def.did, Some(substs))?; Ok(()) })?; diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 983b6e532d66e..40941a16ced4a 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -2,7 +2,7 @@ use hir::Unsafety; use hir::def::Namespace; use hir::def_id::DefId; use ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt}; -use ty::print::{FmtPrinter, Printer, PrintCx}; +use ty::print::{FmtPrinter, Printer}; use traits; use rustc_target::spec::abi::Abi; @@ -175,9 +175,10 @@ impl<'tcx> InstanceDef<'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(&mut *f, Namespace::ValueNS), |cx| { - let substs = cx.tcx.lift(&self.substs).expect("could not lift for printing"); - cx.print_def_path(self.def_id(), Some(substs))?; + ty::tls::with(|tcx| { + let substs = tcx.lift(&self.substs).expect("could not lift for printing"); + FmtPrinter::new(tcx, &mut *f, Namespace::ValueNS) + .print_def_path(self.def_id(), Some(substs))?; Ok(()) })?; diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 0caf98bbdfd5b..8eb90c75bac5c 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -5,59 +5,18 @@ use ty::subst::{Kind, Subst, Substs}; use rustc_data_structures::fx::FxHashSet; -use std::ops::{Deref, DerefMut}; - // `pretty` is a separate module only for organization. mod pretty; pub use self::pretty::*; -pub struct PrintCx<'a, 'gcx, 'tcx, P> { - pub tcx: TyCtxt<'a, 'gcx, 'tcx>, - inner: P, -} - -impl

Deref for PrintCx<'_, '_, '_, P> { - type Target = P; - fn deref(&self) -> &P { - &self.inner - } -} - -impl

DerefMut for PrintCx<'_, '_, '_, P> { - fn deref_mut(&mut self) -> &mut P { - &mut self.inner - } -} - -impl<'a, 'gcx, 'tcx, P> PrintCx<'a, 'gcx, 'tcx, P> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, inner: P) -> Self { - PrintCx { - tcx, - inner, - } - } - - pub fn with_tls_tcx(inner: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { - ty::tls::with(|tcx| f(PrintCx::new(tcx, inner))) - } - - pub fn into_inner(self) -> P { - self.inner - } - - pub fn ok(self) -> Result { - Ok(self.into_inner()) - } -} - -pub trait Print<'tcx, P> { +pub trait Print<'gcx, 'tcx, P> { type Output; type Error; - fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result; + fn print(&self, cx: P) -> Result; } -pub trait Printer: Sized { +pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { type Error; type Path; @@ -65,15 +24,17 @@ pub trait Printer: Sized { type Type; type DynExistential; + fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>; + fn print_def_path( - self: PrintCx<'_, '_, 'tcx, Self>, + self, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ) -> Result { self.default_print_def_path(def_id, substs) } fn print_impl_path( - self: PrintCx<'_, '_, 'tcx, Self>, + self, impl_def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, self_ty: Ty<'tcx>, @@ -83,62 +44,56 @@ pub trait Printer: Sized { } fn print_region( - self: PrintCx<'_, '_, '_, Self>, + self, region: ty::Region<'_>, ) -> Result; fn print_type( - self: PrintCx<'_, '_, 'tcx, Self>, + self, ty: Ty<'tcx>, ) -> Result; fn print_dyn_existential( - self: PrintCx<'_, '_, 'tcx, Self>, + self, predicates: &'tcx ty::List>, ) -> Result; fn path_crate( - self: PrintCx<'_, '_, '_, Self>, + self, cnum: CrateNum, ) -> Result; fn path_qualified( - self: PrintCx<'_, '_, 'tcx, Self>, + self, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result; - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append_impl( + self, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result; - fn path_append<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, text: &str, ) -> Result; - fn path_generic_args<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_generic_args( + self, + print_prefix: impl FnOnce(Self) -> Result, args: &[Kind<'tcx>], ) -> Result; -} -impl PrintCx<'_, 'gcx, 'tcx, P> { - pub fn default_print_def_path( + // Defaults (should not be overriden): + + fn default_print_def_path( self, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, - ) -> Result { + ) -> Result { debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs); - let key = self.tcx.def_key(def_id); + let key = self.tcx().def_key(def_id); debug!("default_print_def_path: key={:?}", key); match key.disambiguated_data.data { @@ -148,29 +103,29 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { } DefPathData::Impl => { - let mut self_ty = self.tcx.type_of(def_id); + let mut self_ty = self.tcx().type_of(def_id); if let Some(substs) = substs { - self_ty = self_ty.subst(self.tcx, substs); + self_ty = self_ty.subst(self.tcx(), substs); } - let mut impl_trait_ref = self.tcx.impl_trait_ref(def_id); + let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id); if let Some(substs) = substs { - impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); + impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs); } self.print_impl_path(def_id, substs, self_ty, impl_trait_ref) } _ => { - let generics = substs.map(|_| self.tcx.generics_of(def_id)); + let generics = substs.map(|_| self.tcx().generics_of(def_id)); let generics_parent = generics.as_ref().and_then(|g| g.parent); let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let print_parent_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| { + let print_parent_path = |cx: Self| { if let Some(generics_parent_def_id) = generics_parent { assert_eq!(parent_def_id, generics_parent_def_id); // FIXME(eddyb) try to move this into the parent's printing // logic, instead of doing it when printing the child. - let parent_generics = cx.tcx.generics_of(parent_def_id); + let parent_generics = cx.tcx().generics_of(parent_def_id); let parent_has_own_self = parent_generics.has_self && parent_generics.parent_count == 0; if let (Some(substs), true) = (substs, parent_has_own_self) { @@ -183,7 +138,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { cx.print_def_path(parent_def_id, None) } }; - let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| { + let print_path = |cx: Self| { match key.disambiguated_data.data { // Skip `::{{constructor}}` on tuple/unit structs. DefPathData::StructCtor => print_parent_path(cx), @@ -207,7 +162,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { } } - pub fn generic_args_to_print( + fn generic_args_to_print( &self, generics: &'tcx ty::Generics, substs: &'tcx Substs<'tcx>, @@ -225,7 +180,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { ty::GenericParamDefKind::Lifetime => false, ty::GenericParamDefKind::Type { has_default, .. } => { has_default && substs[param.index as usize] == Kind::from( - self.tcx.type_of(param.def_id).subst(self.tcx, substs) + self.tcx().type_of(param.def_id).subst(self.tcx(), substs) ) } } @@ -240,7 +195,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { _substs: Option<&'tcx Substs<'tcx>>, self_ty: Ty<'tcx>, impl_trait_ref: Option>, - ) -> Result { + ) -> Result { debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", impl_def_id, self_ty, impl_trait_ref); @@ -249,14 +204,14 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { // users may find it useful. Currently, we omit the parent if // the impl is either in the same module as the self-type or // as the trait. - let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); + let parent_def_id = self.tcx().parent(impl_def_id).unwrap(); let in_self_mod = match characteristic_def_id_of_type(self_ty) { None => false, - Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id), + Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id), }; let in_trait_mod = match impl_trait_ref { None => false, - Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), + Some(trait_ref) => self.tcx().parent(trait_ref.def_id) == Some(parent_def_id), }; if !in_self_mod && !in_trait_mod { @@ -324,34 +279,36 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } } -impl Print<'tcx, P> for ty::RegionKind { +impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::RegionKind { type Output = P::Region; type Error = P::Error; - fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print(&self, cx: P) -> Result { cx.print_region(self) } } -impl Print<'tcx, P> for ty::Region<'_> { +impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for ty::Region<'_> { type Output = P::Region; type Error = P::Error; - fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print(&self, cx: P) -> Result { cx.print_region(self) } } -impl Print<'tcx, P> for Ty<'tcx> { +impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for Ty<'tcx> { type Output = P::Type; type Error = P::Error; - fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print(&self, cx: P) -> Result { cx.print_type(self) } } -impl Print<'tcx, P> for &'tcx ty::List> { +impl<'gcx: 'tcx, 'tcx, P: Printer<'gcx, 'tcx>> Print<'gcx, 'tcx, P> + for &'tcx ty::List> +{ type Output = P::DynExistential; type Error = P::Error; - fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print(&self, cx: P) -> Result { cx.print_dyn_existential(self) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index e53ecfdad45bb..95d11020fcf11 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -19,17 +19,12 @@ use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. use super::*; -macro_rules! nest { - ($e:expr) => { - scoped_cx!() = PrintCx::new(scoped_cx!().tcx, $e?) - } -} macro_rules! print_inner { (write ($($data:expr),+)) => { write!(scoped_cx!(), $($data),+)? }; ($kind:ident ($data:expr)) => { - nest!($data.$kind(scoped_cx!())) + scoped_cx!() = $data.$kind(scoped_cx!())? }; } macro_rules! p { @@ -171,8 +166,8 @@ impl RegionHighlightMode { } /// Trait for printers that pretty-print using `fmt::Write` to the printer. -pub trait PrettyPrinter: - Printer< +pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: + Printer<'gcx, 'tcx, Error = fmt::Error, Path = Self, Region = Self, @@ -183,7 +178,7 @@ pub trait PrettyPrinter: { /// Like `print_def_path` but for value paths. fn print_value_path( - self: PrintCx<'_, '_, 'tcx, Self>, + self, def_id: DefId, substs: Option<&'tcx Substs<'tcx>>, ) -> Result { @@ -191,92 +186,54 @@ pub trait PrettyPrinter: } fn in_binder( - self: PrintCx<'_, '_, 'tcx, Self>, + self, value: &ty::Binder, ) -> Result - where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> + where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> { value.skip_binder().print(self) } /// Print comma-separated elements. fn comma_sep( - mut self: PrintCx<'_, '_, 'tcx, Self>, + mut self, mut elems: impl Iterator, ) -> Result - where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> { - define_scoped_cx!(self); - if let Some(first) = elems.next() { - nest!(first.print(self)); + self = first.print(self)?; for elem in elems { self.write_str(", ")?; - nest!(elem.print(self)); + self = elem.print(self)?; } } - self.ok() + Ok(self) } /// Print `<...>` around what `f` prints. - fn generic_delimiters<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + fn generic_delimiters( + self, + f: impl FnOnce(Self) -> Result, ) -> Result; /// Return `true` if the region should be printed in /// optional positions, e.g. `&'a T` or `dyn Tr + 'b`. /// This is typically the case for all non-`'_` regions. fn region_should_not_be_omitted( - self: &PrintCx<'_, '_, '_, Self>, + &self, region: ty::Region<'_>, ) -> bool; -} - -impl fmt::Write for PrintCx<'_, '_, '_, P> { - fn write_str(&mut self, s: &str) -> fmt::Result { - (**self).write_str(s) - } -} - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always - // (but also some things just print a `DefId` generally so maybe we need this?) - fn guess_def_namespace(self, def_id: DefId) -> Namespace { - match self.def_key(def_id).disambiguated_data.data { - DefPathData::ValueNs(..) | - DefPathData::EnumVariant(..) | - DefPathData::Field(..) | - DefPathData::AnonConst | - DefPathData::ClosureExpr | - DefPathData::StructCtor => Namespace::ValueNS, - - DefPathData::MacroDef(..) => Namespace::MacroNS, - - _ => Namespace::TypeNS, - } - } - /// Returns a string identifying this def-id. This string is - /// suitable for user output. - pub fn def_path_str(self, def_id: DefId) -> String { - let ns = self.guess_def_namespace(def_id); - debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); - let mut s = String::new(); - let _ = PrintCx::new(self, FmtPrinter::new(&mut s, ns)) - .print_def_path(def_id, None); - s - } -} + // Defaults (should not be overriden): -impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. fn try_print_visible_def_path( mut self, def_id: DefId, - ) -> Result<(P, bool), P::Error> { + ) -> Result<(Self, bool), Self::Error> { define_scoped_cx!(self); debug!("try_print_visible_def_path: def_id={:?}", def_id); @@ -300,7 +257,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // 2. for an extern inferred from a path or an indirect crate, // where there is no explicit `extern crate`, we just prepend // the crate name. - match *self.tcx.extern_crate(def_id) { + match *self.tcx().extern_crate(def_id) { Some(ExternCrate { src: ExternCrateSource::Extern(def_id), direct: true, @@ -322,12 +279,12 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } if def_id.is_local() { - return self.ok().map(|path| (path, false)); + return Ok((self, false)); } - let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); + let visible_parent_map = self.tcx().visible_parent_map(LOCAL_CRATE); - let mut cur_def_key = self.tcx.def_key(def_id); + let mut cur_def_key = self.tcx().def_key(def_id); debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); // For a UnitStruct or TupleStruct we want the name of its parent rather than . @@ -337,27 +294,22 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), }; - cur_def_key = self.tcx.def_key(parent); + cur_def_key = self.tcx().def_key(parent); } let visible_parent = match visible_parent_map.get(&def_id).cloned() { Some(parent) => parent, - None => return self.ok().map(|path| (path, false)), - }; - // HACK(eddyb) this uses `nest` to avoid knowing ahead of time whether - // the entire path will succeed or not. To support printers that do not - // implement `PrettyPrinter`, a `Vec` or linked list on the stack would - // need to be built, before starting to print anything. - let prefix_success; - nest!({ - let (path, success) = self.try_print_visible_def_path(visible_parent)?; - prefix_success = success; - Ok(path) - }); - if !prefix_success { - return self.ok().map(|path| (path, false)); + None => return Ok((self, false)), }; - let actual_parent = self.tcx.parent(def_id); + // HACK(eddyb) this bypasses `path_append`'s prefix printing to avoid + // knowing ahead of time whether the entire path will succeed or not. + // To support printers that do not implement `PrettyPrinter`, a `Vec` or + // linked list on the stack would need to be built, before any printing. + match self.try_print_visible_def_path(visible_parent)? { + (cx, false) => return Ok((cx, false)), + (cx, true) => self = cx, + } + let actual_parent = self.tcx().parent(def_id); debug!( "try_print_visible_def_path: visible_parent={:?} actual_parent={:?}", visible_parent, actual_parent, @@ -405,7 +357,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { visible_parent .and_then(|parent| { - self.tcx.item_children(parent) + self.tcx().item_children(parent) .iter() .find(|child| child.def.def_id() == cur_def) .map(|child| child.ident.as_str()) @@ -416,7 +368,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { // Re-exported `extern crate` (#43189). if let DefPathData::CrateRoot = data { - self.tcx.original_crate_name(def_id.krate).as_str() + self.tcx().original_crate_name(def_id.krate).as_str() } else { Symbol::intern("").as_str() } @@ -424,14 +376,14 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { }, }; debug!("try_print_visible_def_path: symbol={:?}", symbol); - Ok((self.path_append(|cx| cx.ok(), &symbol)?, true)) + Ok((self.path_append(Ok, &symbol)?, true)) } - pub fn pretty_path_qualified( + fn pretty_path_qualified( self, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { + ) -> Result { if trait_ref.is_none() { // Inherent impls. Try to print `Foo::bar` for an inherent // impl on `Foo`, but fallback to `::bar` if self-type is @@ -454,19 +406,17 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { if let Some(trait_ref) = trait_ref { p!(write(" as "), print(trait_ref)); } - cx.ok() + Ok(cx) }) } - pub fn pretty_path_append_impl( + fn pretty_path_append_impl( mut self, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, P>, - ) -> Result, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, - ) -> Result { - self = PrintCx::new(self.tcx, print_prefix(self)?); + ) -> Result { + self = print_prefix(self)?; self.generic_delimiters(|mut cx| { define_scoped_cx!(cx); @@ -477,502 +427,78 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(print(self_ty)); - cx.ok() + Ok(cx) }) } -} - -// HACK(eddyb) boxed to avoid moving around a large struct by-value. -pub struct FmtPrinter(Box>); - -pub struct FmtPrinterData { - fmt: F, - - empty_path: bool, - in_value: bool, - - used_region_names: FxHashSet, - region_index: usize, - binder_depth: usize, - - pub region_highlight_mode: RegionHighlightMode, -} - -impl Deref for FmtPrinter { - type Target = FmtPrinterData; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for FmtPrinter { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} - -impl FmtPrinter { - pub fn new(fmt: F, ns: Namespace) -> Self { - FmtPrinter(Box::new(FmtPrinterData { - fmt, - empty_path: false, - in_value: ns == Namespace::ValueNS, - used_region_names: Default::default(), - region_index: 0, - binder_depth: 0, - region_highlight_mode: RegionHighlightMode::default(), - })) - } -} - -impl fmt::Write for FmtPrinter { - fn write_str(&mut self, s: &str) -> fmt::Result { - self.fmt.write_str(s) - } -} -impl Printer for FmtPrinter { - type Error = fmt::Error; - - type Path = Self; - type Region = Self; - type Type = Self; - type DynExistential = Self; - - fn print_def_path( - mut self: PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - ) -> Result { + fn pretty_print_type( + mut self, + ty: Ty<'tcx>, + ) -> Result { define_scoped_cx!(self); - // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` - // both here and in `default_print_def_path`. - let generics = substs.map(|_| self.tcx.generics_of(def_id)); - if generics.as_ref().and_then(|g| g.parent).is_none() { - let visible_path_success; - nest!({ - let (path, success) = self.try_print_visible_def_path(def_id)?; - visible_path_success = success; - Ok(path) - }); - if visible_path_success { - return if let (Some(generics), Some(substs)) = (generics, substs) { - let args = self.generic_args_to_print(generics, substs); - self.path_generic_args(|cx| cx.ok(), args) - } else { - self.ok() - }; + match ty.sty { + ty::Bool => p!(write("bool")), + ty::Char => p!(write("char")), + ty::Int(t) => p!(write("{}", t.ty_to_string())), + ty::Uint(t) => p!(write("{}", t.ty_to_string())), + ty::Float(t) => p!(write("{}", t.ty_to_string())), + ty::RawPtr(ref tm) => { + p!(write("*{} ", match tm.mutbl { + hir::MutMutable => "mut", + hir::MutImmutable => "const", + })); + p!(print(tm.ty)) } - } - - let key = self.tcx.def_key(def_id); - if let DefPathData::Impl = key.disambiguated_data.data { - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = - !def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; - - if !use_types { - // If no type info is available, fall back to - // pretty printing some span information. This should - // only occur very early in the compiler pipeline. - let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let span = self.tcx.def_span(def_id); - return self.path_append( - |cx| cx.print_def_path(parent_def_id, None), - &format!("", span), - ); + ty::Ref(r, ty, mutbl) => { + p!(write("&")); + if self.region_should_not_be_omitted(r) { + p!(print(r), write(" ")); + } + p!(print(ty::TypeAndMut { ty, mutbl })) } - } - - self.default_print_def_path(def_id, substs) - } - - fn print_region( - self: PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> Result { - self.pretty_print_region(region) - } - - fn print_type( - self: PrintCx<'_, '_, 'tcx, Self>, - ty: Ty<'tcx>, - ) -> Result { - self.pretty_print_type(ty) - } - - fn print_dyn_existential( - self: PrintCx<'_, '_, 'tcx, Self>, - predicates: &'tcx ty::List>, - ) -> Result { - self.pretty_print_dyn_existential(predicates) - } - - fn path_crate( - mut self: PrintCx<'_, '_, '_, Self>, - cnum: CrateNum, - ) -> Result { - self.empty_path = true; - if cnum == LOCAL_CRATE { - if self.tcx.sess.rust_2018() { - // We add the `crate::` keyword on Rust 2018, only when desired. - if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - write!(self, "{}", keywords::Crate.name())?; - self.empty_path = false; + ty::Never => p!(write("!")), + ty::Tuple(ref tys) => { + p!(write("(")); + let mut tys = tys.iter(); + if let Some(&ty) = tys.next() { + p!(print(ty), write(",")); + if let Some(&ty) = tys.next() { + p!(write(" "), print(ty)); + for &ty in tys { + p!(write(", "), print(ty)); + } + } } + p!(write(")")) } - } else { - write!(self, "{}", self.tcx.crate_name(cnum))?; - self.empty_path = false; - } - self.ok() - } - fn path_qualified( - self: PrintCx<'_, '_, 'tcx, Self>, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - let mut path = self.pretty_path_qualified(self_ty, trait_ref)?; - path.empty_path = false; - Ok(path) - } - - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, - self_ty: Ty<'tcx>, - trait_ref: Option>, - ) -> Result { - let mut path = self.pretty_path_append_impl(|cx| { - let mut path = print_prefix(cx)?; - if !path.empty_path { - write!(path, "::")?; + ty::FnDef(def_id, substs) => { + let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); + p!(print(sig), write(" {{")); + self = self.print_value_path(def_id, Some(substs))?; + p!(write("}}")) } - - Ok(path) - }, self_ty, trait_ref)?; - path.empty_path = false; - Ok(path) - } - fn path_append<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, - text: &str, - ) -> Result { - let mut path = print_prefix(self)?; - - // FIXME(eddyb) `text` should never be empty, but it - // currently is for `extern { ... }` "foreign modules". - if !text.is_empty() { - if !path.empty_path { - write!(path, "::")?; + ty::FnPtr(ref bare_fn) => { + p!(print(bare_fn)) } - write!(path, "{}", text)?; - path.empty_path = false; - } - - Ok(path) - } - fn path_generic_args<'gcx, 'tcx>( - mut self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, - args: &[Kind<'tcx>], - ) -> Result { - define_scoped_cx!(self); - - nest!(print_prefix(self)); + ty::Infer(infer_ty) => p!(write("{}", infer_ty)), + ty::Error => p!(write("[type error]")), + ty::Param(ref param_ty) => p!(write("{}", param_ty)), + ty::Bound(debruijn, bound_ty) => { + match bound_ty.kind { + ty::BoundTyKind::Anon => { + if debruijn == ty::INNERMOST { + p!(write("^{}", bound_ty.var.index())) + } else { + p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) + } + } - // Don't print `'_` if there's no unerased regions. - let print_regions = args.iter().any(|arg| { - match arg.unpack() { - UnpackedKind::Lifetime(r) => *r != ty::ReErased, - _ => false, + ty::BoundTyKind::Param(p) => p!(write("{}", p)), + } } - }); - let args = args.iter().cloned().filter(|arg| { - match arg.unpack() { - UnpackedKind::Lifetime(_) => print_regions, - _ => true, - } - }); - - if args.clone().next().is_some() { - if self.in_value { - write!(self, "::")?; - } - self.generic_delimiters(|cx| cx.comma_sep(args)) - } else { - self.ok() - } - } -} - -impl PrettyPrinter for FmtPrinter { - fn print_value_path( - mut self: PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, - ) -> Result { - let was_in_value = std::mem::replace(&mut self.in_value, true); - let mut path = self.print_def_path(def_id, substs)?; - path.in_value = was_in_value; - - Ok(path) - } - - fn in_binder( - self: PrintCx<'_, '_, 'tcx, Self>, - value: &ty::Binder, - ) -> Result - where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> - { - self.pretty_in_binder(value) - } - - fn generic_delimiters<'gcx, 'tcx>( - mut self: PrintCx<'_, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, - ) -> Result { - write!(self, "<")?; - - let was_in_value = std::mem::replace(&mut self.in_value, false); - let mut inner = f(self)?; - inner.in_value = was_in_value; - - write!(inner, ">")?; - Ok(inner) - } - - fn region_should_not_be_omitted( - self: &PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> bool { - let highlight = self.region_highlight_mode; - if highlight.region_highlighted(region).is_some() { - return true; - } - - if self.tcx.sess.verbose() { - return true; - } - - let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; - - match *region { - ty::ReEarlyBound(ref data) => { - data.name != "" && data.name != "'_" - } - - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { - return true; - } - } - - if let Some((region, _)) = highlight.highlight_bound_region { - if br == region { - return true; - } - } - - false - } - - ty::ReScope(_) | - ty::ReVar(_) if identify_regions => true, - - ty::ReVar(_) | - ty::ReScope(_) | - ty::ReErased => false, - - ty::ReStatic | - ty::ReEmpty | - ty::ReClosureBound(_) => true, - } - } -} - -// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`. -impl FmtPrinter { - pub fn pretty_print_region( - mut self: PrintCx<'_, '_, '_, Self>, - region: ty::Region<'_>, - ) -> Result { - define_scoped_cx!(self); - - // Watch out for region highlights. - let highlight = self.region_highlight_mode; - if let Some(n) = highlight.region_highlighted(region) { - p!(write("'{}", n)); - return self.ok(); - } - - if self.tcx.sess.verbose() { - p!(write("{:?}", region)); - return self.ok(); - } - - let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; - - // These printouts are concise. They do not contain all the information - // the user might want to diagnose an error, but there is basically no way - // to fit that into a short string. Hence the recommendation to use - // `explain_region()` or `note_and_explain_region()`. - match *region { - ty::ReEarlyBound(ref data) => { - if data.name != "" { - p!(write("{}", data.name)); - return self.ok(); - } - } - ty::ReLateBound(_, br) | - ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | - ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { - if let ty::BrNamed(_, name) = br { - if name != "" && name != "'_" { - p!(write("{}", name)); - return self.ok(); - } - } - - if let Some((region, counter)) = highlight.highlight_bound_region { - if br == region { - p!(write("'{}", counter)); - return self.ok(); - } - } - } - ty::ReScope(scope) if identify_regions => { - match scope.data { - region::ScopeData::Node => - p!(write("'{}s", scope.item_local_id().as_usize())), - region::ScopeData::CallSite => - p!(write("'{}cs", scope.item_local_id().as_usize())), - region::ScopeData::Arguments => - p!(write("'{}as", scope.item_local_id().as_usize())), - region::ScopeData::Destruction => - p!(write("'{}ds", scope.item_local_id().as_usize())), - region::ScopeData::Remainder(first_statement_index) => p!(write( - "'{}_{}rs", - scope.item_local_id().as_usize(), - first_statement_index.index() - )), - } - return self.ok(); - } - ty::ReVar(region_vid) if identify_regions => { - p!(write("{:?}", region_vid)); - return self.ok(); - } - ty::ReVar(_) => {} - ty::ReScope(_) | - ty::ReErased => {} - ty::ReStatic => { - p!(write("'static")); - return self.ok(); - } - ty::ReEmpty => { - p!(write("'")); - return self.ok(); - } - - // The user should never encounter these in unsubstituted form. - ty::ReClosureBound(vid) => { - p!(write("{:?}", vid)); - return self.ok(); - } - } - - p!(write("'_")); - - self.ok() - } -} - -impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { - pub fn pretty_print_type( - mut self, - ty: Ty<'tcx>, - ) -> Result { - define_scoped_cx!(self); - - match ty.sty { - ty::Bool => p!(write("bool")), - ty::Char => p!(write("char")), - ty::Int(t) => p!(write("{}", t.ty_to_string())), - ty::Uint(t) => p!(write("{}", t.ty_to_string())), - ty::Float(t) => p!(write("{}", t.ty_to_string())), - ty::RawPtr(ref tm) => { - p!(write("*{} ", match tm.mutbl { - hir::MutMutable => "mut", - hir::MutImmutable => "const", - })); - p!(print(tm.ty)) - } - ty::Ref(r, ty, mutbl) => { - p!(write("&")); - if self.region_should_not_be_omitted(r) { - p!(print(r), write(" ")); - } - p!(print(ty::TypeAndMut { ty, mutbl })) - } - ty::Never => p!(write("!")), - ty::Tuple(ref tys) => { - p!(write("(")); - let mut tys = tys.iter(); - if let Some(&ty) = tys.next() { - p!(print(ty), write(",")); - if let Some(&ty) = tys.next() { - p!(write(" "), print(ty)); - for &ty in tys { - p!(write(", "), print(ty)); - } - } - } - p!(write(")")) - } - ty::FnDef(def_id, substs) => { - let sig = self.tcx.fn_sig(def_id).subst(self.tcx, substs); - p!(print(sig), write(" {{")); - nest!(self.print_value_path(def_id, Some(substs))); - p!(write("}}")) - } - ty::FnPtr(ref bare_fn) => { - p!(print(bare_fn)) - } - ty::Infer(infer_ty) => p!(write("{}", infer_ty)), - ty::Error => p!(write("[type error]")), - ty::Param(ref param_ty) => p!(write("{}", param_ty)), - ty::Bound(debruijn, bound_ty) => { - match bound_ty.kind { - ty::BoundTyKind::Anon => { - if debruijn == ty::INNERMOST { - p!(write("^{}", bound_ty.var.index())) - } else { - p!(write("^{}_{}", debruijn.index(), bound_ty.var.index())) - } - } - - ty::BoundTyKind::Param(p) => p!(write("{}", p)), - } - } - ty::Adt(def, substs) => { - nest!(self.print_def_path(def.did, Some(substs))); + ty::Adt(def, substs) => { + self = self.print_def_path(def.did, Some(substs))?; } ty::Dynamic(data, r) => { let print_r = self.region_should_not_be_omitted(r); @@ -985,7 +511,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } ty::Foreign(def_id) => { - nest!(self.print_def_path(def_id, None)); + self = self.print_def_path(def_id, None)?; } ty::Projection(ref data) => p!(print(data)), ty::UnnormalizedProjection(ref data) => { @@ -996,12 +522,12 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } ty::Opaque(def_id, substs) => { // FIXME(eddyb) print this with `print_def_path`. - if self.tcx.sess.verbose() { + if self.tcx().sess.verbose() { p!(write("Opaque({:?}, {:?})", def_id, substs)); - return self.ok(); + return Ok(self); } - let def_key = self.tcx.def_key(def_id); + let def_key = self.tcx().def_key(def_id); if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { p!(write("{}", name)); let mut substs = substs.iter(); @@ -1014,11 +540,11 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(write(">")); } - return self.ok(); + return Ok(self); } // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, // by looking up the projections associated with the def_id. - let bounds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); + let bounds = self.tcx().predicates_of(def_id).instantiate(self.tcx(), substs); let mut first = true; let mut is_sized = false; @@ -1026,7 +552,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. - if Some(trait_ref.def_id()) == self.tcx.lang_items().sized_trait() { + if Some(trait_ref.def_id()) == self.tcx().lang_items().sized_trait() { is_sized = true; continue; } @@ -1045,8 +571,8 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } ty::Str => p!(write("str")), ty::Generator(did, substs, movability) => { - let upvar_tys = substs.upvar_tys(did, self.tcx); - let witness = substs.witness(did, self.tcx); + let upvar_tys = substs.upvar_tys(did, self.tcx()); + let witness = substs.witness(did, self.tcx()); if movability == hir::GeneratorMovability::Movable { p!(write("[generator")); } else { @@ -1054,10 +580,10 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } // FIXME(eddyb) should use `def_span`. - if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { - p!(write("@{:?}", self.tcx.hir().span(node_id))); + if let Some(node_id) = self.tcx().hir().as_local_node_id(did) { + p!(write("@{:?}", self.tcx().hir().span(node_id))); let mut sep = " "; - for (freevar, upvar_ty) in self.tcx.freevars(did) + for (freevar, upvar_ty) in self.tcx().freevars(did) .as_ref() .map_or(&[][..], |fv| &fv[..]) .iter() @@ -1066,7 +592,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!( write("{}{}:", sep, - self.tcx.hir().name(freevar.var_id())), + self.tcx().hir().name(freevar.var_id())), print(upvar_ty)); sep = ", "; } @@ -1086,21 +612,21 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write(" "), print(witness), write("]")) }, ty::GeneratorWitness(types) => { - nest!(self.in_binder(&types)) + self = self.in_binder(&types)?; } ty::Closure(did, substs) => { - let upvar_tys = substs.upvar_tys(did, self.tcx); + let upvar_tys = substs.upvar_tys(did, self.tcx()); p!(write("[closure")); // FIXME(eddyb) should use `def_span`. - if let Some(node_id) = self.tcx.hir().as_local_node_id(did) { - if self.tcx.sess.opts.debugging_opts.span_free_formats { + if let Some(node_id) = self.tcx().hir().as_local_node_id(did) { + if self.tcx().sess.opts.debugging_opts.span_free_formats { p!(write("@{:?}", node_id)); } else { - p!(write("@{:?}", self.tcx.hir().span(node_id))); + p!(write("@{:?}", self.tcx().hir().span(node_id))); } let mut sep = " "; - for (freevar, upvar_ty) in self.tcx.freevars(did) + for (freevar, upvar_ty) in self.tcx().freevars(did) .as_ref() .map_or(&[][..], |fv| &fv[..]) .iter() @@ -1109,7 +635,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!( write("{}{}:", sep, - self.tcx.hir().name(freevar.var_id())), + self.tcx().hir().name(freevar.var_id())), print(upvar_ty)); sep = ", "; } @@ -1135,7 +661,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write("_")); } ty::LazyConst::Evaluated(c) => { - p!(write("{}", c.unwrap_usize(self.tcx))); + p!(write("{}", c.unwrap_usize(self.tcx()))); } } p!(write("]")) @@ -1145,30 +671,30 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - self.ok() + Ok(self) } fn pretty_print_dyn_existential( mut self, predicates: &'tcx ty::List>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); // Generate the main trait ref, including associated types. let mut first = true; if let Some(principal) = predicates.principal() { - nest!(self.print_def_path(principal.def_id, None)); + self = self.print_def_path(principal.def_id, None)?; let mut resugared = false; // Special-case `Fn(...) -> ...` and resugar it. - let fn_trait_kind = self.tcx.lang_items().fn_trait_kind(principal.def_id); - if !self.tcx.sess.verbose() && fn_trait_kind.is_some() { + let fn_trait_kind = self.tcx().lang_items().fn_trait_kind(principal.def_id); + if !self.tcx().sess.verbose() && fn_trait_kind.is_some() { if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - nest!(self.pretty_fn_sig(args, false, proj.ty)); + self = self.pretty_fn_sig(args, false, proj.ty)?; resugared = true; } } @@ -1178,11 +704,11 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // in order to place the projections inside the `<...>`. if !resugared { // Use a type that can't appear in defaults of type parameters. - let dummy_self = self.tcx.mk_infer(ty::FreshTy(0)); - let principal = principal.with_self_ty(self.tcx, dummy_self); + let dummy_self = self.tcx().mk_infer(ty::FreshTy(0)); + let principal = principal.with_self_ty(self.tcx(), dummy_self); let args = self.generic_args_to_print( - self.tcx.generics_of(principal.def_id), + self.tcx().generics_of(principal.def_id), principal.substs, ); @@ -1207,13 +733,13 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { let args = arg0.into_iter().chain(args); let projections = projection0.into_iter().chain(projections); - nest!(self.generic_delimiters(|mut cx| { - cx = PrintCx::new(cx.tcx, cx.comma_sep(args)?); + self = self.generic_delimiters(|mut cx| { + cx = cx.comma_sep(args)?; if arg0.is_some() && projection0.is_some() { write!(cx, ", ")?; } cx.comma_sep(projections) - })); + })?; } } first = false; @@ -1223,7 +749,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // FIXME(eddyb) avoid printing twice (needed to ensure // that the auto traits are sorted *and* printed via cx). let mut auto_traits: Vec<_> = predicates.auto_traits().map(|did| { - (self.tcx.def_path_str(did), did) + (self.tcx().def_path_str(did), did) }).collect(); // The auto traits come ordered by `DefPathHash`. While @@ -1241,18 +767,18 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } first = false; - nest!(self.print_def_path(def_id, None)); + self = self.print_def_path(def_id, None)?; } - self.ok() + Ok(self) } - pub fn pretty_fn_sig( + fn pretty_fn_sig( mut self, inputs: &[Ty<'tcx>], variadic: bool, output: Ty<'tcx>, - ) -> Result { + ) -> Result { define_scoped_cx!(self); p!(write("(")); @@ -1271,30 +797,475 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { p!(write(" -> "), print(output)); } - self.ok() + Ok(self) } } -// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, -// `region_index` and `used_region_names`. -impl FmtPrinter { - pub fn pretty_in_binder( - mut self: PrintCx<'_, '_, 'tcx, Self>, - value: &ty::Binder, - ) -> Result - where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx> - { - fn name_by_region_index(index: usize) -> InternedString { - match index { - 0 => Symbol::intern("'r"), - 1 => Symbol::intern("'s"), - i => Symbol::intern(&format!("'t{}", i-2)), - }.as_interned_str() - } +// HACK(eddyb) boxed to avoid moving around a large struct by-value. +pub struct FmtPrinter<'a, 'gcx, 'tcx, F>(Box>); - // Replace any anonymous late-bound regions with named - // variants, using gensym'd identifiers, so that we can - // clearly differentiate between named and unnamed regions in +pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + fmt: F, + + empty_path: bool, + in_value: bool, + + used_region_names: FxHashSet, + region_index: usize, + binder_depth: usize, + + pub region_highlight_mode: RegionHighlightMode, +} + +impl Deref for FmtPrinter<'a, 'gcx, 'tcx, F> { + type Target = FmtPrinterData<'a, 'gcx, 'tcx, F>; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for FmtPrinter<'_, '_, '_, F> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl FmtPrinter<'a, 'gcx, 'tcx, F> { + pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, fmt: F, ns: Namespace) -> Self { + FmtPrinter(Box::new(FmtPrinterData { + tcx, + fmt, + empty_path: false, + in_value: ns == Namespace::ValueNS, + used_region_names: Default::default(), + region_index: 0, + binder_depth: 0, + region_highlight_mode: RegionHighlightMode::default(), + })) + } +} + +impl TyCtxt<'_, '_, '_> { + // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always + // (but also some things just print a `DefId` generally so maybe we need this?) + fn guess_def_namespace(self, def_id: DefId) -> Namespace { + match self.def_key(def_id).disambiguated_data.data { + DefPathData::ValueNs(..) | + DefPathData::EnumVariant(..) | + DefPathData::Field(..) | + DefPathData::AnonConst | + DefPathData::ClosureExpr | + DefPathData::StructCtor => Namespace::ValueNS, + + DefPathData::MacroDef(..) => Namespace::MacroNS, + + _ => Namespace::TypeNS, + } + } + + /// Returns a string identifying this def-id. This string is + /// suitable for user output. + pub fn def_path_str(self, def_id: DefId) -> String { + let ns = self.guess_def_namespace(def_id); + debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); + let mut s = String::new(); + let _ = FmtPrinter::new(self, &mut s, ns) + .print_def_path(def_id, None); + s + } +} + +impl fmt::Write for FmtPrinter<'_, '_, '_, F> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.fmt.write_str(s) + } +} + +impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { + type Error = fmt::Error; + + type Path = Self; + type Region = Self; + type Type = Self; + type DynExistential = Self; + + fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { + self.tcx + } + + fn print_def_path( + mut self, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + ) -> Result { + define_scoped_cx!(self); + + // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` + // both here and in `default_print_def_path`. + let generics = substs.map(|_| self.tcx.generics_of(def_id)); + if generics.as_ref().and_then(|g| g.parent).is_none() { + match self.try_print_visible_def_path(def_id)? { + (cx, true) => return if let (Some(generics), Some(substs)) = (generics, substs) { + let args = cx.generic_args_to_print(generics, substs); + cx.path_generic_args(Ok, args) + } else { + Ok(cx) + }, + (cx, false) => self = cx, + } + } + + let key = self.tcx.def_key(def_id); + if let DefPathData::Impl = key.disambiguated_data.data { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = + !def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; + + if !use_types { + // If no type info is available, fall back to + // pretty printing some span information. This should + // only occur very early in the compiler pipeline. + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let span = self.tcx.def_span(def_id); + return self.path_append( + |cx| cx.print_def_path(parent_def_id, None), + &format!("", span), + ); + } + } + + self.default_print_def_path(def_id, substs) + } + + fn print_region( + self, + region: ty::Region<'_>, + ) -> Result { + self.pretty_print_region(region) + } + + fn print_type( + self, + ty: Ty<'tcx>, + ) -> Result { + self.pretty_print_type(ty) + } + + fn print_dyn_existential( + self, + predicates: &'tcx ty::List>, + ) -> Result { + self.pretty_print_dyn_existential(predicates) + } + + fn path_crate( + mut self, + cnum: CrateNum, + ) -> Result { + self.empty_path = true; + if cnum == LOCAL_CRATE { + if self.tcx.sess.rust_2018() { + // We add the `crate::` keyword on Rust 2018, only when desired. + if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + write!(self, "{}", keywords::Crate.name())?; + self.empty_path = false; + } + } + } else { + write!(self, "{}", self.tcx.crate_name(cnum))?; + self.empty_path = false; + } + Ok(self) + } + fn path_qualified( + mut self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self = self.pretty_path_qualified(self_ty, trait_ref)?; + self.empty_path = false; + Ok(self) + } + + fn path_append_impl( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self = self.pretty_path_append_impl(|mut cx| { + cx = print_prefix(cx)?; + if !cx.empty_path { + write!(cx, "::")?; + } + + Ok(cx) + }, self_ty, trait_ref)?; + self.empty_path = false; + Ok(self) + } + fn path_append( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + text: &str, + ) -> Result { + self = print_prefix(self)?; + + // FIXME(eddyb) `text` should never be empty, but it + // currently is for `extern { ... }` "foreign modules". + if !text.is_empty() { + if !self.empty_path { + write!(self, "::")?; + } + write!(self, "{}", text)?; + self.empty_path = false; + } + + Ok(self) + } + fn path_generic_args( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + args: &[Kind<'tcx>], + ) -> Result { + self = print_prefix(self)?; + + // Don't print `'_` if there's no unerased regions. + let print_regions = args.iter().any(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + let args = args.iter().cloned().filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + + if args.clone().next().is_some() { + if self.in_value { + write!(self, "::")?; + } + self.generic_delimiters(|cx| cx.comma_sep(args)) + } else { + Ok(self) + } + } +} + +impl PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { + fn print_value_path( + mut self, + def_id: DefId, + substs: Option<&'tcx Substs<'tcx>>, + ) -> Result { + let was_in_value = std::mem::replace(&mut self.in_value, true); + self = self.print_def_path(def_id, substs)?; + self.in_value = was_in_value; + + Ok(self) + } + + fn in_binder( + self, + value: &ty::Binder, + ) -> Result + where T: Print<'gcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> + { + self.pretty_in_binder(value) + } + + fn generic_delimiters( + mut self, + f: impl FnOnce(Self) -> Result, + ) -> Result { + write!(self, "<")?; + + let was_in_value = std::mem::replace(&mut self.in_value, false); + let mut inner = f(self)?; + inner.in_value = was_in_value; + + write!(inner, ">")?; + Ok(inner) + } + + fn region_should_not_be_omitted( + &self, + region: ty::Region<'_>, + ) -> bool { + let highlight = self.region_highlight_mode; + if highlight.region_highlighted(region).is_some() { + return true; + } + + if self.tcx.sess.verbose() { + return true; + } + + let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; + + match *region { + ty::ReEarlyBound(ref data) => { + data.name != "" && data.name != "'_" + } + + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + return true; + } + } + + if let Some((region, _)) = highlight.highlight_bound_region { + if br == region { + return true; + } + } + + false + } + + ty::ReScope(_) | + ty::ReVar(_) if identify_regions => true, + + ty::ReVar(_) | + ty::ReScope(_) | + ty::ReErased => false, + + ty::ReStatic | + ty::ReEmpty | + ty::ReClosureBound(_) => true, + } + } +} + +// HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`. +impl FmtPrinter<'_, '_, '_, F> { + pub fn pretty_print_region( + mut self, + region: ty::Region<'_>, + ) -> Result { + define_scoped_cx!(self); + + // Watch out for region highlights. + let highlight = self.region_highlight_mode; + if let Some(n) = highlight.region_highlighted(region) { + p!(write("'{}", n)); + return Ok(self); + } + + if self.tcx.sess.verbose() { + p!(write("{:?}", region)); + return Ok(self); + } + + let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; + + // These printouts are concise. They do not contain all the information + // the user might want to diagnose an error, but there is basically no way + // to fit that into a short string. Hence the recommendation to use + // `explain_region()` or `note_and_explain_region()`. + match *region { + ty::ReEarlyBound(ref data) => { + if data.name != "" { + p!(write("{}", data.name)); + return Ok(self); + } + } + ty::ReLateBound(_, br) | + ty::ReFree(ty::FreeRegion { bound_region: br, .. }) | + ty::RePlaceholder(ty::Placeholder { name: br, .. }) => { + if let ty::BrNamed(_, name) = br { + if name != "" && name != "'_" { + p!(write("{}", name)); + return Ok(self); + } + } + + if let Some((region, counter)) = highlight.highlight_bound_region { + if br == region { + p!(write("'{}", counter)); + return Ok(self); + } + } + } + ty::ReScope(scope) if identify_regions => { + match scope.data { + region::ScopeData::Node => + p!(write("'{}s", scope.item_local_id().as_usize())), + region::ScopeData::CallSite => + p!(write("'{}cs", scope.item_local_id().as_usize())), + region::ScopeData::Arguments => + p!(write("'{}as", scope.item_local_id().as_usize())), + region::ScopeData::Destruction => + p!(write("'{}ds", scope.item_local_id().as_usize())), + region::ScopeData::Remainder(first_statement_index) => p!(write( + "'{}_{}rs", + scope.item_local_id().as_usize(), + first_statement_index.index() + )), + } + return Ok(self); + } + ty::ReVar(region_vid) if identify_regions => { + p!(write("{:?}", region_vid)); + return Ok(self); + } + ty::ReVar(_) => {} + ty::ReScope(_) | + ty::ReErased => {} + ty::ReStatic => { + p!(write("'static")); + return Ok(self); + } + ty::ReEmpty => { + p!(write("'")); + return Ok(self); + } + + // The user should never encounter these in unsubstituted form. + ty::ReClosureBound(vid) => { + p!(write("{:?}", vid)); + return Ok(self); + } + } + + p!(write("'_")); + + Ok(self) + } +} + +// HACK(eddyb) limited to `FmtPrinter` because of `binder_depth`, +// `region_index` and `used_region_names`. +impl FmtPrinter<'_, 'gcx, 'tcx, F> { + pub fn pretty_in_binder( + mut self, + value: &ty::Binder, + ) -> Result + where T: Print<'gcx, 'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx> + { + fn name_by_region_index(index: usize) -> InternedString { + match index { + 0 => Symbol::intern("'r"), + 1 => Symbol::intern("'s"), + i => Symbol::intern(&format!("'t{}", i-2)), + }.as_interned_str() + } + + // Replace any anonymous late-bound regions with named + // variants, using gensym'd 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 { @@ -1372,107 +1343,94 @@ impl FmtPrinter { } } -impl Print<'tcx, P> for ty::Binder - where T: Print<'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx> +impl<'gcx: 'tcx, 'tcx, T, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P> + for ty::Binder + where T: Print<'gcx, 'tcx, P, Output = P, Error = P::Error> + TypeFoldable<'tcx> { type Output = P; type Error = P::Error; - fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print(&self, cx: P) -> Result { cx.in_binder(self) } } -pub trait LiftAndPrintToFmt<'tcx> { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result; -} - -impl LiftAndPrintToFmt<'tcx> for T - where T: ty::Lift<'tcx>, - for<'a, 'b> >::Lifted: - Print<'tcx, FmtPrinter<&'a mut fmt::Formatter<'b>>, Error = fmt::Error> +impl<'gcx: 'tcx, 'tcx, T, U, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P> + for ty::OutlivesPredicate + where T: Print<'gcx, 'tcx, P, Output = P, Error = P::Error>, + U: Print<'gcx, 'tcx, P, Output = P, Error = P::Error>, { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - tcx.lift(self) - .expect("could not lift for printing") - .print(PrintCx::new(tcx, FmtPrinter::new(f, Namespace::TypeNS)))?; - Ok(()) - } -} - -// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. -impl LiftAndPrintToFmt<'tcx> for ty::RegionKind { - fn lift_and_print_to_fmt( - &self, - tcx: TyCtxt<'_, '_, 'tcx>, - f: &mut fmt::Formatter<'_>, - ) -> fmt::Result { - self.print(PrintCx::new(tcx, FmtPrinter::new(f, Namespace::TypeNS)))?; - Ok(()) + type Output = P; + type Error = P::Error; + fn print(&self, mut cx: P) -> Result { + define_scoped_cx!(cx); + p!(print(self.0), write(" : "), print(self.1)); + Ok(cx) } } macro_rules! forward_display_to_print { - (<$($T:ident),*> $ty:ty) => { - impl<$($T),*> fmt::Display for $ty - where Self: for<'a> LiftAndPrintToFmt<'a> - { + ($($ty:ty),+) => { + $(impl fmt::Display for $ty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ty::tls::with(|tcx| self.lift_and_print_to_fmt(tcx, f)) + ty::tls::with(|tcx| { + tcx.lift(self) + .expect("could not lift for printing") + .print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?; + Ok(()) + }) } - } - }; - - ($ty:ty) => { - forward_display_to_print!(<> $ty); + })+ }; } macro_rules! define_print_and_forward_display { - (($self:ident, $cx:ident): <$($T:ident),*> $ty:ty $print:block) => { - impl<$($T,)* P: PrettyPrinter> Print<'tcx, P> for $ty - where $($T: Print<'tcx, P, Output = P, Error = P::Error>),* - { + (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { + $(impl<'gcx: 'tcx, 'tcx, P: PrettyPrinter<'gcx, 'tcx>> Print<'gcx, 'tcx, P> for $ty { type Output = P; type Error = fmt::Error; - fn print(&$self, $cx: PrintCx<'_, '_, 'tcx, P>) -> Result { + fn print(&$self, $cx: P) -> Result { #[allow(unused_mut)] let mut $cx = $cx; define_scoped_cx!($cx); let _: () = $print; #[allow(unreachable_code)] - $cx.ok() + Ok($cx) } - } + })+ - forward_display_to_print!(<$($T),*> $ty); - }; - - (($self:ident, $cx:ident): $($ty:ty $print:block)+) => { - $(define_print_and_forward_display!(($self, $cx): <> $ty $print);)+ + forward_display_to_print!($($ty),+); }; } -forward_display_to_print!(ty::RegionKind); -forward_display_to_print!(Ty<'tcx>); -forward_display_to_print!(&'tcx ty::List>); -forward_display_to_print!( ty::Binder); - -define_print_and_forward_display! { - (self, cx): - - ty::OutlivesPredicate { - p!(print(self.0), write(" : "), print(self.1)) +// HACK(eddyb) this is separate because `ty::RegionKind` doesn't need lifting. +impl fmt::Display for ty::RegionKind { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + ty::tls::with(|tcx| { + self.print(FmtPrinter::new(tcx, f, Namespace::TypeNS))?; + Ok(()) + }) } } +forward_display_to_print! { + Ty<'tcx>, + &'tcx ty::List>, + + // HACK(eddyb) these are exhaustive instead of generic, + // because `for<'gcx: 'tcx, 'tcx>` isn't possible yet. + ty::Binder<&'tcx ty::List>>, + ty::Binder>, + ty::Binder>, + ty::Binder>, + ty::Binder>, + ty::Binder>, + ty::Binder, ty::Region<'tcx>>>, + ty::Binder, ty::Region<'tcx>>>, + + ty::OutlivesPredicate, ty::Region<'tcx>>, + ty::OutlivesPredicate, ty::Region<'tcx>> +} + define_print_and_forward_display! { (self, cx): @@ -1495,13 +1453,13 @@ define_print_and_forward_display! { ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. - let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let trait_ref = self.with_self_ty(cx.tcx, dummy_self); + let dummy_self = cx.tcx().mk_infer(ty::FreshTy(0)); + let trait_ref = self.with_self_ty(cx.tcx(), dummy_self); p!(print(trait_ref)) } ty::ExistentialProjection<'tcx> { - let name = cx.tcx.associated_item(self.item_def_id).ident; + let name = cx.tcx().associated_item(self.item_def_id).ident; p!(write("{}=", name), print(self.ty)) } @@ -1510,7 +1468,7 @@ define_print_and_forward_display! { ty::ExistentialPredicate::Trait(x) => p!(print(x)), ty::ExistentialPredicate::Projection(x) => p!(print(x)), ty::ExistentialPredicate::AutoTrait(def_id) => { - nest!(cx.print_def_path(def_id, None)) + cx = cx.print_def_path(def_id, None)?; } } } @@ -1525,13 +1483,13 @@ define_print_and_forward_display! { } p!(write("fn")); - nest!(cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())); + cx = cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())?; } ty::InferTy { - if cx.tcx.sess.verbose() { + if cx.tcx().sess.verbose() { p!(write("{:?}", self)); - return cx.ok(); + return Ok(cx); } match *self { ty::TyVar(_) => p!(write("_")), @@ -1544,7 +1502,7 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - nest!(cx.print_def_path(self.def_id, Some(self.substs))); + cx = cx.print_def_path(self.def_id, Some(self.substs))?; } ty::ParamTy { @@ -1564,7 +1522,7 @@ define_print_and_forward_display! { } ty::ProjectionTy<'tcx> { - nest!(cx.print_def_path(self.item_def_id, Some(self.substs))); + cx = cx.print_def_path(self.item_def_id, Some(self.substs))?; } ty::ClosureKind { @@ -1585,17 +1543,17 @@ define_print_and_forward_display! { ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("the trait `")); - nest!(cx.print_def_path(trait_def_id, None)); + cx = cx.print_def_path(trait_def_id, None)?; p!(write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { p!(write("the closure `")); - nest!(cx.print_value_path(closure_def_id, None)); + cx = cx.print_value_path(closure_def_id, None)?; p!(write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { p!(write("the constant `")); - nest!(cx.print_value_path(def_id, Some(substs))); + cx = cx.print_value_path(def_id, Some(substs))?; p!(write("` can be evaluated")) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 54c27485875e2..fcb23caedf11a 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -8,7 +8,7 @@ use mir::ProjectionKind; use mir::interpret::ConstValue; use ty::{self, Lift, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use ty::print::{FmtPrinter, PrintCx, Printer}; +use ty::print::{FmtPrinter, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use smallvec::SmallVec; use mir::interpret; @@ -32,8 +32,9 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.print_def_path(self.def_id, None)?; + ty::tls::with(|tcx| { + FmtPrinter::new(tcx, f, Namespace::TypeNS) + .print_def_path(self.def_id, None)?; Ok(()) }) } @@ -41,8 +42,9 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with_tls_tcx(FmtPrinter::new(f, Namespace::TypeNS), |cx| { - cx.print_def_path(self.did, None)?; + ty::tls::with(|tcx| { + FmtPrinter::new(tcx, f, Namespace::TypeNS) + .print_def_path(self.did, None)?; Ok(()) }) } @@ -318,6 +320,7 @@ CloneTypeFoldableAndLiftImpls! { /////////////////////////////////////////////////////////////////////////// // Lift implementations +// FIXME(eddyb) replace all the uses of `Option::map` with `?`. impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) { type Lifted = (A::Lifted, B::Lifted); fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { @@ -414,6 +417,23 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialTraitRef<'a> { } } +impl<'a, 'tcx> Lift<'tcx> for ty::ExistentialPredicate<'a> { + type Lifted = ty::ExistentialPredicate<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + match self { + ty::ExistentialPredicate::Trait(x) => { + tcx.lift(x).map(ty::ExistentialPredicate::Trait) + } + ty::ExistentialPredicate::Projection(x) => { + tcx.lift(x).map(ty::ExistentialPredicate::Projection) + } + ty::ExistentialPredicate::AutoTrait(def_id) => { + Some(ty::ExistentialPredicate::AutoTrait(*def_id)) + } + } + } +} + impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> { type Lifted = ty::TraitPredicate<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 2337d8f6ea407..e20f6aaaddcab 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -92,7 +92,7 @@ use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::print::{PrettyPrinter, PrintCx, Printer, Print}; +use rustc::ty::print::{PrettyPrinter, Printer, Print}; use rustc::ty::query::Providers; use rustc::ty::subst::{Kind, Substs, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -221,10 +221,11 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - PrintCx::new(tcx, SymbolPath::new()) - .print_def_path(def_id, None) - .unwrap() - .into_interned() + SymbolPrinter { + tcx, + path: SymbolPath::new(), + keep_within_component: false, + }.print_def_path(def_id, None).unwrap().path.into_interned() } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { @@ -319,7 +320,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id)); if instance.is_vtable_shim() { - let _ = buf.write_str("{{vtable-shim}}"); + sanitize(&mut buf.temp_buf, "{{vtable-shim}}"); } buf.finish(hash) @@ -342,12 +343,6 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance struct SymbolPath { result: String, temp_buf: String, - - // When `true`, `finalize_pending_component` isn't used. - // This is needed when recursing into `path_qualified`, - // or `path_generic_args`, as any nested paths are - // logically within one component. - keep_within_component: bool, } impl SymbolPath { @@ -355,7 +350,6 @@ impl SymbolPath { let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), - keep_within_component: false, }; result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested result @@ -365,7 +359,6 @@ impl SymbolPath { let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), - keep_within_component: false, }; result.result.push_str(&symbol.as_str()); result @@ -393,17 +386,28 @@ impl SymbolPath { } } +struct SymbolPrinter<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + path: SymbolPath, + + // When `true`, `finalize_pending_component` isn't used. + // This is needed when recursing into `path_qualified`, + // or `path_generic_args`, as any nested paths are + // logically within one component. + keep_within_component: bool, +} + // HACK(eddyb) this relies on using the `fmt` interface to get // `PrettyPrinter` aka pretty printing of e.g. types in paths, // symbol names should have their own printing machinery. -impl fmt::Write for SymbolPath { +impl fmt::Write for SymbolPrinter<'_, '_> { fn write_str(&mut self, s: &str) -> fmt::Result { - sanitize(&mut self.temp_buf, s); + sanitize(&mut self.path.temp_buf, s); Ok(()) } } -impl Printer for SymbolPath { +impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { type Error = fmt::Error; type Path = Self; @@ -411,15 +415,19 @@ impl Printer for SymbolPath { type Type = Self; type DynExistential = Self; + fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx + } + fn print_region( - self: PrintCx<'_, '_, '_, Self>, + self, _region: ty::Region<'_>, ) -> Result { - self.ok() + Ok(self) } fn print_type( - self: PrintCx<'_, '_, 'tcx, Self>, + self, ty: Ty<'tcx>, ) -> Result { match ty.sty { @@ -437,7 +445,7 @@ impl Printer for SymbolPath { } fn print_dyn_existential( - mut self: PrintCx<'_, '_, 'tcx, Self>, + mut self, predicates: &'tcx ty::List>, ) -> Result { let mut first = false; @@ -446,20 +454,20 @@ impl Printer for SymbolPath { write!(self, "+")?; } first = false; - self = PrintCx::new(self.tcx, p.print(self)?); + self = p.print(self)?; } - self.ok() + Ok(self) } fn path_crate( - mut self: PrintCx<'_, '_, '_, Self>, + mut self, cnum: CrateNum, ) -> Result { self.write_str(&self.tcx.original_crate_name(cnum).as_str())?; - self.ok() + Ok(self) } fn path_qualified( - self: PrintCx<'_, '_, 'tcx, Self>, + self, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -481,11 +489,9 @@ impl Printer for SymbolPath { } } - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append_impl( + self, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -495,33 +501,29 @@ impl Printer for SymbolPath { trait_ref, ) } - fn path_append<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append( + mut self, + print_prefix: impl FnOnce(Self) -> Result, text: &str, ) -> Result { - let mut path = print_prefix(self)?; + self = print_prefix(self)?; - if path.keep_within_component { + if self.keep_within_component { // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. - path.write_str("::")?; + self.write_str("::")?; } else { - path.finalize_pending_component(); + self.path.finalize_pending_component(); } - path.write_str(text)?; - Ok(path) + self.write_str(text)?; + Ok(self) } - fn path_generic_args<'gcx, 'tcx>( - mut self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_generic_args( + mut self, + print_prefix: impl FnOnce(Self) -> Result, args: &[Kind<'tcx>], ) -> Result { - self = PrintCx::new(self.tcx, print_prefix(self)?); + self = print_prefix(self)?; let args = args.iter().cloned().filter(|arg| { match arg.unpack() { @@ -533,48 +535,48 @@ impl Printer for SymbolPath { if args.clone().next().is_some() { self.generic_delimiters(|cx| cx.comma_sep(args)) } else { - self.ok() + Ok(self) } } } -impl PrettyPrinter for SymbolPath { +impl PrettyPrinter<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { fn region_should_not_be_omitted( - self: &PrintCx<'_, '_, '_, Self>, + &self, _region: ty::Region<'_>, ) -> bool { false } fn comma_sep( - mut self: PrintCx<'_, '_, 'tcx, Self>, + mut self, mut elems: impl Iterator, ) -> Result - where T: Print<'tcx, Self, Output = Self, Error = Self::Error> + where T: Print<'tcx, 'tcx, Self, Output = Self, Error = Self::Error> { if let Some(first) = elems.next() { - self = PrintCx::new(self.tcx, first.print(self)?); + self = first.print(self)?; for elem in elems { self.write_str(",")?; - self = PrintCx::new(self.tcx, elem.print(self)?); + self = elem.print(self)?; } } - self.ok() + Ok(self) } - fn generic_delimiters<'gcx, 'tcx>( - mut self: PrintCx<'_, 'gcx, 'tcx, Self>, - f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result, + fn generic_delimiters( + mut self, + f: impl FnOnce(Self) -> Result, ) -> Result { write!(self, "<")?; let kept_within_component = mem::replace(&mut self.keep_within_component, true); - let mut path = f(self)?; - path.keep_within_component = kept_within_component; + self = f(self)?; + self.keep_within_component = kept_within_component; - write!(path, ">")?; + write!(self, ">")?; - Ok(path) + Ok(self) } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 9bcecaa489483..78c34cb78b623 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -2308,7 +2308,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// name where required. fn get_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut s, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS); // We need to add synthesized lifetimes where appropriate. We do // this by hooking into the pretty printer and telling it to label the @@ -2323,7 +2323,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => {} } - let _ = ty.print(ty::print::PrintCx::new(self.infcx.tcx, printer)); + let _ = ty.print(printer); s } @@ -2331,7 +2331,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// synthesized lifetime name where required. fn get_region_name_for_ty(&self, ty: ty::Ty<'tcx>, counter: usize) -> String { let mut s = String::new(); - let mut printer = ty::print::FmtPrinter::new(&mut s, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS); let region = match ty.sty { ty::TyKind::Ref(region, _, _) => { @@ -2348,7 +2348,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => bug!("ty for annotation of borrow region is not a reference"), }; - let _ = region.print(ty::print::PrintCx::new(self.infcx.tcx, printer)); + let _ = region.print(printer); s } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 28d0d1e310be0..e89ffa153a397 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4043,13 +4043,18 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { } } -pub fn get_path_for_type(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path -where F: Fn(DefId) -> Def { - use rustc::ty::print::{PrintCx, Printer}; +pub fn get_path_for_type( + tcx: TyCtxt, + def_id: DefId, + def_ctor: impl Fn(DefId) -> Def, +) -> hir::Path { + use rustc::ty::print::Printer; - struct AbsolutePathPrinter; + struct AbsolutePathPrinter<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + } - impl Printer for AbsolutePathPrinter { + impl Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> { type Error = !; type Path = Vec; @@ -4057,35 +4062,39 @@ where F: Fn(DefId) -> Def { type Type = (); type DynExistential = (); + fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx + } + fn print_region( - self: PrintCx<'_, '_, '_, Self>, + self, _region: ty::Region<'_>, ) -> Result { Ok(()) } fn print_type( - self: PrintCx<'_, '_, 'tcx, Self>, + self, _ty: Ty<'tcx>, ) -> Result { Ok(()) } - fn print_dyn_existential<'tcx>( - self: PrintCx<'_, '_, 'tcx, Self>, + fn print_dyn_existential( + self, _predicates: &'tcx ty::List>, ) -> Result { Ok(()) } fn path_crate( - self: PrintCx<'_, '_, '_, Self>, + self, cnum: CrateNum, ) -> Result { Ok(vec![self.tcx.original_crate_name(cnum).to_string()]) } fn path_qualified( - self: PrintCx<'_, '_, 'tcx, Self>, + self, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -4096,11 +4105,9 @@ where F: Fn(DefId) -> Def { }]) } - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append_impl( + self, + print_prefix: impl FnOnce(Self) -> Result, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -4116,29 +4123,25 @@ where F: Fn(DefId) -> Def { Ok(path) } - fn path_append<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, text: &str, ) -> Result { let mut path = print_prefix(self)?; path.push(text.to_string()); Ok(path) } - fn path_generic_args<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_generic_args( + self, + print_prefix: impl FnOnce(Self) -> Result, _args: &[Kind<'tcx>], ) -> Result { print_prefix(self) } } - let names = PrintCx::new(tcx, AbsolutePathPrinter) + let names = AbsolutePathPrinter { tcx: tcx.global_tcx() } .print_def_path(def_id, None) .unwrap(); From 0d2cee3021292076a89544bfdbfbad45f4072600 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 12:28:43 +0200 Subject: [PATCH 63/68] rustc: let ty::print::pretty's p! macro call arbitrary methods. --- src/librustc/ty/print/pretty.rs | 67 ++++++++++++++++----------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 95d11020fcf11..25ba0f38b44d6 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -19,20 +19,19 @@ use std::ops::{Deref, DerefMut}; // `pretty` is a separate module only for organization. use super::*; -macro_rules! print_inner { - (write ($($data:expr),+)) => { +macro_rules! p { + (@write($($data:expr),+)) => { write!(scoped_cx!(), $($data),+)? }; - ($kind:ident ($data:expr)) => { - scoped_cx!() = $data.$kind(scoped_cx!())? + (@print($x:expr)) => { + scoped_cx!() = $x.print(scoped_cx!())? }; -} -macro_rules! p { - ($($kind:ident $data:tt),+) => { - { - $(print_inner!($kind $data));+ - } + (@$method:ident($($arg:expr),*)) => { + scoped_cx!() = scoped_cx!().$method($($arg),*)? }; + ($($kind:ident $data:tt),+) => {{ + $(p!(@$kind $data);)+ + }}; } macro_rules! define_scoped_cx { ($cx:ident) => { @@ -474,9 +473,8 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } ty::FnDef(def_id, substs) => { let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); - p!(print(sig), write(" {{")); - self = self.print_value_path(def_id, Some(substs))?; - p!(write("}}")) + p!(print(sig), + write(" {{"), print_value_path(def_id, Some(substs)), write("}}")); } ty::FnPtr(ref bare_fn) => { p!(print(bare_fn)) @@ -498,7 +496,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } } ty::Adt(def, substs) => { - self = self.print_def_path(def.did, Some(substs))?; + p!(print_def_path(def.did, Some(substs))); } ty::Dynamic(data, r) => { let print_r = self.region_should_not_be_omitted(r); @@ -511,7 +509,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } } ty::Foreign(def_id) => { - self = self.print_def_path(def_id, None)?; + p!(print_def_path(def_id, None)); } ty::Projection(ref data) => p!(print(data)), ty::UnnormalizedProjection(ref data) => { @@ -612,7 +610,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: p!(write(" "), print(witness), write("]")) }, ty::GeneratorWitness(types) => { - self = self.in_binder(&types)?; + p!(in_binder(&types)); } ty::Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, self.tcx()); @@ -684,7 +682,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: let mut first = true; if let Some(principal) = predicates.principal() { - self = self.print_def_path(principal.def_id, None)?; + p!(print_def_path(principal.def_id, None)); let mut resugared = false; @@ -694,7 +692,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: if let ty::Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = predicates.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - self = self.pretty_fn_sig(args, false, proj.ty)?; + p!(pretty_fn_sig(args, false, proj.ty)); resugared = true; } } @@ -733,13 +731,13 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: let args = arg0.into_iter().chain(args); let projections = projection0.into_iter().chain(projections); - self = self.generic_delimiters(|mut cx| { + p!(generic_delimiters(|mut cx| { cx = cx.comma_sep(args)?; if arg0.is_some() && projection0.is_some() { write!(cx, ", ")?; } cx.comma_sep(projections) - })?; + })); } } first = false; @@ -767,7 +765,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } first = false; - self = self.print_def_path(def_id, None)?; + p!(print_def_path(def_id, None)); } Ok(self) @@ -1468,7 +1466,7 @@ define_print_and_forward_display! { ty::ExistentialPredicate::Trait(x) => p!(print(x)), ty::ExistentialPredicate::Projection(x) => p!(print(x)), ty::ExistentialPredicate::AutoTrait(def_id) => { - cx = cx.print_def_path(def_id, None)?; + p!(print_def_path(def_id, None)); } } } @@ -1482,8 +1480,7 @@ define_print_and_forward_display! { p!(write("extern {} ", self.abi)); } - p!(write("fn")); - cx = cx.pretty_fn_sig(self.inputs(), self.variadic, self.output())?; + p!(write("fn"), pretty_fn_sig(self.inputs(), self.variadic, self.output())); } ty::InferTy { @@ -1502,7 +1499,7 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - cx = cx.print_def_path(self.def_id, Some(self.substs))?; + p!(print_def_path(self.def_id, Some(self.substs))); } ty::ParamTy { @@ -1522,7 +1519,7 @@ define_print_and_forward_display! { } ty::ProjectionTy<'tcx> { - cx = cx.print_def_path(self.item_def_id, Some(self.substs))?; + p!(print_def_path(self.item_def_id, Some(self.substs))); } ty::ClosureKind { @@ -1542,19 +1539,19 @@ define_print_and_forward_display! { ty::Predicate::Projection(ref predicate) => p!(print(predicate)), ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { - p!(write("the trait `")); - cx = cx.print_def_path(trait_def_id, None)?; - p!(write("` is object-safe")) + p!(write("the trait `"), + print_def_path(trait_def_id, None), + write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - p!(write("the closure `")); - cx = cx.print_value_path(closure_def_id, None)?; - p!(write("` implements the trait `{}`", kind)) + p!(write("the closure `"), + print_value_path(closure_def_id, None), + write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { - p!(write("the constant `")); - cx = cx.print_value_path(def_id, Some(substs))?; - p!(write("` can be evaluated")) + p!(write("the constant `"), + print_value_path(def_id, Some(substs)), + write("` can be evaluated")) } } } From 53d9194ff484e467960e9c6def241ecdc99c344b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 16:02:57 +0200 Subject: [PATCH 64/68] Fix rebase fallout. --- src/librustc/ty/print/pretty.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 25ba0f38b44d6..7e10888ac57ac 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -6,7 +6,6 @@ use middle::region; use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use ty::subst::{Kind, Subst, Substs, UnpackedKind}; use middle::cstore::{ExternCrate, ExternCrateSource}; -use syntax::ast; use syntax::symbol::{keywords, Symbol}; use rustc_target::spec::abi::Abi; @@ -353,14 +352,11 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. DefPathData::Module(actual_name) | - DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { - visible_parent - .and_then(|parent| { - self.tcx().item_children(parent) - .iter() - .find(|child| child.def.def_id() == cur_def) - .map(|child| child.ident.as_str()) - }) + DefPathData::TypeNs(actual_name) if Some(visible_parent) != actual_parent => { + self.tcx().item_children(visible_parent) + .iter() + .find(|child| child.def.def_id() == def_id) + .map(|child| child.ident.as_str()) .unwrap_or_else(|| actual_name.as_str()) } _ => { From e95d059431122942885e539ff94ed3d1aaf4d51b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Jan 2019 07:21:11 +0200 Subject: [PATCH 65/68] rustc: fix ty::print for symbol mangling. --- src/librustc/hir/map/definitions.rs | 6 +- src/librustc/infer/error_reporting/mod.rs | 8 +- src/librustc/lib.rs | 1 - src/librustc/mir/mod.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/print/mod.rs | 106 +++++++------- src/librustc/ty/print/pretty.rs | 135 ++++++++++-------- src/librustc/ty/structural_impls.rs | 4 +- src/librustc_codegen_utils/symbol_names.rs | 32 ++++- src/librustdoc/clean/mod.rs | 8 +- src/test/mir-opt/retag.rs | 2 +- src/test/ui/consts/const-size_of-cycle.stderr | 8 +- src/test/ui/deprecation/deprecation-lint.rs | 2 +- .../ui/deprecation/deprecation-lint.stderr | 4 +- src/test/ui/impl-trait/auto-trait-leak.stderr | 12 +- src/test/ui/issues/issue-17252.stderr | 2 +- src/test/ui/issues/issue-23302-1.stderr | 6 +- src/test/ui/issues/issue-23302-2.stderr | 6 +- src/test/ui/issues/issue-36163.stderr | 6 +- src/test/ui/issues/issue-44415.stderr | 8 +- src/test/ui/namespace/namespace-mix.stderr | 4 +- 21 files changed, 205 insertions(+), 159 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 1b7445199475c..236990be9b48d 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -660,13 +660,13 @@ impl DefPathData { return name } // note that this does not show up in user printouts - CrateRoot => "{{root}}", + CrateRoot => "{{crate}}", Impl => "{{impl}}", - Misc => "{{?}}", + Misc => "{{misc}}", ClosureExpr => "{{closure}}", StructCtor => "{{constructor}}", AnonConst => "{{constant}}", - ImplTrait => "{{impl-Trait}}", + ImplTrait => "{{opaque}}", }; Symbol::intern(s).as_interned_str() diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 5f339c8c3bb0c..4f745612d746f 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -446,6 +446,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sp: Span, ) { use hir::def_id::CrateNum; + use hir::map::DisambiguatedDefPathData; use ty::print::Printer; use ty::subst::Kind; @@ -505,6 +506,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn path_append_impl( self, _print_prefix: impl FnOnce(Self) -> Result, + _disambiguated_data: &DisambiguatedDefPathData, _self_ty: Ty<'tcx>, _trait_ref: Option>, ) -> Result { @@ -513,10 +515,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn path_append( self, print_prefix: impl FnOnce(Self) -> Result, - text: &str, + disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let mut path = print_prefix(self)?; - path.push(text.to_string()); + path.push(disambiguated_data.data.as_interned_str().to_string()); Ok(path) } fn path_generic_args( @@ -534,7 +536,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let abs_path = |def_id| { AbsolutePathPrinter { tcx: self.tcx } - .print_def_path(def_id, None) + .print_def_path(def_id, &[]) }; // We compare strings because DefPath can be different diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index ce7b228a52709..6fc20c2fbde67 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -60,7 +60,6 @@ #![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![feature(underscore_imports)] #![recursion_limit="512"] diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 61dc52074268e..bc95f8150c01b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2382,7 +2382,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { ty::tls::with(|tcx| { let substs = tcx.lift(&substs).expect("could not lift for printing"); FmtPrinter::new(tcx, f, Namespace::ValueNS) - .print_def_path(variant_def.did, Some(substs))?; + .print_def_path(variant_def.did, substs)?; Ok(()) })?; diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 40941a16ced4a..92aa20f11adef 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -178,7 +178,7 @@ impl<'tcx> fmt::Display for Instance<'tcx> { ty::tls::with(|tcx| { let substs = tcx.lift(&self.substs).expect("could not lift for printing"); FmtPrinter::new(tcx, &mut *f, Namespace::ValueNS) - .print_def_path(self.def_id(), Some(substs))?; + .print_def_path(self.def_id(), substs)?; Ok(()) })?; diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 8eb90c75bac5c..ebeb1061dc573 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,7 +1,7 @@ -use hir::map::DefPathData; +use hir::map::{DefPathData, DisambiguatedDefPathData}; use hir::def_id::{CrateNum, DefId}; use ty::{self, DefIdTree, Ty, TyCtxt}; -use ty::subst::{Kind, Subst, Substs}; +use ty::subst::{Kind, Subst}; use rustc_data_structures::fx::FxHashSet; @@ -29,14 +29,14 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn print_def_path( self, def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + substs: &'tcx [Kind<'tcx>], ) -> Result { self.default_print_def_path(def_id, substs) } fn print_impl_path( self, impl_def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + substs: &'tcx [Kind<'tcx>], self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -71,13 +71,14 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn path_append_impl( self, print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result; fn path_append( self, print_prefix: impl FnOnce(Self) -> Result, - text: &str, + disambiguated_data: &DisambiguatedDefPathData, ) -> Result; fn path_generic_args( self, @@ -90,7 +91,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn default_print_def_path( self, def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + substs: &'tcx [Kind<'tcx>], ) -> Result { debug!("default_print_def_path: def_id={:?}, substs={:?}", def_id, substs); let key = self.tcx().def_key(def_id); @@ -103,61 +104,61 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { } DefPathData::Impl => { + let generics = self.tcx().generics_of(def_id); let mut self_ty = self.tcx().type_of(def_id); - if let Some(substs) = substs { - self_ty = self_ty.subst(self.tcx(), substs); - } - let mut impl_trait_ref = self.tcx().impl_trait_ref(def_id); - if let Some(substs) = substs { + if substs.len() >= generics.count() { + self_ty = self_ty.subst(self.tcx(), substs); impl_trait_ref = impl_trait_ref.subst(self.tcx(), substs); } self.print_impl_path(def_id, substs, self_ty, impl_trait_ref) } _ => { - let generics = substs.map(|_| self.tcx().generics_of(def_id)); - let generics_parent = generics.as_ref().and_then(|g| g.parent); let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; - let print_parent_path = |cx: Self| { - if let Some(generics_parent_def_id) = generics_parent { - assert_eq!(parent_def_id, generics_parent_def_id); - - // FIXME(eddyb) try to move this into the parent's printing - // logic, instead of doing it when printing the child. - let parent_generics = cx.tcx().generics_of(parent_def_id); - let parent_has_own_self = - parent_generics.has_self && parent_generics.parent_count == 0; - if let (Some(substs), true) = (substs, parent_has_own_self) { - let trait_ref = ty::TraitRef::new(parent_def_id, substs); - cx.path_qualified(trait_ref.self_ty(), Some(trait_ref)) - } else { - cx.print_def_path(parent_def_id, substs) - } - } else { - cx.print_def_path(parent_def_id, None) - } - }; - let print_path = |cx: Self| { + + let mut parent_substs = substs; + let mut trait_qualify_parent = false; + if !substs.is_empty() { + let generics = self.tcx().generics_of(def_id); + parent_substs = &substs[..generics.parent_count.min(substs.len())]; + match key.disambiguated_data.data { - // Skip `::{{constructor}}` on tuple/unit structs. - DefPathData::StructCtor => print_parent_path(cx), - - _ => { - cx.path_append( - print_parent_path, - &key.disambiguated_data.data.as_interned_str().as_str(), - ) + // Closures' own generics are only captures, don't print them. + DefPathData::ClosureExpr => {} + + // If we have any generic arguments to print, we do that + // on top of the same path, but without its own generics. + _ => if !generics.params.is_empty() && substs.len() >= generics.count() { + let args = self.generic_args_to_print(generics, substs); + return self.path_generic_args( + |cx| cx.print_def_path(def_id, parent_substs), + args, + ); } } - }; - if let (Some(generics), Some(substs)) = (generics, substs) { - let args = self.generic_args_to_print(generics, substs); - self.path_generic_args(print_path, args) - } else { - print_path(self) + // FIXME(eddyb) try to move this into the parent's printing + // logic, instead of doing it when printing the child. + trait_qualify_parent = + generics.has_self && + generics.parent == Some(parent_def_id) && + parent_substs.len() == generics.parent_count && + self.tcx().generics_of(parent_def_id).parent_count == 0; } + + self.path_append( + |cx: Self| if trait_qualify_parent { + let trait_ref = ty::TraitRef::new( + parent_def_id, + cx.tcx().intern_substs(parent_substs), + ); + cx.path_qualified(trait_ref.self_ty(), Some(trait_ref)) + } else { + cx.print_def_path(parent_def_id, parent_substs) + }, + &key.disambiguated_data, + ) } } } @@ -165,7 +166,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn generic_args_to_print( &self, generics: &'tcx ty::Generics, - substs: &'tcx Substs<'tcx>, + substs: &'tcx [Kind<'tcx>], ) -> &'tcx [Kind<'tcx>] { let mut own_params = generics.parent_count..generics.count(); @@ -192,19 +193,21 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn default_print_impl_path( self, impl_def_id: DefId, - _substs: Option<&'tcx Substs<'tcx>>, + _substs: &'tcx [Kind<'tcx>], self_ty: Ty<'tcx>, impl_trait_ref: Option>, ) -> Result { debug!("default_print_impl_path: impl_def_id={:?}, self_ty={}, impl_trait_ref={:?}", impl_def_id, self_ty, impl_trait_ref); + let key = self.tcx().def_key(impl_def_id); + let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; + // Decide whether to print the parent path for the impl. // Logically, since impls are global, it's never needed, but // users may find it useful. Currently, we omit the parent if // the impl is either in the same module as the self-type or // as the trait. - let parent_def_id = self.tcx().parent(impl_def_id).unwrap(); let in_self_mod = match characteristic_def_id_of_type(self_ty) { None => false, Some(ty_def_id) => self.tcx().parent(ty_def_id) == Some(parent_def_id), @@ -219,7 +222,8 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { // trait-type, then fallback to a format that identifies // the module more clearly. self.path_append_impl( - |cx| cx.print_def_path(parent_def_id, None), + |cx| cx.print_def_path(parent_def_id, &[]), + &key.disambiguated_data, self_ty, impl_trait_ref, ) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 7e10888ac57ac..747437026ea73 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1,10 +1,10 @@ use hir; use hir::def::Namespace; -use hir::map::DefPathData; +use hir::map::{DefPathData, DisambiguatedDefPathData}; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use middle::region; use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use ty::subst::{Kind, Subst, Substs, UnpackedKind}; +use ty::subst::{Kind, Subst, UnpackedKind}; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::symbol::{keywords, Symbol}; @@ -178,7 +178,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: fn print_value_path( self, def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + substs: &'tcx [Kind<'tcx>], ) -> Result { self.print_def_path(def_id, substs) } @@ -264,7 +264,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: }) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); return Ok((if !span.is_dummy() { - self.print_def_path(def_id, None)? + self.print_def_path(def_id, &[])? } else { self.path_crate(cnum)? }, true)); @@ -313,13 +313,13 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: visible_parent, actual_parent, ); - let data = cur_def_key.disambiguated_data.data; + let mut data = cur_def_key.disambiguated_data.data; debug!( "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}", data, visible_parent, actual_parent, ); - let symbol = match data { + match data { // In order to output a path that could actually be imported (valid and visible), // we need to handle re-exports correctly. // @@ -351,27 +351,30 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: // the children of the visible parent (as was done when computing // `visible_parent_map`), looking for the specific child we currently have and then // have access to the re-exported name. - DefPathData::Module(actual_name) | - DefPathData::TypeNs(actual_name) if Some(visible_parent) != actual_parent => { - self.tcx().item_children(visible_parent) + DefPathData::Module(ref mut name) | + DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { + let reexport = self.tcx().item_children(visible_parent) .iter() .find(|child| child.def.def_id() == def_id) - .map(|child| child.ident.as_str()) - .unwrap_or_else(|| actual_name.as_str()) + .map(|child| child.ident.as_interned_str()); + if let Some(reexport) = reexport { + *name = reexport; + } } - _ => { - data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { - // Re-exported `extern crate` (#43189). - if let DefPathData::CrateRoot = data { - self.tcx().original_crate_name(def_id.krate).as_str() - } else { - Symbol::intern("").as_str() - } - }) - }, - }; - debug!("try_print_visible_def_path: symbol={:?}", symbol); - Ok((self.path_append(Ok, &symbol)?, true)) + // Re-exported `extern crate` (#43189). + DefPathData::CrateRoot => { + data = DefPathData::Module( + self.tcx().original_crate_name(def_id.krate).as_interned_str(), + ); + } + _ => {} + } + debug!("try_print_visible_def_path: data={:?}", data); + + Ok((self.path_append(Ok, &DisambiguatedDefPathData { + data, + disambiguator: 0, + })?, true)) } fn pretty_path_qualified( @@ -469,8 +472,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } ty::FnDef(def_id, substs) => { let sig = self.tcx().fn_sig(def_id).subst(self.tcx(), substs); - p!(print(sig), - write(" {{"), print_value_path(def_id, Some(substs)), write("}}")); + p!(print(sig), write(" {{"), print_value_path(def_id, substs), write("}}")); } ty::FnPtr(ref bare_fn) => { p!(print(bare_fn)) @@ -492,7 +494,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } } ty::Adt(def, substs) => { - p!(print_def_path(def.did, Some(substs))); + p!(print_def_path(def.did, substs)); } ty::Dynamic(data, r) => { let print_r = self.region_should_not_be_omitted(r); @@ -505,7 +507,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } } ty::Foreign(def_id) => { - p!(print_def_path(def_id, None)); + p!(print_def_path(def_id, &[])); } ty::Projection(ref data) => p!(print(data)), ty::UnnormalizedProjection(ref data) => { @@ -678,7 +680,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: let mut first = true; if let Some(principal) = predicates.principal() { - p!(print_def_path(principal.def_id, None)); + p!(print_def_path(principal.def_id, &[])); let mut resugared = false; @@ -761,7 +763,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } first = false; - p!(print_def_path(def_id, None)); + p!(print_def_path(def_id, &[])); } Ok(self) @@ -865,7 +867,7 @@ impl TyCtxt<'_, '_, '_> { debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); let mut s = String::new(); let _ = FmtPrinter::new(self, &mut s, ns) - .print_def_path(def_id, None); + .print_def_path(def_id, &[]); s } } @@ -891,21 +893,13 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { fn print_def_path( mut self, def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + substs: &'tcx [Kind<'tcx>], ) -> Result { define_scoped_cx!(self); - // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` - // both here and in `default_print_def_path`. - let generics = substs.map(|_| self.tcx.generics_of(def_id)); - if generics.as_ref().and_then(|g| g.parent).is_none() { + if substs.is_empty() { match self.try_print_visible_def_path(def_id)? { - (cx, true) => return if let (Some(generics), Some(substs)) = (generics, substs) { - let args = cx.generic_args_to_print(generics, substs); - cx.path_generic_args(Ok, args) - } else { - Ok(cx) - }, + (cx, true) => return Ok(cx), (cx, false) => self = cx, } } @@ -927,10 +921,18 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { // only occur very early in the compiler pipeline. let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; let span = self.tcx.def_span(def_id); - return self.path_append( - |cx| cx.print_def_path(parent_def_id, None), - &format!("", span), - ); + + self = self.print_def_path(parent_def_id, &[])?; + + // HACK(eddyb) copy of `path_append` to avoid + // constructing a `DisambiguatedDefPathData`. + if !self.empty_path { + write!(self, "::")?; + } + write!(self, "", span)?; + self.empty_path = false; + + return Ok(self); } } @@ -990,6 +992,7 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { fn path_append_impl( mut self, print_prefix: impl FnOnce(Self) -> Result, + _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -1007,17 +1010,35 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { fn path_append( mut self, print_prefix: impl FnOnce(Self) -> Result, - text: &str, + disambiguated_data: &DisambiguatedDefPathData, ) -> Result { self = print_prefix(self)?; - // FIXME(eddyb) `text` should never be empty, but it + // Skip `::{{constructor}}` on tuple/unit structs. + match disambiguated_data.data { + DefPathData::StructCtor => return Ok(self), + _ => {} + } + + // FIXME(eddyb) `name` should never be empty, but it // currently is for `extern { ... }` "foreign modules". - if !text.is_empty() { + let name = disambiguated_data.data.as_interned_str().as_str(); + if !name.is_empty() { if !self.empty_path { write!(self, "::")?; } - write!(self, "{}", text)?; + write!(self, "{}", name)?; + + // FIXME(eddyb) this will print e.g. `{{closure}}#3`, but it + // might be nicer to use something else, e.g. `{closure#3}`. + let dis = disambiguated_data.disambiguator; + let print_dis = + disambiguated_data.data.get_opt_name().is_none() || + dis != 0 && self.tcx.sess.verbose(); + if print_dis { + write!(self, "#{}", dis)?; + } + self.empty_path = false; } @@ -1059,7 +1080,7 @@ impl PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> fn print_value_path( mut self, def_id: DefId, - substs: Option<&'tcx Substs<'tcx>>, + substs: &'tcx [Kind<'tcx>], ) -> Result { let was_in_value = std::mem::replace(&mut self.in_value, true); self = self.print_def_path(def_id, substs)?; @@ -1462,7 +1483,7 @@ define_print_and_forward_display! { ty::ExistentialPredicate::Trait(x) => p!(print(x)), ty::ExistentialPredicate::Projection(x) => p!(print(x)), ty::ExistentialPredicate::AutoTrait(def_id) => { - p!(print_def_path(def_id, None)); + p!(print_def_path(def_id, &[])); } } } @@ -1495,7 +1516,7 @@ define_print_and_forward_display! { } ty::TraitRef<'tcx> { - p!(print_def_path(self.def_id, Some(self.substs))); + p!(print_def_path(self.def_id, self.substs)); } ty::ParamTy { @@ -1515,7 +1536,7 @@ define_print_and_forward_display! { } ty::ProjectionTy<'tcx> { - p!(print_def_path(self.item_def_id, Some(self.substs))); + p!(print_def_path(self.item_def_id, self.substs)); } ty::ClosureKind { @@ -1536,17 +1557,17 @@ define_print_and_forward_display! { ty::Predicate::WellFormed(ty) => p!(print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { p!(write("the trait `"), - print_def_path(trait_def_id, None), + print_def_path(trait_def_id, &[]), write("` is object-safe")) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { p!(write("the closure `"), - print_value_path(closure_def_id, None), + print_value_path(closure_def_id, &[]), write("` implements the trait `{}`", kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { p!(write("the constant `"), - print_value_path(def_id, Some(substs)), + print_value_path(def_id, substs), write("` can be evaluated")) } } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index fcb23caedf11a..43c20f1e371ec 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -34,7 +34,7 @@ impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { FmtPrinter::new(tcx, f, Namespace::TypeNS) - .print_def_path(self.def_id, None)?; + .print_def_path(self.def_id, &[])?; Ok(()) }) } @@ -44,7 +44,7 @@ impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { FmtPrinter::new(tcx, f, Namespace::TypeNS) - .print_def_path(self.did, None)?; + .print_def_path(self.did, &[])?; Ok(()) }) } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index e20f6aaaddcab..61e0f9ef23b43 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -90,11 +90,11 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; -use rustc::hir::map::definitions::DefPathData; +use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::ich::NodeIdHashingMode; use rustc::ty::print::{PrettyPrinter, Printer, Print}; use rustc::ty::query::Providers; -use rustc::ty::subst::{Kind, Substs, UnpackedKind}; +use rustc::ty::subst::{Kind, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::util::common::record_time; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -225,7 +225,7 @@ fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty:: tcx, path: SymbolPath::new(), keep_within_component: false, - }.print_def_path(def_id, None).unwrap().path.into_interned() + }.print_def_path(def_id, &[]).unwrap().path.into_interned() } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { @@ -438,7 +438,7 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, ty::ClosureSubsts { substs }) | ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { - self.print_def_path(def_id, Some(substs)) + self.print_def_path(def_id, substs) } _ => self.pretty_print_type(ty), } @@ -492,11 +492,23 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { fn path_append_impl( self, print_prefix: impl FnOnce(Self) -> Result, + _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { self.pretty_path_append_impl( - |cx| cx.path_append(print_prefix, ""), + |mut cx| { + cx = print_prefix(cx)?; + + if cx.keep_within_component { + // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. + cx.write_str("::")?; + } else { + cx.path.finalize_pending_component(); + } + + Ok(cx) + }, self_ty, trait_ref, ) @@ -504,10 +516,16 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { fn path_append( mut self, print_prefix: impl FnOnce(Self) -> Result, - text: &str, + disambiguated_data: &DisambiguatedDefPathData, ) -> Result { self = print_prefix(self)?; + // Skip `::{{constructor}}` on tuple/unit structs. + match disambiguated_data.data { + DefPathData::StructCtor => return Ok(self), + _ => {} + } + if self.keep_within_component { // HACK(eddyb) print the path similarly to how `FmtPrinter` prints it. self.write_str("::")?; @@ -515,7 +533,7 @@ impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { self.path.finalize_pending_component(); } - self.write_str(text)?; + self.write_str(&disambiguated_data.data.as_interned_str().as_str())?; Ok(self) } fn path_generic_args( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e89ffa153a397..f7a0f72905f07 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -20,6 +20,7 @@ use rustc::mir::interpret::GlobalId; use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc::hir::map::DisambiguatedDefPathData; use rustc::ty::subst::{Kind, Substs}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; @@ -4108,6 +4109,7 @@ pub fn get_path_for_type( fn path_append_impl( self, print_prefix: impl FnOnce(Self) -> Result, + _disambiguated_data: &DisambiguatedDefPathData, self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -4126,10 +4128,10 @@ pub fn get_path_for_type( fn path_append( self, print_prefix: impl FnOnce(Self) -> Result, - text: &str, + disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let mut path = print_prefix(self)?; - path.push(text.to_string()); + path.push(disambiguated_data.data.as_interned_str().to_string()); Ok(path) } fn path_generic_args( @@ -4142,7 +4144,7 @@ pub fn get_path_for_type( } let names = AbsolutePathPrinter { tcx: tcx.global_tcx() } - .print_def_path(def_id, None) + .print_def_path(def_id, &[]) .unwrap(); hir::Path { diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index bb794409ae01f..7350369fe6118 100644 --- a/src/test/mir-opt/retag.rs +++ b/src/test/mir-opt/retag.rs @@ -98,7 +98,7 @@ fn main() { // } // END rustc.main.EraseRegions.after.mir // START rustc.main-{{closure}}.EraseRegions.after.mir -// fn main::{{closure}}(_1: &[closure@NodeId(124)], _2: &i32) -> &i32 { +// fn main::{{closure}}#0(_1: &[closure@NodeId(124)], _2: &i32) -> &i32 { // ... // bb0: { // Retag([fn entry] _1); diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 8f8eb38e93873..3762f5e3d6ad8 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -1,22 +1,22 @@ -error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}` +error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0` --> $DIR/const-size_of-cycle.rs:6:17 | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: ...which requires const-evaluating `Foo::bytes::{{constant}}`... +note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... --> $SRC_DIR/libcore/mem.rs:LL:COL | LL | intrinsics::size_of::() | ^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}`... +note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... --> $DIR/const-size_of-cycle.rs:6:17 | LL | bytes: [u8; std::mem::size_of::()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}`, completing the cycle + = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo` --> $DIR/const-size_of-cycle.rs:5:1 | diff --git a/src/test/ui/deprecation/deprecation-lint.rs b/src/test/ui/deprecation/deprecation-lint.rs index 6b3e9a8ad8116..38ac8dc7a5571 100644 --- a/src/test/ui/deprecation/deprecation-lint.rs +++ b/src/test/ui/deprecation/deprecation-lint.rs @@ -313,7 +313,7 @@ mod this_crate { let _ = || { #[deprecated] fn bar() { } - bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar' + bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar' }; } diff --git a/src/test/ui/deprecation/deprecation-lint.stderr b/src/test/ui/deprecation/deprecation-lint.stderr index 46875d0bf13ba..b9355b67d74f1 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -286,10 +286,10 @@ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text LL | ::trait_deprecated_text(&foo); //~ ERROR use of deprecated item 'this_crate::Trait::trait_deprecated_text': text | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar' +error: use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar' --> $DIR/deprecation-lint.rs:316:13 | -LL | bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}::bar' +LL | bar(); //~ ERROR use of deprecated item 'this_crate::test_fn_closure_body::{{closure}}#0::bar' | ^^^ error: use of deprecated item 'this_crate::DeprecatedTrait': text diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index b936fed85f48e..4e79dfc3f7c01 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` +error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0` --> $DIR/auto-trait-leak.rs:14:16 | LL | fn cycle1() -> impl Clone { @@ -10,7 +10,7 @@ note: ...which requires processing `cycle1`... LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... -note: ...which requires processing `cycle2::{{impl-Trait}}`... +note: ...which requires processing `cycle2::{{opaque}}#0`... --> $DIR/auto-trait-leak.rs:23:16 | LL | fn cycle2() -> impl Clone { @@ -21,7 +21,7 @@ note: ...which requires processing `cycle2`... LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... - = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle + = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/auto-trait-leak.rs:3:1 | @@ -34,7 +34,7 @@ LL | | Rc::new(String::from("foo")) LL | | } | |_^ -error[E0391]: cycle detected when processing `cycle1::{{impl-Trait}}` +error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0` --> $DIR/auto-trait-leak.rs:14:16 | LL | fn cycle1() -> impl Clone { @@ -46,7 +46,7 @@ note: ...which requires processing `cycle1`... LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... -note: ...which requires processing `cycle2::{{impl-Trait}}`... +note: ...which requires processing `cycle2::{{opaque}}#0`... --> $DIR/auto-trait-leak.rs:23:16 | LL | fn cycle2() -> impl Clone { @@ -56,7 +56,7 @@ note: ...which requires processing `cycle2`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: ...which again requires processing `cycle1::{{impl-Trait}}`, completing the cycle + = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle note: cycle used when checking item types in top-level module --> $DIR/auto-trait-leak.rs:3:1 | diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr index e333e15065111..809f9413e5996 100644 --- a/src/test/ui/issues/issue-17252.stderr +++ b/src/test/ui/issues/issue-17252.stderr @@ -5,7 +5,7 @@ LL | const FOO: usize = FOO; //~ ERROR E0391 | ^^^ | = note: ...which again requires processing `FOO`, completing the cycle -note: cycle used when processing `main::{{constant}}` +note: cycle used when processing `main::{{constant}}#0` --> $DIR/issue-17252.rs:4:18 | LL | let _x: [u8; FOO]; // caused stack overflow prior to fix diff --git a/src/test/ui/issues/issue-23302-1.stderr b/src/test/ui/issues/issue-23302-1.stderr index ed422e10c985e..7394b83db6381 100644 --- a/src/test/ui/issues/issue-23302-1.stderr +++ b/src/test/ui/issues/issue-23302-1.stderr @@ -1,11 +1,11 @@ -error[E0391]: cycle detected when processing `X::A::{{constant}}` +error[E0391]: cycle detected when processing `X::A::{{constant}}#0` --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, //~ ERROR E0391 | ^^^^^^^^^^^^^ | - = note: ...which again requires processing `X::A::{{constant}}`, completing the cycle -note: cycle used when const-evaluating `X::A::{{constant}}` + = note: ...which again requires processing `X::A::{{constant}}#0`, completing the cycle +note: cycle used when const-evaluating `X::A::{{constant}}#0` --> $DIR/issue-23302-1.rs:4:9 | LL | A = X::A as isize, //~ ERROR E0391 diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index b6d44ceec9d75..122fe930fc8c2 100644 --- a/src/test/ui/issues/issue-23302-2.stderr +++ b/src/test/ui/issues/issue-23302-2.stderr @@ -1,11 +1,11 @@ -error[E0391]: cycle detected when processing `Y::A::{{constant}}` +error[E0391]: cycle detected when processing `Y::A::{{constant}}#0` --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, //~ ERROR E0391 | ^^^^^^^^^^^^^ | - = note: ...which again requires processing `Y::A::{{constant}}`, completing the cycle -note: cycle used when const-evaluating `Y::A::{{constant}}` + = note: ...which again requires processing `Y::A::{{constant}}#0`, completing the cycle +note: cycle used when const-evaluating `Y::A::{{constant}}#0` --> $DIR/issue-23302-2.rs:4:9 | LL | A = Y::B as isize, //~ ERROR E0391 diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/issues/issue-36163.stderr index c114e58e4d943..99891f1af6962 100644 --- a/src/test/ui/issues/issue-36163.stderr +++ b/src/test/ui/issues/issue-36163.stderr @@ -1,4 +1,4 @@ -error[E0391]: cycle detected when processing `Foo::B::{{constant}}` +error[E0391]: cycle detected when processing `Foo::B::{{constant}}#0` --> $DIR/issue-36163.rs:4:9 | LL | B = A, //~ ERROR E0391 @@ -9,8 +9,8 @@ note: ...which requires processing `A`... | LL | const A: isize = Foo::B as isize; | ^^^^^^^^^^^^^^^ - = note: ...which again requires processing `Foo::B::{{constant}}`, completing the cycle -note: cycle used when const-evaluating `Foo::B::{{constant}}` + = note: ...which again requires processing `Foo::B::{{constant}}#0`, completing the cycle +note: cycle used when const-evaluating `Foo::B::{{constant}}#0` --> $DIR/issue-36163.rs:4:9 | LL | B = A, //~ ERROR E0391 diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr index 3f377fd27e7db..df8e804c87a3f 100644 --- a/src/test/ui/issues/issue-44415.stderr +++ b/src/test/ui/issues/issue-44415.stderr @@ -1,22 +1,22 @@ -error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}` +error[E0391]: cycle detected when const-evaluating + checking `Foo::bytes::{{constant}}#0` --> $DIR/issue-44415.rs:6:17 | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^ | -note: ...which requires const-evaluating `Foo::bytes::{{constant}}`... +note: ...which requires const-evaluating `Foo::bytes::{{constant}}#0`... --> $DIR/issue-44415.rs:6:26 | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: All, def_id: None }, value: [u8; _] }`... -note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}`... +note: ...which requires const-evaluating + checking `Foo::bytes::{{constant}}#0`... --> $DIR/issue-44415.rs:6:17 | LL | bytes: [u8; unsafe { intrinsics::size_of::() }], | ^^^^^^ - = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}`, completing the cycle + = note: ...which again requires const-evaluating + checking `Foo::bytes::{{constant}}#0`, completing the cycle note: cycle used when processing `Foo` --> $DIR/issue-44415.rs:5:1 | diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index 5ebb40e75b395..3856d8d6a3415 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -462,11 +462,11 @@ note: required by `check` LL | fn check(_: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::c::E::TV}: Impossible` is not satisfied +error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}: Impossible` is not satisfied --> $DIR/namespace-mix.rs:128:5 | LL | check(xm9::TV); //~ ERROR c::E - | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::c::E::TV}` + | ^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` | note: required by `check` --> $DIR/namespace-mix.rs:21:1 From 26898a067baaf2ca173a7073dd8907bcb87ef33d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Jan 2019 07:24:32 +0200 Subject: [PATCH 66/68] rustc_codegen_utils: add new mangling scheme implementation. --- Cargo.lock | 7 + src/librustc_codegen_utils/Cargo.toml | 1 + src/librustc_codegen_utils/lib.rs | 3 + src/librustc_codegen_utils/symbol_names.rs | 103 +-- .../symbol_names/new.rs | 675 ++++++++++++++++++ 5 files changed, 745 insertions(+), 44 deletions(-) create mode 100644 src/librustc_codegen_utils/symbol_names/new.rs diff --git a/Cargo.lock b/Cargo.lock index c34a325a47492..319a877d97076 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1877,6 +1877,11 @@ dependencies = [ "getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "punycode" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quick-error" version = "1.2.2" @@ -2524,6 +2529,7 @@ version = "0.0.0" dependencies = [ "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", @@ -3939,6 +3945,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum proptest 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "926d0604475349f463fe44130aae73f2294b5309ab2ca0310b998bd334ef191f" "checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" +"checksum punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ddd112cca70a4d30883b2d21568a1d376ff8be4758649f64f973c6845128ad3" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index 34a09f30b6411..9794d4c0c9041 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -12,6 +12,7 @@ test = false [dependencies] flate2 = "1.0" log = "0.4" +punycode = "0.4.0" syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index bb3b347b6a8fe..ac8a90ba0d324 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -9,8 +9,10 @@ #![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(core_intrinsics)] #![feature(custom_attribute)] #![feature(in_band_lifetimes)] +#![feature(never_type)] #![feature(nll)] #![allow(unused_attributes)] #![feature(rustc_diagnostic_macros)] @@ -20,6 +22,7 @@ extern crate flate2; #[macro_use] extern crate log; +extern crate punycode; #[macro_use] extern crate rustc; diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 61e0f9ef23b43..01f45600a733a 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -106,6 +106,8 @@ use syntax_pos::symbol::Symbol; use std::fmt::{self, Write}; use std::mem::{self, discriminant}; +mod new; + pub fn provide(providers: &mut Providers) { *providers = Providers { def_symbol_name, @@ -118,9 +120,6 @@ pub fn provide(providers: &mut Providers) { fn get_symbol_hash<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, - // the DefId of the item this name is for - def_id: DefId, - // instance this name will be for instance: Instance<'tcx>, @@ -129,11 +128,9 @@ fn get_symbol_hash<'a, 'tcx>( // included in the hash as a kind of // safeguard. item_type: Ty<'tcx>, - - // values for generic type parameters, - // if any. - substs: &'tcx Substs<'tcx>, ) -> u64 { + let def_id = instance.def_id(); + let substs = instance.substs; debug!( "get_symbol_hash(def_id={:?}, parameters={:?})", def_id, substs @@ -170,42 +167,7 @@ fn get_symbol_hash<'a, 'tcx>( assert!(!substs.needs_subst()); substs.hash_stable(&mut hcx, &mut hasher); - let is_generic = substs.types().next().is_some(); - let avoid_cross_crate_conflicts = - // If this is an instance of a generic function, we also hash in - // the ID of the instantiating crate. This avoids symbol conflicts - // in case the same instances is emitted in two crates of the same - // project. - is_generic || - - // If we're dealing with an instance of a function that's inlined from - // another crate but we're marking it as globally shared to our - // compliation (aka we're not making an internal copy in each of our - // codegen units) then this symbol may become an exported (but hidden - // visibility) symbol. This means that multiple crates may do the same - // and we want to be sure to avoid any symbol conflicts here. - match MonoItem::Fn(instance).instantiation_mode(tcx) { - InstantiationMode::GloballyShared { may_conflict: true } => true, - _ => false, - }; - - if avoid_cross_crate_conflicts { - let instantiating_crate = if is_generic { - if !def_id.is_local() && tcx.sess.opts.share_generics() { - // If we are re-using a monomorphization from another crate, - // we have to compute the symbol hash accordingly. - let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id); - - upstream_monomorphizations - .and_then(|monos| monos.get(&substs).cloned()) - .unwrap_or(LOCAL_CRATE) - } else { - LOCAL_CRATE - } - } else { - LOCAL_CRATE - }; - + if let Some(instantiating_crate) = instantiating_crate(tcx, instance) { (&tcx.original_crate_name(instantiating_crate).as_str()[..]) .hash_stable(&mut hcx, &mut hasher); (&tcx.crate_disambiguator(instantiating_crate)).hash_stable(&mut hcx, &mut hasher); @@ -220,6 +182,53 @@ fn get_symbol_hash<'a, 'tcx>( hasher.finish() } +fn instantiating_crate( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + instance: Instance<'tcx>, +) -> Option { + let def_id = instance.def_id(); + let substs = instance.substs; + + let is_generic = substs.types().next().is_some(); + let avoid_cross_crate_conflicts = + // If this is an instance of a generic function, we also hash in + // the ID of the instantiating crate. This avoids symbol conflicts + // in case the same instances is emitted in two crates of the same + // project. + is_generic || + + // If we're dealing with an instance of a function that's inlined from + // another crate but we're marking it as globally shared to our + // compliation (aka we're not making an internal copy in each of our + // codegen units) then this symbol may become an exported (but hidden + // visibility) symbol. This means that multiple crates may do the same + // and we want to be sure to avoid any symbol conflicts here. + match MonoItem::Fn(instance).instantiation_mode(tcx) { + InstantiationMode::GloballyShared { may_conflict: true } => true, + _ => false, + }; + + if avoid_cross_crate_conflicts { + Some(if is_generic { + if !def_id.is_local() && tcx.sess.opts.share_generics() { + // If we are re-using a monomorphization from another crate, + // we have to compute the symbol hash accordingly. + let upstream_monomorphizations = tcx.upstream_monomorphizations_for(def_id); + + upstream_monomorphizations + .and_then(|monos| monos.get(&substs).cloned()) + .unwrap_or(LOCAL_CRATE) + } else { + LOCAL_CRATE + } + } else { + LOCAL_CRATE + }) + } else { + None + } +} + fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { SymbolPrinter { tcx, @@ -282,6 +291,12 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance return tcx.item_name(def_id).to_string(); } + compute_mangled_symbol_name(tcx, instance) +} + +fn compute_mangled_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<'tcx>) -> String { + let def_id = instance.def_id(); + // We want to compute the "type" of this item. Unfortunately, some // kinds of items (e.g., closures) don't have an entry in the // item-type array. So walk back up the find the closest parent @@ -315,7 +330,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance // and should not matter anyhow. let instance_ty = tcx.erase_regions(&instance_ty); - let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs); + let hash = get_symbol_hash(tcx, instance, instance_ty); let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id)); diff --git a/src/librustc_codegen_utils/symbol_names/new.rs b/src/librustc_codegen_utils/symbol_names/new.rs new file mode 100644 index 0000000000000..535d2cd456393 --- /dev/null +++ b/src/librustc_codegen_utils/symbol_names/new.rs @@ -0,0 +1,675 @@ +use rustc::hir; +use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::print::{Printer, Print}; +use rustc::ty::subst::{Kind, Subst, UnpackedKind}; +use rustc_data_structures::base_n; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_mir::monomorphize::Instance; +use rustc_target::spec::abi::Abi; +use syntax::ast::{IntTy, UintTy, FloatTy}; + +use std::fmt::Write; +use std::ops::Range; + +pub(super) fn mangle( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + instance: Instance<'tcx>, +) -> (String, String) { + let def_id = instance.def_id(); + // FIXME(eddyb) this should ideally not be needed. + let substs = + tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.substs); + + let print_symbol = |mut cx: SymbolMangler<'_, 'tcx>| { + cx = if instance.is_vtable_shim() { + cx.path_append_ns( + |cx| cx.print_def_path(def_id, substs), + 'S', + 0, + "", + ).unwrap() + } else { + cx.print_def_path(def_id, substs).unwrap() + }; + if let Some(instantiating_crate) = super::instantiating_crate(tcx, instance) { + cx = cx.print_def_path(instantiating_crate.as_def_id(), &[]).unwrap(); + } + cx.out + }; + + let prefix = "_R"; + + let uncompressed = print_symbol(SymbolMangler { + tcx, + compress: None, + binders: vec![], + out: String::from(prefix), + }); + + let compressed = print_symbol(SymbolMangler { + tcx, + compress: Some(Box::new(CompressionCaches { + start_offset: prefix.len(), + + paths: FxHashMap::default(), + types: FxHashMap::default(), + consts: FxHashMap::default(), + })), + binders: vec![], + out: String::from(prefix), + }); + + (uncompressed, compressed) +} + +struct CompressionCaches<'tcx> { + // The length of the prefix in `out` (e.g. 2 for `_R`). + start_offset: usize, + + // The values are start positions in `out`, in bytes. + paths: FxHashMap<(DefId, &'tcx [Kind<'tcx>]), usize>, + types: FxHashMap, usize>, + consts: FxHashMap<&'tcx ty::LazyConst<'tcx>, usize>, +} + +struct BinderLevel { + /// The range of distances from the root of what's + /// being printed, to the lifetimes in a binder. + /// Specifically, a `BrAnon(i)` lifetime has depth + /// `lifetime_depths.start + i`, going away from the + /// the root and towards its use site, as `i` increases. + /// This is used to flatten rustc's pairing of `BrAnon` + /// (intra-binder disambiguation) with a `DebruijnIndex` + /// (binder addressing), to "true" de Bruijn indices, + /// by subtracting the depth of a certain lifetime, from + /// the innermost depth at its use site. + lifetime_depths: Range, +} + +struct SymbolMangler<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + compress: Option>>, + binders: Vec, + out: String, +} + +impl SymbolMangler<'_, 'tcx> { + fn push(&mut self, s: &str) { + self.out.push_str(s); + } + + fn push_integer_62(&mut self, x: u64) { + if let Some(x) = x.checked_sub(1) { + base_n::push_str(x as u128, 62, &mut self.out); + } + self.push("_"); + } + + fn push_opt_integer_62(&mut self, tag: &str, x: u64) { + if let Some(x) = x.checked_sub(1) { + self.push(tag); + self.push_integer_62(x); + } + } + + fn push_disambiguator(&mut self, dis: u64) { + self.push_opt_integer_62("s", dis); + } + + fn push_ident(&mut self, ident: &str) { + let mut use_punycode = false; + let bytes = ident.as_bytes(); + if !bytes.is_empty() { + match bytes[0] { + b'_' | b'a'..=b'z' | b'A'..=b'Z' => {} + 0x80..=0xff => use_punycode = true, + b => bug!("symbol_names: bad start byte {} in ident {:?}", b, ident), + } + for &b in &bytes[1..] { + match b { + b'_' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => {} + 0x80..=0xff => use_punycode = true, + _ => bug!("symbol_names: bad byte {} in ident {:?}", b, ident), + } + } + } + if !use_punycode { + let _ = write!(self.out, "{}{}", ident.len(), ident); + return; + } + + // FIXME(eddyb) we should probably roll our own punycode implementation. + let mut punycode_bytes = match ::punycode::encode(ident) { + Ok(s) => s.into_bytes(), + Err(()) => bug!("symbol_names: punycode encoding failed for ident {:?}", ident), + }; + + // Replace `-` with `_`. + let punycode_suffix = match punycode_bytes.iter().rposition(|&c| c == b'-') { + Some(i) => { + punycode_bytes[i] = b'_'; + &mut punycode_bytes[i + 1..] + } + None => &mut punycode_bytes, + }; + // Replace [0-9] with [A-J]. + for b in punycode_suffix { + if let b'0'..=b'9' = *b { + *b = b'A' + (*b - b'0'); + } + } + + let punycode_string = String::from_utf8(punycode_bytes).unwrap(); + let _ = write!(self.out, "u{}{}", punycode_string.len(), punycode_string); + } + + fn path_append_ns( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + ns: char, + disambiguator: u64, + name: &str, + ) -> Result { + self.push("N"); + self.out.push(ns); + self = print_prefix(self)?; + self.push_disambiguator(disambiguator as u64); + self.push_ident(name); + Ok(self) + } + + fn print_backref(mut self, i: usize) -> Result { + self.push("B"); + self.push_integer_62((i - self.compress.as_ref().unwrap().start_offset) as u64); + Ok(self) + } + + fn in_binder( + mut self, + value: &ty::Binder, + print_value: impl FnOnce(Self, &T) -> Result + ) -> Result + where T: TypeFoldable<'tcx> + { + let regions = if value.has_late_bound_regions() { + self.tcx.collect_referenced_late_bound_regions(value) + } else { + FxHashSet::default() + }; + + let mut lifetime_depths = + self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i); + + let lifetimes = regions.into_iter().map(|br| { + match br { + ty::BrAnon(i) => i + 1, + _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), + } + }).max().unwrap_or(0); + + self.push_opt_integer_62("G", lifetimes as u64); + lifetime_depths.end += lifetimes; + + self.binders.push(BinderLevel { lifetime_depths }); + self = print_value(self, value.skip_binder())?; + self.binders.pop(); + + Ok(self) + } + + // FIXME(eddyb) move this to `Printer` when const generics land. + fn print_const(mut self, constant: &'tcx ty::LazyConst<'tcx>) -> Result { + if let Some(&i) = self.compress.as_ref().and_then(|c| c.consts.get(&constant)) { + return self.print_backref(i); + } + let start = self.out.len(); + + let ty = match *constant { + ty::LazyConst::Unevaluated(def_id, substs) => { + self.tcx.type_of(def_id).subst(self.tcx, substs) + } + ty::LazyConst::Evaluated(c) => c.ty, + }; + match ty.sty { + ty::Uint(_) => {} + _ => { + bug!("symbol_names: unsupported constant of type `{}` ({:?})", + ty, constant); + } + } + self = ty.print(self)?; + match *constant { + ty::LazyConst::Unevaluated(..) => { + // NOTE(eddyb) despite having the path, we need to + // encode a placeholder, as the path could refer + // back to e.g. an `impl` using the constant. + self.push("p"); + } + ty::LazyConst::Evaluated(c) => { + let bits = c.unwrap_bits(self.tcx, ty::ParamEnv::empty().and(ty)); + let _ = write!(self.out, "{:x}_", bits); + } + } + + // Only cache consts that do not refer to an enclosing + // binder (which would change depending on context). + if !constant.has_escaping_bound_vars() { + if let Some(c) = &mut self.compress { + c.consts.insert(constant, start); + } + } + Ok(self) + } +} + +impl Printer<'tcx, 'tcx> for SymbolMangler<'_, 'tcx> { + type Error = !; + + type Path = Self; + type Region = Self; + type Type = Self; + type DynExistential = Self; + + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx + } + + fn print_def_path( + mut self, + def_id: DefId, + substs: &'tcx [Kind<'tcx>], + ) -> Result { + if let Some(&i) = self.compress.as_ref().and_then(|c| c.paths.get(&(def_id, substs))) { + return self.print_backref(i); + } + let start = self.out.len(); + + self = self.default_print_def_path(def_id, substs)?; + + // Only cache paths that do not refer to an enclosing + // binder (which would change depending on context). + if !substs.iter().any(|k| k.has_escaping_bound_vars()) { + if let Some(c) = &mut self.compress { + c.paths.insert((def_id, substs), start); + } + } + Ok(self) + } + + fn print_impl_path( + self, + impl_def_id: DefId, + substs: &'tcx [Kind<'tcx>], + mut self_ty: Ty<'tcx>, + mut impl_trait_ref: Option>, + ) -> Result { + let key = self.tcx.def_key(impl_def_id); + let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; + + let mut param_env = self.tcx.param_env(impl_def_id) + .with_reveal_all(); + if !substs.is_empty() { + param_env = param_env.subst(self.tcx, substs); + } + + match &mut impl_trait_ref { + Some(impl_trait_ref) => { + assert_eq!(impl_trait_ref.self_ty(), self_ty); + *impl_trait_ref = + self.tcx.normalize_erasing_regions(param_env, *impl_trait_ref); + self_ty = impl_trait_ref.self_ty(); + } + None => { + self_ty = self.tcx.normalize_erasing_regions(param_env, self_ty); + } + } + + self.path_append_impl( + |cx| cx.print_def_path(parent_def_id, &[]), + &key.disambiguated_data, + self_ty, + impl_trait_ref, + ) + } + + fn print_region( + mut self, + region: ty::Region<'_>, + ) -> Result { + let i = match *region { + // Erased lifetimes use the index 0, for a + // shorter mangling of `L_`. + ty::ReErased => 0, + + // Late-bound lifetimes use indices starting at 1, + // see `BinderLevel` for more details. + ty::ReLateBound(debruijn, ty::BrAnon(i)) => { + let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; + let depth = binder.lifetime_depths.start + i; + + 1 + (self.binders.last().unwrap().lifetime_depths.end - 1 - depth) + } + + _ => bug!("symbol_names: non-erased region `{:?}`", region), + }; + self.push("L"); + self.push_integer_62(i as u64); + Ok(self) + } + + fn print_type( + mut self, + ty: Ty<'tcx>, + ) -> Result { + // Basic types, never cached (single-character). + let basic_type = match ty.sty { + ty::Bool => "b", + ty::Char => "c", + ty::Str => "e", + ty::Tuple(_) if ty.is_unit() => "u", + ty::Int(IntTy::I8) => "a", + ty::Int(IntTy::I16) => "s", + ty::Int(IntTy::I32) => "l", + ty::Int(IntTy::I64) => "x", + ty::Int(IntTy::I128) => "n", + ty::Int(IntTy::Isize) => "i", + ty::Uint(UintTy::U8) => "h", + ty::Uint(UintTy::U16) => "t", + ty::Uint(UintTy::U32) => "m", + ty::Uint(UintTy::U64) => "y", + ty::Uint(UintTy::U128) => "o", + ty::Uint(UintTy::Usize) => "j", + ty::Float(FloatTy::F32) => "f", + ty::Float(FloatTy::F64) => "d", + ty::Never => "z", + + // Placeholders (should be demangled as `_`). + ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | + ty::Infer(_) | ty::Error => "p", + + _ => "", + }; + if !basic_type.is_empty() { + self.push(basic_type); + return Ok(self); + } + + if let Some(&i) = self.compress.as_ref().and_then(|c| c.types.get(&ty)) { + return self.print_backref(i); + } + let start = self.out.len(); + + match ty.sty { + // Basic types, handled above. + ty::Bool | ty::Char | ty::Str | + ty::Int(_) | ty::Uint(_) | ty::Float(_) | + ty::Never => unreachable!(), + ty::Tuple(_) if ty.is_unit() => unreachable!(), + + // Placeholders, also handled as part of basic types. + ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | + ty::Infer(_) | ty::Error => unreachable!(), + + ty::Ref(r, ty, mutbl) => { + self.push(match mutbl { + hir::MutImmutable => "R", + hir::MutMutable => "Q", + }); + if *r != ty::ReErased { + self = r.print(self)?; + } + self = ty.print(self)?; + } + + ty::RawPtr(mt) => { + self.push(match mt.mutbl { + hir::MutImmutable => "P", + hir::MutMutable => "O", + }); + self = mt.ty.print(self)?; + } + + ty::Array(ty, len) => { + self.push("A"); + self = ty.print(self)?; + self = self.print_const(len)?; + } + ty::Slice(ty) => { + self.push("S"); + self = ty.print(self)?; + } + + ty::Tuple(tys) => { + self.push("T"); + for &ty in tys { + self = ty.print(self)?; + } + self.push("E"); + } + + // Mangle all nominal types as paths. + ty::Adt(&ty::AdtDef { did: def_id, .. }, substs) | + ty::FnDef(def_id, substs) | + ty::Opaque(def_id, substs) | + ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::Closure(def_id, ty::ClosureSubsts { substs }) | + ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + self = self.print_def_path(def_id, substs)?; + } + ty::Foreign(def_id) => { + self = self.print_def_path(def_id, &[])?; + } + + ty::FnPtr(sig) => { + self.push("F"); + self = self.in_binder(&sig, |mut cx, sig| { + if sig.unsafety == hir::Unsafety::Unsafe { + cx.push("U"); + } + match sig.abi { + Abi::Rust => {} + Abi::C => cx.push("KC"), + abi => { + cx.push("K"); + let name = abi.name(); + if name.contains('-') { + cx.push_ident(&name.replace('-', "_")); + } else { + cx.push_ident(name); + } + } + } + for &ty in sig.inputs() { + cx = ty.print(cx)?; + } + if sig.variadic { + cx.push("v"); + } + cx.push("E"); + sig.output().print(cx) + })?; + } + + ty::Dynamic(predicates, r) => { + self.push("D"); + self = self.in_binder(&predicates, |cx, predicates| { + cx.print_dyn_existential(predicates) + })?; + self = r.print(self)?; + } + + ty::GeneratorWitness(_) => { + bug!("symbol_names: unexpected `GeneratorWitness`") + } + } + + // Only cache types that do not refer to an enclosing + // binder (which would change depending on context). + if !ty.has_escaping_bound_vars() { + if let Some(c) = &mut self.compress { + c.types.insert(ty, start); + } + } + Ok(self) + } + + fn print_dyn_existential( + mut self, + predicates: &'tcx ty::List>, + ) -> Result { + for predicate in predicates { + match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => { + // Use a type that can't appear in defaults of type parameters. + let dummy_self = self.tcx.mk_infer(ty::FreshTy(0)); + let trait_ref = trait_ref.with_self_ty(self.tcx, dummy_self); + self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?; + } + ty::ExistentialPredicate::Projection(projection) => { + let name = self.tcx.associated_item(projection.item_def_id).ident; + self.push("p"); + self.push_ident(&name.as_str()); + self = projection.ty.print(self)?; + } + ty::ExistentialPredicate::AutoTrait(def_id) => { + self = self.print_def_path(def_id, &[])?; + } + } + } + self.push("E"); + Ok(self) + } + + fn path_crate( + mut self, + cnum: CrateNum, + ) -> Result { + self.push("C"); + let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint(); + self.push_disambiguator(fingerprint.to_smaller_hash()); + let name = self.tcx.original_crate_name(cnum).as_str(); + match name.as_bytes()[0] { + // Crate names can start with digits, so escape them with `_` + // (and also `_` itself, to preserve the distinction). + b'0'..=b'9' | b'_' => self.push_ident(&format!("_{}", name)), + + _ => self.push_ident(&name), + } + Ok(self) + } + fn path_qualified( + mut self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + assert!(trait_ref.is_some()); + let trait_ref = trait_ref.unwrap(); + + self.push("Y"); + self = self_ty.print(self)?; + self.print_def_path(trait_ref.def_id, trait_ref.substs) + } + + fn path_append_impl( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.push(match trait_ref { + Some(_) => "X", + None => "M", + }); + self.push_disambiguator(disambiguated_data.disambiguator as u64); + self = print_prefix(self)?; + self = self_ty.print(self)?; + if let Some(trait_ref) = trait_ref { + self = self.print_def_path(trait_ref.def_id, trait_ref.substs)?; + } + Ok(self) + } + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + ) -> Result { + let name = disambiguated_data.data.get_opt_name().map(|s| s.as_str()); + let name = name.as_ref().map_or("", |s| &s[..]); + let ns = match disambiguated_data.data { + // Avoid putting the burden on demanglers to ignore this. + DefPathData::StructCtor => return print_prefix(self), + + DefPathData::ClosureExpr => 'C', + + // Lowercase a-z are unspecified disambiguation categories. + _ => { + let discriminant = unsafe { + ::std::intrinsics::discriminant_value(&disambiguated_data.data) + }; + assert!(discriminant < 26); + + // Mix in the name to avoid making it too predictable. + let mut d = (discriminant ^ 0x55) % 26; + for (i, b) in name.bytes().enumerate() { + d = (d + i as u64 + b as u64) % 26; + } + + (b'a' + d as u8) as char + } + }; + + self.path_append_ns( + print_prefix, + ns, + disambiguated_data.disambiguator as u64, + name + ) + } + fn path_generic_args( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + args: &[Kind<'tcx>], + ) -> Result { + // Don't print any regions if they're all erased. + let print_regions = args.iter().any(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + let args = args.iter().cloned().filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + + if args.clone().next().is_none() { + return print_prefix(self); + } + + self.push("I"); + self = print_prefix(self)?; + for arg in args { + match arg.unpack() { + UnpackedKind::Lifetime(lt) => { + self = lt.print(self)?; + } + UnpackedKind::Type(ty) => { + self = ty.print(self)?; + } + /*UnpackedKind::Const(c) => { + self.push("K"); + self = c.print(self)?; + }*/ + } + } + self.push("E"); + + Ok(self) + } +} From 386d425add2c3907d742a42d95714751b1c992d7 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Jan 2019 07:26:15 +0200 Subject: [PATCH 67/68] [TEMPORARY] rustc_codegen_utils: add harness for dumping/checking symbol names, and mw mangling impl. --- Cargo.lock | 23 + src/librustc_codegen_utils/Cargo.toml | 8 + src/librustc_codegen_utils/symbol_names.rs | 8 +- .../symbol_names/dump.rs | 540 ++++++++++++++++++ src/librustc_codegen_utils/symbol_names/mw.rs | 344 +++++++++++ src/tools/tidy/src/extdeps.rs | 8 + 6 files changed, 930 insertions(+), 1 deletion(-) create mode 100644 src/librustc_codegen_utils/symbol_names/dump.rs create mode 100644 src/librustc_codegen_utils/symbol_names/mw.rs diff --git a/Cargo.lock b/Cargo.lock index 319a877d97076..0847f5b632003 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2371,6 +2371,11 @@ dependencies = [ "rustc-std-workspace-core 1.0.0", ] +[[package]] +name = "rustc-demangle" +version = "0.1.13" +source = "git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7#20d5bcc9bcea0d9413540916dd5f9fdadc7012f7" + [[package]] name = "rustc-hash" version = "1.0.1" @@ -2531,11 +2536,13 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "punycode 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc-demangle 0.1.13 (git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7)", "rustc_data_structures 0.0.0", "rustc_incremental 0.0.0", "rustc_metadata 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", + "std-mangle-rs 0.1.0 (git+https://github.com/michaelwoerister/std-mangle-rs?rev=2336dcdfcc91db3cdda18eda73aca488773ac6fc)", "syntax 0.0.0", "syntax_pos 0.0.0", ] @@ -3095,6 +3102,14 @@ dependencies = [ "unwind 0.0.0", ] +[[package]] +name = "std-mangle-rs" +version = "0.1.0" +source = "git+https://github.com/michaelwoerister/std-mangle-rs?rev=2336dcdfcc91db3cdda18eda73aca488773ac6fc#2336dcdfcc91db3cdda18eda73aca488773ac6fc" +dependencies = [ + "unic-idna-punycode 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "string_cache" version = "0.7.3" @@ -3554,6 +3569,11 @@ name = "ucd-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unic-idna-punycode" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -3987,6 +4007,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc-ap-syntax 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1adc189e5e4500a4167b9afa04e67067f40d0039e0e05870c977bebb561f065a" "checksum rustc-ap-syntax_pos 306.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d42c430dbb0be4377bfe6aa5099074c63ac8796b24098562c2e2154aecc5652" "checksum rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "82ae957aa1b3055d8e086486723c0ccd3d7b8fa190ae8fa2e35543b6171c810e" +"checksum rustc-demangle 0.1.13 (git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7)" = "" "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" "checksum rustc-rayon 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6d5a683c6ba4ed37959097e88d71c9e8e26659a3cb5be8b389078e7ad45306" "checksum rustc-rayon-core 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40f06724db71e18d68b3b946fdf890ca8c921d9edccc1404fdfdb537b0d12649" @@ -4014,6 +4035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" +"checksum std-mangle-rs 0.1.0 (git+https://github.com/michaelwoerister/std-mangle-rs?rev=2336dcdfcc91db3cdda18eda73aca488773ac6fc)" = "" "checksum string_cache 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "25d70109977172b127fe834e5449e5ab1740b9ba49fa18a2020f509174f25423" "checksum string_cache_codegen 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "35293b05cf1494e8ddd042a7df6756bf18d07f42d234f32e71dce8a7aabb0191" "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc" @@ -4051,6 +4073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum toml-query 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6854664bfc6df0360c695480836ee90e2d0c965f06db291d10be9344792d43e8" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum unic-idna-punycode 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1b0366615c248bc56ea5ceafe6f71a682f6591e653b1ce61814999302617b8c0" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" "checksum unicode-segmentation 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aa6024fc12ddfd1c6dbc14a80fa2324d4568849869b779f6bd37e5e4c03344d1" diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index 9794d4c0c9041..5339cd07c9a63 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -22,3 +22,11 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } rustc_incremental = { path = "../librustc_incremental" } + +[dependencies.std-mangle-rs] +git = "https://github.com/michaelwoerister/std-mangle-rs" +rev = "2336dcdfcc91db3cdda18eda73aca488773ac6fc" + +[dependencies.rustc-demangle] +git = "https://github.com/eddyb/rustc-demangle" +rev = "20d5bcc9bcea0d9413540916dd5f9fdadc7012f7" diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 01f45600a733a..5a55fe99b0255 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -106,6 +106,8 @@ use syntax_pos::symbol::Symbol; use std::fmt::{self, Write}; use std::mem::{self, discriminant}; +mod dump; +mod mw; mod new; pub fn provide(providers: &mut Providers) { @@ -338,7 +340,11 @@ fn compute_mangled_symbol_name(tcx: TyCtxt<'_, 'tcx, 'tcx>, instance: Instance<' sanitize(&mut buf.temp_buf, "{{vtable-shim}}"); } - buf.finish(hash) + let mangled_symbol = buf.finish(hash); + + return dump::record(tcx, instance, &mangled_symbol, hash); + + // mangled_symbol } // Follow C++ namespace-mangling style, see diff --git a/src/librustc_codegen_utils/symbol_names/dump.rs b/src/librustc_codegen_utils/symbol_names/dump.rs new file mode 100644 index 0000000000000..f284dcb535a68 --- /dev/null +++ b/src/librustc_codegen_utils/symbol_names/dump.rs @@ -0,0 +1,540 @@ +extern crate rustc_demangle; + +use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::print::{PrettyPrinter, Printer, Print}; +use rustc::ty::subst::{Kind, Subst, UnpackedKind}; +use rustc_mir::monomorphize::Instance; + +use std::cell::RefCell; +use std::fmt::{self, Write as FmtWrite}; +use std::fs::{self, File}; +use std::io::Write; +use std::ops::Range; +use std::path::PathBuf; +use std::time::SystemTime; + +use symbol_names::{self as old, mw, new}; + +thread_local!(static OUT_DIR: Option = { + std::env::var_os("RUST_SYMBOL_DUMP_DIR").map(PathBuf::from) +}); +thread_local!(static OUTPUT: RefCell> = RefCell::new(None)); + +pub fn record( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + instance: Instance<'tcx>, + old_mangling: &str, + old_hash: u64, +) -> String { + let header = "old+generics,old,mw,mw+compression,new,new+compression"; + + // Always compute all forms of mangling. + let def_id = instance.def_id(); + // FIXME(eddyb) this should ideally not be needed. + let substs = + tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), instance.substs); + + let old_mangling_plus_generics = { + let mut symbol_path = old::SymbolPrinter { + tcx, + path: old::SymbolPath::new(), + keep_within_component: false, + }.print_def_path(def_id, substs).unwrap().path; + + if instance.is_vtable_shim() { + symbol_path.finalize_pending_component(); + old::sanitize(&mut symbol_path.temp_buf, "{{vtable-shim}}"); + } + + symbol_path.finish(old_hash) + }; + + let (mw_mangling, mw_mangling_plus_compression) = mw::mangle(tcx, instance) + .unwrap_or((String::new(), String::new())); + let (new_mangling, new_mangling_plus_compression) = new::mangle(tcx, instance); + + OUTPUT.with(|out| { + let mut out = out.borrow_mut(); + if out.is_none() { + OUT_DIR.with(|out_dir| { + if let Some(out_dir) = out_dir { + let mut opts = fs::OpenOptions::new(); + opts.write(true).create_new(true); + + let mut time = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .map(|d| d.as_secs()) + .unwrap_or(0); + let mut file = loop { + let file_path = out_dir.join(format!("{}-{}.{}.csv", + tcx.crate_name, + tcx.sess.local_crate_disambiguator(), + time, + )); + + match opts.open(&file_path) { + Ok(file) => break file, + Err(e) => { + if e.kind() == std::io::ErrorKind::AlreadyExists { + time += 1; + continue; + } + bug!("can't open symbol dump file `{}`: {:?}", + file_path.display(), e); + } + } + }; + writeln!(file, "{}", header).unwrap(); + *out = Some(file); + } + }) + } + + if let Some(out) = out.as_mut() { + writeln!(out, "{},{},{},{},{},{}", + old_mangling_plus_generics, + old_mangling, + mw_mangling, + mw_mangling_plus_compression, + new_mangling, + new_mangling_plus_compression, + ).unwrap(); + } + }); + + // Build the expected output of demangling, via `ty::print`. + let make_expected_demangling = |alternate| { + let cx = DemanglingPrinter { + tcx, + out: String::new(), + alternate, + in_value: true, + binders: vec![], + }; + if instance.is_vtable_shim() { + cx.path_append_ns( + |cx| cx.print_def_path(def_id, substs), + 'S', + 0, + "", + ).unwrap().out + } else { + cx.print_def_path(def_id, substs).unwrap().out + } + }; + let expected_demangling_alt = make_expected_demangling(true); + let expected_demangling = make_expected_demangling(false); + + for mangling in &[&new_mangling, &new_mangling_plus_compression] { + match rustc_demangle::try_demangle(mangling) { + Ok(demangling) => { + let demangling_alt = format!("{:#}", demangling); + if demangling_alt.contains('?') { + bug!("demangle(alt) printing failed for {:?}\n{:?}", mangling, demangling_alt); + } + assert_eq!(demangling_alt, expected_demangling_alt); + + let demangling = format!("{}", demangling); + if demangling.contains('?') { + bug!("demangle printing failed for {:?}\n{:?}", mangling, demangling); + } + assert_eq!(demangling, expected_demangling); + } + Err(_) => bug!("try_demangle failed for {:?}", mangling), + } + } + + new_mangling_plus_compression +} + +struct BinderLevel { + lifetime_depths: Range, +} + +// Our expectation of the output of demangling, +// relying on `ty::print` / `PrettyPrinter`. +struct DemanglingPrinter<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + out: String, + + /// Equivalent to `rustc-demangle`'s `{:#}` printing. + alternate: bool, + + in_value: bool, + binders: Vec, +} + +impl fmt::Write for DemanglingPrinter<'_, '_> { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.out.write_str(s) + } +} + +impl DemanglingPrinter<'_, '_> { + fn path_append_ns( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + ns: char, + disambiguator: u64, + name: &str, + ) -> Result { + self = print_prefix(self)?; + self.write_str("::")?; + + if let 'A'..='Z' = ns { + self.write_str("{")?; + match ns { + 'C' => self.write_str("closure")?, + 'S' => self.write_str("shim")?, + _ => write!(self, "{}", ns)?, + } + if !name.is_empty() { + write!(self, ":{}", name)?; + } + write!(self, "#{}", disambiguator)?; + self.write_str("}")?; + } else { + self.write_str(&name)?; + } + + Ok(self) + } + + fn print_lifetime_at_depth(&mut self, depth: u64) -> Result<(), fmt::Error> { + if depth < 26 { + write!(self, "'{}", (b'a' + depth as u8) as char) + } else { + write!(self, "'_{}", depth) + } + } +} + +impl Printer<'tcx, 'tcx> for DemanglingPrinter<'_, 'tcx> { + type Error = fmt::Error; + + type Path = Self; + type Region = Self; + type Type = Self; + type DynExistential = Self; + + fn tcx(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx + } + + fn print_impl_path( + self, + impl_def_id: DefId, + substs: &'tcx [Kind<'tcx>], + mut self_ty: Ty<'tcx>, + mut impl_trait_ref: Option>, + ) -> Result { + let mut param_env = self.tcx.param_env(impl_def_id) + .with_reveal_all(); + if !substs.is_empty() { + param_env = param_env.subst(self.tcx, substs); + } + + match &mut impl_trait_ref { + Some(impl_trait_ref) => { + assert_eq!(impl_trait_ref.self_ty(), self_ty); + *impl_trait_ref = + self.tcx.normalize_erasing_regions(param_env, *impl_trait_ref); + self_ty = impl_trait_ref.self_ty(); + } + None => { + self_ty = self.tcx.normalize_erasing_regions(param_env, self_ty); + } + } + + self.path_qualified(self_ty, impl_trait_ref) + } + + fn print_region( + mut self, + region: ty::Region<'_>, + ) -> Result { + match *region { + ty::ReErased => write!(self, "'_")?, + + ty::ReLateBound(debruijn, ty::BrAnon(i)) => { + let binder = &self.binders[self.binders.len() - 1 - debruijn.index()]; + let depth = binder.lifetime_depths.start + i; + self.print_lifetime_at_depth(depth as u64)?; + } + + _ => bug!("symbol_names::dump: non-erased region `{:?}`", region), + } + + Ok(self) + } + + fn print_type( + mut self, + ty: Ty<'tcx>, + ) -> Result { + match ty.sty { + // Mangled as paths (unlike `pretty_print_type`). + ty::FnDef(def_id, substs) | + ty::Opaque(def_id, substs) | + ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::Closure(def_id, ty::ClosureSubsts { substs }) | + ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + self.print_def_path(def_id, substs) + } + + // Mangled as placeholders. + ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | + ty::Infer(_) | ty::Error => { + write!(self, "_")?; + Ok(self) + } + + // Demangled with explicit type for constants (`len` here). + ty::Array(ty, len) if !self.alternate => { + write!(self, "[")?; + self = ty.print(self)?; + write!(self, "; ")?; + match len { + ty::LazyConst::Unevaluated(_def_id, _substs) => { + write!(self, "_")?; + } + ty::LazyConst::Evaluated(c) => { + write!(self, "{}", c.unwrap_usize(self.tcx))?; + } + } + write!(self, ": usize]")?; + Ok(self) + } + + // Demangled without anyparens. + ty::Dynamic(data, r) => { + let print_r = self.region_should_not_be_omitted(r); + write!(self, "dyn ")?; + self = data.print(self)?; + if print_r { + write!(self, " + ")?; + self = r.print(self)?; + } + Ok(self) + } + + _ => self.pretty_print_type(ty), + } + } + + fn print_dyn_existential( + mut self, + predicates: &'tcx ty::List>, + ) -> Result { + // Generate the main trait ref, including associated types. + let mut first = true; + + if let Some(principal) = predicates.principal() { + self = self.print_def_path(principal.def_id, &[])?; + + // Use a type that can't appear in defaults of type parameters. + let dummy_self = self.tcx().mk_infer(ty::FreshTy(0)); + let principal = principal.with_self_ty(self.tcx(), dummy_self); + + let args = self.generic_args_to_print( + self.tcx().generics_of(principal.def_id), + principal.substs, + ); + + // Don't print any regions if they're all erased. + let print_regions = args.iter().any(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + let mut args = args.iter().cloned().filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + let mut projections = predicates.projection_bounds(); + + let arg0 = args.next(); + let projection0 = projections.next(); + if arg0.is_some() || projection0.is_some() { + let args = arg0.into_iter().chain(args); + let projections = projection0.into_iter().chain(projections); + + self = self.generic_delimiters(|mut cx| { + cx = cx.comma_sep(args)?; + if arg0.is_some() && projection0.is_some() { + write!(cx, ", ")?; + } + cx.comma_sep(projections) + })?; + } + first = false; + } + + for def_id in predicates.auto_traits() { + if !first { + write!(self, " + ")?; + } + first = false; + + self = self.print_def_path(def_id, &[])?; + } + + Ok(self) + } + + fn path_crate( + mut self, + cnum: CrateNum, + ) -> Result { + self.write_str(&self.tcx.original_crate_name(cnum).as_str())?; + let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint(); + if !self.alternate { + write!(self, "[{:x}]", fingerprint.to_smaller_hash())?; + } + Ok(self) + } + fn path_qualified( + self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + self.generic_delimiters(|mut cx| { + cx = self_ty.print(cx)?; + if let Some(trait_ref) = trait_ref { + write!(cx, " as ")?; + cx = trait_ref.print(cx)?; + } + Ok(cx) + }) + } + + fn path_append_impl( + self, + _print_prefix: impl FnOnce(Self) -> Result, + _disambiguated_data: &DisambiguatedDefPathData, + _self_ty: Ty<'tcx>, + _trait_ref: Option>, + ) -> Result { + unreachable!() + } + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + ) -> Result { + let ns = match disambiguated_data.data { + DefPathData::StructCtor => return print_prefix(self), + DefPathData::ClosureExpr => 'C', + _ => '_', + }; + + let name = disambiguated_data.data.get_opt_name().map(|s| s.as_str()); + let name = name.as_ref().map_or("", |s| &s[..]); + + self.path_append_ns( + print_prefix, + ns, + disambiguated_data.disambiguator as u64, + name, + ) + } + fn path_generic_args( + mut self, + print_prefix: impl FnOnce(Self) -> Result, + args: &[Kind<'tcx>], + ) -> Result { + self = print_prefix(self)?; + + // Don't print any regions if they're all erased. + let print_regions = args.iter().any(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + let args = args.iter().cloned().filter(|arg| { + match arg.unpack() { + UnpackedKind::Lifetime(_) => print_regions, + _ => true, + } + }); + + if args.clone().next().is_some() { + if self.in_value { + write!(self, "::")?; + } + self.generic_delimiters(|cx| cx.comma_sep(args)) + } else { + Ok(self) + } + } +} + +impl PrettyPrinter<'tcx, 'tcx> for DemanglingPrinter<'_, 'tcx> { + fn region_should_not_be_omitted( + &self, + region: ty::Region<'_>, + ) -> bool { + *region != ty::ReErased + } + + fn generic_delimiters( + mut self, + f: impl FnOnce(Self) -> Result, + ) -> Result { + write!(self, "<")?; + let was_in_value = ::std::mem::replace(&mut self.in_value, false); + self = f(self)?; + self.in_value = was_in_value; + write!(self, ">")?; + Ok(self) + } + + fn in_binder( + mut self, + value: &ty::Binder, + ) -> Result + where T: Print<'tcx, 'tcx, Self, Output = Self, Error = Self::Error> + TypeFoldable<'tcx> + { + let regions = if value.has_late_bound_regions() { + self.tcx.collect_referenced_late_bound_regions(value) + } else { + Default::default() + }; + + let mut lifetime_depths = + self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i); + + let lifetimes = regions.into_iter().map(|br| { + match br { + ty::BrAnon(i) => i + 1, + _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value), + } + }).max().unwrap_or(0); + + lifetime_depths.end += lifetimes; + + if lifetimes > 0 { + write!(self, "for<")?; + for i in lifetime_depths.clone() { + if i > lifetime_depths.start { + write!(self, ", ")?; + } + self.print_lifetime_at_depth(i as u64)?; + } + write!(self, "> ")?; + } + + self.binders.push(BinderLevel { lifetime_depths }); + self = value.skip_binder().print(self)?; + self.binders.pop(); + + Ok(self) + } +} diff --git a/src/librustc_codegen_utils/symbol_names/mw.rs b/src/librustc_codegen_utils/symbol_names/mw.rs new file mode 100644 index 0000000000000..f203ad9ff7828 --- /dev/null +++ b/src/librustc_codegen_utils/symbol_names/mw.rs @@ -0,0 +1,344 @@ +extern crate std_mangle_rs as mw_mangle; +use self::mw_mangle::{ast, compress::compress_ext}; + +use rustc::hir; +use rustc::hir::def_id::{CrateNum, DefId}; +use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::print::{Printer, Print}; +use rustc::ty::subst::{Kind, UnpackedKind}; +use rustc_data_structures::base_n; +use rustc_mir::monomorphize::Instance; +use rustc_target::spec::abi::Abi; +use syntax::ast::{IntTy, UintTy, FloatTy}; + +use std::sync::Arc; + +pub(super) struct Unsupported; + +pub(super) fn mangle( + tcx: TyCtxt<'_, 'tcx, 'tcx>, + instance: Instance<'tcx>, +) -> Result<(String, String), Unsupported> { + if instance.is_vtable_shim() { + return Err(Unsupported); + } + + let instantiating_crate = super::instantiating_crate(tcx, instance); + let symbol = ast::Symbol { + name: SymbolPrinter { tcx } + .print_def_path(instance.def_id(), instance.substs)?, + instantiating_crate: instantiating_crate.map(|instantiating_crate| { + let fingerprint = tcx.crate_disambiguator(instantiating_crate).to_fingerprint(); + Arc::new(ast::PathPrefix::CrateId { + name: tcx.original_crate_name(instantiating_crate).to_string(), + dis: base_n::encode(fingerprint.to_smaller_hash() as u128, 62), + }) + }), + }; + + let mut uncompressed = String::new(); + symbol.mangle(&mut uncompressed); + + let (compressed_symbol, _) = compress_ext(&symbol); + let mut compressed = String::new(); + compressed_symbol.mangle(&mut compressed); + + Ok((uncompressed, compressed)) +} + +#[derive(Copy, Clone)] +struct SymbolPrinter<'a, 'tcx> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, +} + +impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { + type Error = Unsupported; + + type Path = Arc; + type Region = !; + type Type = Arc; + type DynExistential = !; + + fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> { + self.tcx + } + + fn print_impl_path( + self, + impl_def_id: DefId, + _substs: &[Kind<'tcx>], + self_ty: Ty<'tcx>, + impl_trait_ref: Option>, + ) -> Result { + let key = self.tcx.def_key(impl_def_id); + let parent_def_id = DefId { index: key.parent.unwrap(), ..impl_def_id }; + + self.path_append_impl( + |cx| cx.print_def_path(parent_def_id, &[]), + &key.disambiguated_data, + self_ty, + impl_trait_ref, + ) + } + + fn print_region( + self, + _region: ty::Region<'_>, + ) -> Result { + bug!("mw::print_region: should never be called") + } + + fn print_type( + self, + ty: Ty<'tcx>, + ) -> Result { + macro_rules! basic { + ($name:ident) => (ast::Type::BasicType(ast::BasicType::$name)) + } + Ok(Arc::new(match ty.sty { + ty::Bool => basic!(Bool), + ty::Char => basic!(Char), + ty::Str => basic!(Str), + ty::Tuple(_) if ty.is_unit() => basic!(Unit), + ty::Int(IntTy::I8) => basic!(I8), + ty::Int(IntTy::I16) => basic!(I16), + ty::Int(IntTy::I32) => basic!(I32), + ty::Int(IntTy::I64) => basic!(I64), + ty::Int(IntTy::I128) => basic!(I128), + ty::Int(IntTy::Isize) => basic!(Isize), + ty::Uint(UintTy::U8) => basic!(U8), + ty::Uint(UintTy::U16) => basic!(U16), + ty::Uint(UintTy::U32) => basic!(U32), + ty::Uint(UintTy::U64) => basic!(U64), + ty::Uint(UintTy::U128) => basic!(U128), + ty::Uint(UintTy::Usize) => basic!(Usize), + ty::Float(FloatTy::F32) => basic!(F32), + ty::Float(FloatTy::F64) => basic!(F64), + ty::Never => basic!(Never), + + ty::Ref(_, ty, hir::MutImmutable) => ast::Type::Ref(ty.print(self)?), + ty::Ref(_, ty, hir::MutMutable) => ast::Type::RefMut(ty.print(self)?), + + ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::MutImmutable }) => { + ast::Type::RawPtrConst(ty.print(self)?) + } + ty::RawPtr(ty::TypeAndMut { ty, mutbl: hir::MutMutable }) => { + ast::Type::RawPtrMut(ty.print(self)?) + } + + ty::Array(ty, len) => { + let len = match len { + ty::LazyConst::Unevaluated(..) => return Err(Unsupported), + ty::LazyConst::Evaluated(c) => c.unwrap_usize(self.tcx), + }; + ast::Type::Array(Some(len), ty.print(self)?) + } + ty::Slice(ty) => ast::Type::Array(None, ty.print(self)?), + + ty::Tuple(tys) => { + let tys = tys.iter() + .map(|ty| ty.print(self)) + .collect::, _>>()?; + ast::Type::Tuple(tys) + } + + // Mangle all nominal types as paths. + ty::Adt(&ty::AdtDef { did: def_id, .. }, substs) | + ty::FnDef(def_id, substs) | + ty::Opaque(def_id, substs) | + ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | + ty::Closure(def_id, ty::ClosureSubsts { substs }) | + ty::Generator(def_id, ty::GeneratorSubsts { substs }, _) => { + ast::Type::Named(self.print_def_path(def_id, substs)?) + } + ty::Foreign(def_id) => { + ast::Type::Named(self.print_def_path(def_id, &[])?) + } + + ty::Param(p) => ast::Type::GenericParam(ast::Ident { + ident: p.name.to_string(), + tag: ast::IdentTag::TypeNs, + dis: ast::NumericDisambiguator(0), + }), + + ty::FnPtr(sig) => { + let mut params = sig.inputs().skip_binder().iter() + .map(|ty| ty.print(self)) + .collect::, _>>()?; + if sig.variadic() { + params.push(Arc::new(basic!(Ellipsis))); + } + let output = *sig.output().skip_binder(); + let return_type = if output.is_unit() { + None + } else { + Some(output.print(self)?) + }; + ast::Type::Fn { + is_unsafe: sig.unsafety() == hir::Unsafety::Unsafe, + abi: match sig.abi() { + Abi::Rust => ast::Abi::Rust, + Abi::C => ast::Abi::C, + _ => return Err(Unsupported), + }, + params, + return_type, + } + } + + _ => return Err(Unsupported), + })) + } + + fn print_dyn_existential( + self, + _predicates: &'tcx ty::List>, + ) -> Result { + Err(Unsupported) + } + + fn path_crate( + self, + cnum: CrateNum, + ) -> Result { + let path = ast::PathPrefix::CrateId { + name: self.tcx.original_crate_name(cnum).to_string(), + dis: self.tcx.crate_disambiguator(cnum).to_string(), + }; + Ok(Arc::new(ast::AbsolutePath::Path { + name: Arc::new(path), + args: ast::GenericArgumentList::new_empty(), + })) + } + fn path_qualified( + self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + assert!(trait_ref.is_some()); + let trait_ref = trait_ref.unwrap(); + + // This is a default method in the trait declaration. + // HACK(eddyb) this uses disambiguator 0 while actual impls have + // their disambiguator incremented by 1 (see `path_append_impl`). + let path = ast::PathPrefix::TraitImpl { + self_type: self_ty.print(self)?, + impled_trait: Some(self.print_def_path(trait_ref.def_id, trait_ref.substs)?), + dis: ast::NumericDisambiguator(0), + }; + Ok(Arc::new(ast::AbsolutePath::Path { + name: Arc::new(path), + args: ast::GenericArgumentList::new_empty(), + })) + } + + fn path_append_impl( + self, + _print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Result { + let path = ast::PathPrefix::TraitImpl { + self_type: self_ty.print(self)?, + impled_trait: match trait_ref { + Some(trait_ref) => Some( + self.print_def_path(trait_ref.def_id, trait_ref.substs)? + ), + None => None, + }, + // See `path_qualified` above for why `1 +`. + dis: ast::NumericDisambiguator(1 + disambiguated_data.disambiguator as u64), + }; + Ok(Arc::new(ast::AbsolutePath::Path { + name: Arc::new(path), + args: ast::GenericArgumentList::new_empty(), + })) + } + fn path_append( + self, + print_prefix: impl FnOnce(Self) -> Result, + disambiguated_data: &DisambiguatedDefPathData, + ) -> Result { + let mut path = print_prefix(self)?; + + let (prefix, ast_args) = match Arc::make_mut(&mut path) { + ast::AbsolutePath::Path { name, args } => (name, args), + _ => unreachable!(), + }; + + let tag = match disambiguated_data.data { + DefPathData::StructCtor => { + let ident = match Arc::make_mut(prefix) { + ast::PathPrefix::Node { ident, .. } => ident, + _ => unreachable!(), + }; + ident.tag = ast::IdentTag::ValueNs; + return Ok(path); + } + + DefPathData::ClosureExpr => ast::IdentTag::Closure, + + DefPathData::ValueNs(..) | + DefPathData::EnumVariant(..) | + DefPathData::Field(..) => ast::IdentTag::ValueNs, + + _ => ast::IdentTag::TypeNs, + }; + + let ident = match tag { + ast::IdentTag::Closure => String::new(), + _ => disambiguated_data.data.get_opt_name().ok_or(Unsupported)?.to_string(), + }; + + let dis = ast::NumericDisambiguator(disambiguated_data.disambiguator as u64); + + let prefix = if !ast_args.is_empty() { + Arc::new(ast::PathPrefix::AbsolutePath { path }) + } else { + prefix.clone() + }; + + Ok(Arc::new(ast::AbsolutePath::Path { + name: Arc::new(ast::PathPrefix::Node { + prefix: prefix.clone(), + ident: ast::Ident { ident, tag, dis }, + }), + args: ast::GenericArgumentList::new_empty(), + })) + } + fn path_generic_args( + self, + print_prefix: impl FnOnce(Self) -> Result, + args: &[Kind<'tcx>], + ) -> Result { + let mut path = print_prefix(self)?; + + if args.is_empty() { + return Ok(path); + } + + let ast_args = match Arc::make_mut(&mut path) { + ast::AbsolutePath::Path { args, .. } => args, + _ => unreachable!(), + }; + + if !ast_args.is_empty() { + bug!("mw::path_generic_args({:?}): prefix already has generic args: {:#?}", + args, path); + } + + for &arg in args { + match arg.unpack() { + UnpackedKind::Lifetime(_) => {} + UnpackedKind::Type(ty) => { + ast_args.0.push(ty.print(self)?); + } + } + } + + Ok(path) + } +} diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index 52e263df5e3d3..eac73271f16bd 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -6,6 +6,14 @@ use std::path::Path; /// List of whitelisted sources for packages. const WHITELISTED_SOURCES: &[&str] = &[ "\"registry+https://github.com/rust-lang/crates.io-index\"", + + "\"git+https://github.com/michaelwoerister/std-mangle-rs?\ + rev=2336dcdfcc91db3cdda18eda73aca488773ac6fc#\ + 2336dcdfcc91db3cdda18eda73aca488773ac6fc\"", + + "\"git+https://github.com/eddyb/rustc-demangle?\ + rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7#\ + 20d5bcc9bcea0d9413540916dd5f9fdadc7012f7\"", ]; /// Checks for external package sources. From bfb78ea92c43f4ef0768445a49e976b9c70ebba4 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Jan 2019 09:18:40 +0200 Subject: [PATCH 68/68] test: update to the new mangling scheme. --- Cargo.lock | 14 +++++++------- src/librustc_codegen_llvm/Cargo.toml | 7 ++++++- src/librustc_codegen_ssa/Cargo.toml | 7 ++++++- src/libstd/Cargo.toml | 8 +++++++- src/test/codegen/drop.rs | 18 +++++++++--------- src/test/codegen/external-no-mangle-fns.rs | 4 +++- src/test/codegen/external-no-mangle-statics.rs | 4 +++- src/test/codegen/internalize-closures.rs | 4 +++- src/test/codegen/link-dead-code.rs | 12 +++++++++--- .../local-generics-in-exe-internalized.rs | 4 +++- src/test/codegen/target-cpu-on-functions.rs | 4 +++- src/test/run-pass/backtrace.rs | 15 ++++++++++++++- src/test/ui/symbol-names/basic.rs | 2 +- src/test/ui/symbol-names/basic.stderr | 4 ++-- src/test/ui/symbol-names/impl1.rs | 6 ++++-- src/test/ui/symbol-names/impl1.stderr | 14 +++++++------- 16 files changed, 87 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0847f5b632003..5411b1388cd26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2366,15 +2366,15 @@ dependencies = [ name = "rustc-demangle" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-std-workspace-core 1.0.0", -] [[package]] name = "rustc-demangle" version = "0.1.13" source = "git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7#20d5bcc9bcea0d9413540916dd5f9fdadc7012f7" +dependencies = [ + "compiler_builtins 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-std-workspace-core 1.0.0", +] [[package]] name = "rustc-hash" @@ -2497,7 +2497,7 @@ dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7)", "rustc_llvm 0.0.0", ] @@ -2513,7 +2513,7 @@ dependencies = [ "memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7)", "rustc_allocator 0.0.0", "rustc_apfloat 0.0.0", "rustc_codegen_utils 0.0.0", @@ -3094,7 +3094,7 @@ dependencies = [ "panic_unwind 0.0.0", "profiler_builtins 0.0.0", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (git+https://github.com/eddyb/rustc-demangle?rev=20d5bcc9bcea0d9413540916dd5f9fdadc7012f7)", "rustc_asan 0.0.0", "rustc_lsan 0.0.0", "rustc_msan 0.0.0", diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index b711502b14b7f..1527c529a61bf 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -12,10 +12,15 @@ test = false [dependencies] cc = "1.0.1" num_cpus = "1.0" -rustc-demangle = "0.1.4" +# rustc-demangle = "0.1.4" rustc_llvm = { path = "../librustc_llvm" } memmap = "0.6" +# HACK(eddyb) temporary until upstreaming support for the new mangling scheme +[dependencies.rustc-demangle] +git = "https://github.com/eddyb/rustc-demangle" +rev = "20d5bcc9bcea0d9413540916dd5f9fdadc7012f7" + [features] # This is used to convince Cargo to separately cache builds of `rustc_codegen_llvm` # when this option is enabled or not. That way we can build two, cache two diff --git a/src/librustc_codegen_ssa/Cargo.toml b/src/librustc_codegen_ssa/Cargo.toml index 50994497c2843..90d9a5ee49b55 100644 --- a/src/librustc_codegen_ssa/Cargo.toml +++ b/src/librustc_codegen_ssa/Cargo.toml @@ -13,7 +13,7 @@ test = false bitflags = "1.0.4" cc = "1.0.1" num_cpus = "1.0" -rustc-demangle = "0.1.4" +# rustc-demangle = "0.1.4" memmap = "0.6" log = "0.4.5" libc = "0.2.44" @@ -32,3 +32,8 @@ rustc_fs_util = { path = "../librustc_fs_util" } rustc_incremental = { path = "../librustc_incremental" } rustc_mir = { path = "../librustc_mir" } rustc_target = { path = "../librustc_target" } + +# HACK(eddyb) temporary until upstreaming support for the new mangling scheme +[dependencies.rustc-demangle] +git = "https://github.com/eddyb/rustc-demangle" +rev = "20d5bcc9bcea0d9413540916dd5f9fdadc7012f7" diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml index 92876f7f2d804..94fd45654d239 100644 --- a/src/libstd/Cargo.toml +++ b/src/libstd/Cargo.toml @@ -21,9 +21,15 @@ libc = { version = "0.2.44", default-features = false, features = ['rustc-dep-of compiler_builtins = { version = "0.1.1" } profiler_builtins = { path = "../libprofiler_builtins", optional = true } unwind = { path = "../libunwind" } -rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] } +# rustc-demangle = { version = "0.1.10", features = ['rustc-dep-of-std'] } backtrace-sys = { version = "0.1.24", features = ["rustc-dep-of-std"], optional = true } +# HACK(eddyb) temporary until upstreaming support for the new mangling scheme +[dependencies.rustc-demangle] +git = "https://github.com/eddyb/rustc-demangle" +rev = "20d5bcc9bcea0d9413540916dd5f9fdadc7012f7" +features = ['rustc-dep-of-std'] + [dev-dependencies] rand = "0.6.1" diff --git a/src/test/codegen/drop.rs b/src/test/codegen/drop.rs index 7e6f8eaaa30d2..860c913697712 100644 --- a/src/test/codegen/drop.rs +++ b/src/test/codegen/drop.rs @@ -19,15 +19,15 @@ pub fn droppy() { // that's one new drop call per call to possibly_unwinding(), and finally 3 drop calls for the // regular function exit. We used to have problems with quadratic growths of drop calls in such // functions. -// CHECK-NOT: invoke{{.*}}drop{{.*}}SomeUniqueName -// CHECK: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK-NOT: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName -// CHECK: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK: invoke{{.*}}drop{{.*}}SomeUniqueName -// CHECK: call{{.*}}drop{{.*}}SomeUniqueName -// CHECK-NOT: {{(call|invoke).*}}drop{{.*}}SomeUniqueName +// CHECK-NOT: ; invoke{{.*}}drop{{.*}}SomeUniqueName +// CHECK: ; call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: ; call{{.*}}drop{{.*}}SomeUniqueName +// CHECK-NOT: ; call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: ; invoke{{.*}}drop{{.*}}SomeUniqueName +// CHECK: ; call{{.*}}drop{{.*}}SomeUniqueName +// CHECK: ; invoke{{.*}}drop{{.*}}SomeUniqueName +// CHECK: ; call{{.*}}drop{{.*}}SomeUniqueName +// CHECK-NOT: ; {{(call|invoke).*}}drop{{.*}}SomeUniqueName // The next line checks for the } that ends the function definition // CHECK-LABEL: {{^[}]}} let _s = SomeUniqueName; diff --git a/src/test/codegen/external-no-mangle-fns.rs b/src/test/codegen/external-no-mangle-fns.rs index 79d5dc2400c40..902882144996f 100644 --- a/src/test/codegen/external-no-mangle-fns.rs +++ b/src/test/codegen/external-no-mangle-fns.rs @@ -33,7 +33,9 @@ const HIDDEN: () = { }; // The surrounding item should not accidentally become external -// CHECK: define internal{{.*}} void @_ZN22external_no_mangle_fns1x +// CHECK-LABEL: ; external_no_mangle_fns::x +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define internal #[inline(never)] fn x() { // CHECK: define void @g() diff --git a/src/test/codegen/external-no-mangle-statics.rs b/src/test/codegen/external-no-mangle-statics.rs index 2998000180edb..e44373926b76a 100644 --- a/src/test/codegen/external-no-mangle-statics.rs +++ b/src/test/codegen/external-no-mangle-statics.rs @@ -75,4 +75,6 @@ fn x() { #[no_mangle] pub static mut P: u8 = 0; } -// CHECK: define internal void @_ZN26external_no_mangle_statics1x{{.*$}} +// CHECK-LABEL: ; external_no_mangle_statics::x +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define internal diff --git a/src/test/codegen/internalize-closures.rs b/src/test/codegen/internalize-closures.rs index 3434820aa8a18..627ec9812e628 100644 --- a/src/test/codegen/internalize-closures.rs +++ b/src/test/codegen/internalize-closures.rs @@ -4,7 +4,9 @@ pub fn main() { // We want to make sure that closures get 'internal' linkage instead of // 'weak_odr' when they are not shared between codegen units - // CHECK: define internal {{.*}}_ZN20internalize_closures4main{{.*}}$u7b$$u7b$closure$u7d$$u7d$ + // CHECK-LABEL: ; internalize_closures::main::{closure#0} + // CHECK-NEXT: ; Function Attrs: + // CHECK-NEXT: define internal let c = |x:i32| { x + 1 }; let _ = c(1); } diff --git a/src/test/codegen/link-dead-code.rs b/src/test/codegen/link-dead-code.rs index cb3dd07a2a798..de5a237c5f8a3 100644 --- a/src/test/codegen/link-dead-code.rs +++ b/src/test/codegen/link-dead-code.rs @@ -5,12 +5,18 @@ // This test makes sure that, when -Clink-dead-code is specified, we generate // code for functions that would otherwise be skipped. -// CHECK-LABEL: define hidden i32 @_ZN14link_dead_code8const_fn +// CHECK-LABEL: ; link_dead_code::const_fn +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define hidden const fn const_fn() -> i32 { 1 } -// CHECK-LABEL: define hidden i32 @_ZN14link_dead_code9inline_fn +// CHECK-LABEL: ; link_dead_code::inline_fn +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define hidden #[inline] fn inline_fn() -> i32 { 2 } -// CHECK-LABEL: define hidden i32 @_ZN14link_dead_code10private_fn +// CHECK-LABEL: ; link_dead_code::private_fn +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define hidden fn private_fn() -> i32 { 3 } diff --git a/src/test/codegen/local-generics-in-exe-internalized.rs b/src/test/codegen/local-generics-in-exe-internalized.rs index 6bdbf92919389..89a9731e91a2d 100644 --- a/src/test/codegen/local-generics-in-exe-internalized.rs +++ b/src/test/codegen/local-generics-in-exe-internalized.rs @@ -2,7 +2,9 @@ // Check that local generics are internalized if they are in the same CGU -// CHECK: define internal {{.*}} @_ZN34local_generics_in_exe_internalized3foo{{.*}} +// CHECK-LABEL: ; local_generics_in_exe_internalized::foo:: +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define internal pub fn foo(x: T, y: T) -> (T, T) { (x, y) } diff --git a/src/test/codegen/target-cpu-on-functions.rs b/src/test/codegen/target-cpu-on-functions.rs index 5692dca1df5a2..aad6a187b6b82 100644 --- a/src/test/codegen/target-cpu-on-functions.rs +++ b/src/test/codegen/target-cpu-on-functions.rs @@ -13,7 +13,9 @@ pub extern fn exported() { not_exported(); } -// CHECK-LABEL: define {{.*}} @_ZN23target_cpu_on_functions12not_exported{{.*}}() {{.*}} #0 +// CHECK-LABEL: ; target_cpu_on_functions::not_exported +// CHECK-NEXT: ; Function Attrs: +// CHECK-NEXT: define {{.*}}() {{.*}} #0 fn not_exported() {} // CHECK: attributes #0 = {{.*}} "target-cpu"="{{.*}}" diff --git a/src/test/run-pass/backtrace.rs b/src/test/run-pass/backtrace.rs index da3871aba095c..53d1ae844c985 100644 --- a/src/test/run-pass/backtrace.rs +++ b/src/test/run-pass/backtrace.rs @@ -41,6 +41,19 @@ fn expected(fn_name: &str) -> String { format!(" backtrace::{}", fn_name) } +fn contains_expected_full(s: &str, fn_name: &str) -> bool { + // HACK(eddyb) work around the fact that RUST_BACKTRACE=full + // (or, as is the case here, stack traces from panic-in-panic) + // prints symbols with hashes in them, i.e. `backtrace[...]::`. + let prefix = " backtrace["; + let suffix = &format!("]::{}", fn_name); + s.match_indices(prefix).any(|(i, _)| { + s[i + prefix.len()..] + .trim_start_matches(char::is_alphanumeric) + .starts_with(suffix) + }) +} + fn runtest(me: &str) { // Make sure that the stack trace is printed let p = template(me).arg("fail").env("RUST_BACKTRACE", "1").spawn().unwrap(); @@ -78,7 +91,7 @@ fn runtest(me: &str) { let s = str::from_utf8(&out.stderr).unwrap(); // loosened the following from double::h to double:: due to // spurious failures on mac, 32bit, optimized - assert!(s.contains("stack backtrace") && s.contains(&expected("double")), + assert!(s.contains("stack backtrace") && contains_expected_full(s, "double"), "bad output3: {}", s); // Make sure a stack trace isn't printed too many times diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs index 086b903b973b0..522ff764f40c0 100644 --- a/src/test/ui/symbol-names/basic.rs +++ b/src/test/ui/symbol-names/basic.rs @@ -1,6 +1,6 @@ #![feature(rustc_attrs)] -#[rustc_symbol_name] //~ ERROR _ZN5basic4main +#[rustc_symbol_name] //~ ERROR symbol-name(_RNaCs4fqI2P2rA04_5basic4main) #[rustc_def_path] //~ ERROR def-path(main) fn main() { } diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr index d0dda9062b2a8..d45246cd874d0 100644 --- a/src/test/ui/symbol-names/basic.stderr +++ b/src/test/ui/symbol-names/basic.stderr @@ -1,7 +1,7 @@ -error: symbol-name(_ZN5basic4main17h08bcaf310214ed52E) +error: symbol-name(_RNaCs4fqI2P2rA04_5basic4main) --> $DIR/basic.rs:3:1 | -LL | #[rustc_symbol_name] //~ ERROR _ZN5basic4main +LL | #[rustc_symbol_name] //~ ERROR symbol-name(_RNaCs4fqI2P2rA04_5basic4main) | ^^^^^^^^^^^^^^^^^^^^ error: def-path(main) diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index c712137e828f9..03a20dcdb3ed5 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -5,7 +5,8 @@ mod foo { pub struct Foo { x: u32 } impl Foo { - #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar + #[rustc_symbol_name] + //~^ ERROR symbol-name(_RNpMNdCs4fqI2P2rA04_5impl13fooNnB2_3Foo3bar) #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar) fn bar() { } } @@ -15,7 +16,8 @@ mod bar { use foo::Foo; impl Foo { - #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz + #[rustc_symbol_name] + //~^ ERROR symbol-name(_RNxMNoCs4fqI2P2rA04_5impl13barNnNdB4_3foo3Foo3baz) #[rustc_def_path] //~ ERROR def-path(bar::::baz) fn baz() { } } diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index 9c7a6f771528e..ebbf14a735579 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,23 +1,23 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) +error: symbol-name(_RNpMNdCs4fqI2P2rA04_5impl13fooNnB2_3Foo3bar) --> $DIR/impl1.rs:8:9 | -LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar +LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(foo::Foo::bar) - --> $DIR/impl1.rs:9:9 + --> $DIR/impl1.rs:10:9 | LL | #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar) | ^^^^^^^^^^^^^^^^^ -error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E) - --> $DIR/impl1.rs:18:9 +error: symbol-name(_RNxMNoCs4fqI2P2rA04_5impl13barNnNdB4_3foo3Foo3baz) + --> $DIR/impl1.rs:19:9 | -LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz +LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ error: def-path(bar::::baz) - --> $DIR/impl1.rs:19:9 + --> $DIR/impl1.rs:21:9 | LL | #[rustc_def_path] //~ ERROR def-path(bar::::baz) | ^^^^^^^^^^^^^^^^^

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { if cx.is_verbose { return true; } @@ -1032,28 +1025,28 @@ impl ty::RegionVid { } define_print! { - () ty::InferTy, (self, f, cx) { + () ty::InferTy, (self, cx) { display { if cx.is_verbose { - return self.print_debug(f, cx); + return self.print_debug(cx); } match *self { - ty::TyVar(_) => write!(f, "_"), - ty::IntVar(_) => write!(f, "{}", "{integer}"), - ty::FloatVar(_) => write!(f, "{}", "{float}"), - ty::FreshTy(v) => write!(f, "FreshTy({})", v), - ty::FreshIntTy(v) => write!(f, "FreshIntTy({})", v), - ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({})", v) + ty::TyVar(_) => print!(cx, write("_")), + ty::IntVar(_) => print!(cx, write("{}", "{integer}")), + ty::FloatVar(_) => print!(cx, write("{}", "{float}")), + ty::FreshTy(v) => print!(cx, write("FreshTy({})", v)), + ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({})", v)), + ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({})", v)) } } debug { match *self { - ty::TyVar(ref v) => write!(f, "{:?}", v), - ty::IntVar(ref v) => write!(f, "{:?}", v), - ty::FloatVar(ref v) => write!(f, "{:?}", v), - ty::FreshTy(v) => write!(f, "FreshTy({:?})", v), - ty::FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), - ty::FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) + ty::TyVar(ref v) => print!(cx, write("{:?}", v)), + ty::IntVar(ref v) => print!(cx, write("{:?}", v)), + ty::FloatVar(ref v) => print!(cx, write("{:?}", v)), + ty::FreshTy(v) => print!(cx, write("FreshTy({:?})", v)), + ty::FreshIntTy(v) => print!(cx, write("FreshIntTy({:?})", v)), + ty::FreshFloatTy(v) => print!(cx, write("FreshFloatTy({:?})", v)) } } } @@ -1081,7 +1074,7 @@ impl fmt::Debug for ty::FloatVarValue { for<'a> >::Lifted: fmt::Display + TypeFoldable<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(|cx| cx.in_binder(f, cx.tcx.lift(self) + PrintCx::with(|cx| cx.in_binder(cx.tcx.lift(self) .expect("could not lift for printing"))) } }*/ @@ -1097,134 +1090,129 @@ define_print_multi! { ('tcx) ty::Binder, ty::Region<'tcx>>>, ('tcx) ty::Binder, ty::Region<'tcx>>> ] - (self, f, cx) { + (self, cx) { display { - cx.in_binder(f, self) + cx.in_binder(self) } } } define_print! { - ('tcx) ty::TraitRef<'tcx>, (self, f, cx) { + ('tcx) ty::TraitRef<'tcx>, (self, cx) { display { - cx.parameterized(f, self.def_id, self.substs, iter::empty()) + cx.parameterized(self.def_id, self.substs, iter::empty()) } debug { - // when printing out the debug representation, we don't need - // to enumerate the `for<...>` etc because the debruijn index - // tells you everything you need to know. - print!(f, cx, - write("<"), - print(self.self_ty()), - write(" as "))?; - cx.parameterized(f, self.def_id, self.substs, iter::empty())?; - write!(f, ">") + print!(cx, write("<"), print(self.self_ty()), write(" as "))?; + cx.parameterized(self.def_id, self.substs, iter::empty())?; + print!(cx, write(">")) } } } define_print! { - ('tcx) ty::Ty<'tcx>, (self, f, cx) { + ('tcx) ty::Ty<'tcx>, (self, cx) { display { match self.sty { - Bool => write!(f, "bool"), - Char => write!(f, "char"), - Int(t) => write!(f, "{}", t.ty_to_string()), - Uint(t) => write!(f, "{}", t.ty_to_string()), - Float(t) => write!(f, "{}", t.ty_to_string()), + Bool => print!(cx, write("bool")), + Char => print!(cx, write("char")), + Int(t) => print!(cx, write("{}", t.ty_to_string())), + Uint(t) => print!(cx, write("{}", t.ty_to_string())), + Float(t) => print!(cx, write("{}", t.ty_to_string())), RawPtr(ref tm) => { - write!(f, "*{} ", match tm.mutbl { + print!(cx, write("*{} ", match tm.mutbl { hir::MutMutable => "mut", hir::MutImmutable => "const", - })?; - tm.ty.print(f, cx) + }))?; + tm.ty.print(cx) } Ref(r, ty, mutbl) => { - write!(f, "&")?; + print!(cx, write("&"))?; if r.display_outputs_anything(cx) { - print!(f, cx, print_display(r), write(" "))?; + print!(cx, print_display(r), write(" "))?; } - ty::TypeAndMut { ty, mutbl }.print(f, cx) + ty::TypeAndMut { ty, mutbl }.print(cx) } - Never => write!(f, "!"), + Never => print!(cx, write("!")), Tuple(ref tys) => { - write!(f, "(")?; + print!(cx, write("("))?; let mut tys = tys.iter(); if let Some(&ty) = tys.next() { - print!(f, cx, print(ty), write(","))?; + print!(cx, print(ty), write(","))?; if let Some(&ty) = tys.next() { - print!(f, cx, write(" "), print(ty))?; + print!(cx, write(" "), print(ty))?; for &ty in tys { - print!(f, cx, write(", "), print(ty))?; + print!(cx, write(", "), print(ty))?; } } } - write!(f, ")") + print!(cx, write(")")) } FnDef(def_id, substs) => { let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); - print!(f, cx, print(sig), write(" {{"))?; - cx.parameterized(f, def_id, substs, iter::empty())?; - write!(f, "}}") + print!(cx, print(sig), write(" {{"))?; + cx.parameterized(def_id, substs, iter::empty())?; + print!(cx, write("}}")) } FnPtr(ref bare_fn) => { - bare_fn.print(f, cx) + bare_fn.print(cx) } - Infer(infer_ty) => write!(f, "{}", infer_ty), - Error => write!(f, "[type error]"), - Param(ref param_ty) => write!(f, "{}", param_ty), + Infer(infer_ty) => print!(cx, write("{}", infer_ty)), + Error => print!(cx, write("[type error]")), + Param(ref param_ty) => print!(cx, write("{}", param_ty)), Bound(debruijn, bound_ty) => { match bound_ty.kind { ty::BoundTyKind::Anon => { if debruijn == ty::INNERMOST { - write!(f, "^{}", bound_ty.var.index()) + print!(cx, write("^{}", bound_ty.var.index())) } else { - write!(f, "^{}_{}", debruijn.index(), bound_ty.var.index()) + print!(cx, write("^{}_{}", debruijn.index(), bound_ty.var.index())) } } - ty::BoundTyKind::Param(p) => write!(f, "{}", p), + ty::BoundTyKind::Param(p) => print!(cx, write("{}", p)), } } - Adt(def, substs) => cx.parameterized(f, def.did, substs, iter::empty()), + Adt(def, substs) => cx.parameterized(def.did, substs, iter::empty()), Dynamic(data, r) => { let print_r = r.display_outputs_anything(cx); if print_r { - write!(f, "(")?; + print!(cx, write("("))?; } - write!(f, "dyn ")?; - data.print(f, cx)?; + print!(cx, write("dyn "))?; + data.print(cx)?; if print_r { - print!(f, cx, write(" + "), print_display(r), write(")"))?; + print!(cx, write(" + "), print_display(r), write(")"))?; } Ok(()) } - Foreign(def_id) => cx.parameterized(f, def_id, Substs::empty(), iter::empty()), - Projection(ref data) => data.print(f, cx), + Foreign(def_id) => cx.parameterized(def_id, Substs::empty(), iter::empty()), + Projection(ref data) => data.print(cx), UnnormalizedProjection(ref data) => { - write!(f, "Unnormalized(")?; - data.print(f, cx)?; - write!(f, ")") + print!(cx, write("Unnormalized("))?; + data.print(cx)?; + print!(cx, write(")")) } Placeholder(placeholder) => { - write!(f, "Placeholder({:?})", placeholder) + print!(cx, write("Placeholder({:?})", placeholder)) } Opaque(def_id, substs) => { if cx.is_verbose { - return write!(f, "Opaque({:?}, {:?})", def_id, substs); + return print!(cx, write("Opaque({:?}, {:?})", def_id, substs)); } let def_key = cx.tcx.def_key(def_id); if let Some(name) = def_key.disambiguated_data.data.get_opt_name() { - write!(f, "{}", name)?; + print!(cx, write("{}", name))?; let mut substs = substs.iter(); + // FIXME(eddyb) print this with `parameterized`. if let Some(first) = substs.next() { - write!(f, "::<")?; - write!(f, "{}", first)?; + print!(cx, write("::<"))?; + print!(cx, write("{}", first))?; for subst in substs { - write!(f, ", {}", subst)?; + print!(cx, write(", {}", subst))?; } - write!(f, ">")?; + print!(cx, write(">"))?; } return Ok(()); } @@ -1234,7 +1222,7 @@ define_print! { let mut first = true; let mut is_sized = false; - write!(f, "impl")?; + print!(cx, write("impl"))?; for predicate in bounds.predicates { if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { // Don't print +Sized, but rather +?Sized if absent. @@ -1243,35 +1231,36 @@ define_print! { continue; } - print!(f, cx, + print!(cx, write("{}", if first { " " } else { "+" }), print(trait_ref))?; first = false; } } if !is_sized { - write!(f, "{}?Sized", if first { " " } else { "+" })?; - } else if first { - write!(f, " Sized")?; + print!(cx, write("{}?Sized", if first { " " } else { "+" }))?; + } else if first { + print!(cx, write(" Sized"))?; } Ok(()) } - Str => write!(f, "str"), + Str => print!(cx, write("str")), Generator(did, substs, movability) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); let witness = substs.witness(did, cx.tcx); if movability == hir::GeneratorMovability::Movable { - write!(f, "[generator")?; + print!(cx, write("[generator"))?; } else { - write!(f, "[static generator")?; + print!(cx, write("[static generator"))?; } + // FIXME(eddyb) should use `def_span`. if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { - write!(f, "@{:?}", cx.tcx.hir().span(node_id))?; + print!(cx, write("@{:?}", cx.tcx.hir().span(node_id)))?; let mut sep = " "; cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - print!(f, cx, + print!(cx, write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), @@ -1283,35 +1272,36 @@ define_print! { } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. - write!(f, "@{:?}", did)?; + print!(cx, write("@{:?}", did))?; let mut sep = " "; for (index, upvar_ty) in upvar_tys.enumerate() { - print!(f, cx, + print!(cx, write("{}{}:", sep, index), print(upvar_ty))?; sep = ", "; } } - print!(f, cx, write(" "), print(witness), write("]")) + print!(cx, write(" "), print(witness), write("]")) }, GeneratorWitness(types) => { - cx.in_binder(f, &types) + cx.in_binder(&types) } Closure(did, substs) => { let upvar_tys = substs.upvar_tys(did, cx.tcx); - write!(f, "[closure")?; + print!(cx, write("[closure"))?; + // FIXME(eddyb) should use `def_span`. if let Some(node_id) = cx.tcx.hir().as_local_node_id(did) { if cx.tcx.sess.opts.debugging_opts.span_free_formats { - write!(f, "@{:?}", node_id)?; + print!(cx, write("@{:?}", node_id))?; } else { - write!(f, "@{:?}", cx.tcx.hir().span(node_id))?; + print!(cx, write("@{:?}", cx.tcx.hir().span(node_id)))?; } let mut sep = " "; cx.tcx.with_freevars(node_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - print!(f, cx, + print!(cx, write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), @@ -1323,48 +1313,48 @@ define_print! { } else { // cross-crate closure types should only be // visible in codegen bug reports, I imagine. - write!(f, "@{:?}", did)?; + print!(cx, write("@{:?}", did))?; let mut sep = " "; for (index, upvar_ty) in upvar_tys.enumerate() { - print!(f, cx, + print!(cx, write("{}{}:", sep, index), print(upvar_ty))?; sep = ", "; } } - write!(f, "]") + print!(cx, write("]")) }, Array(ty, sz) => { - print!(f, cx, write("["), print(ty), write("; "))?; + print!(cx, write("["), print(ty), write("; "))?; match sz { ty::LazyConst::Unevaluated(_def_id, _substs) => { - write!(f, "_")?; + print!(cx, write("_"))?; } ty::LazyConst::Evaluated(c) => { - write!(f, "{}", c.unwrap_usize(cx.tcx))?; + print!(cx, write("{}", c.unwrap_usize(cx.tcx)))?; } } - write!(f, "]") + print!(cx, write("]")) } Slice(ty) => { - print!(f, cx, write("["), print(ty), write("]")) + print!(cx, write("["), print(ty), write("]")) } } } debug { - self.print_display(f, cx) + self.print_display(cx) } } } define_print! { - () ty::ParamTy, (self, f, cx) { + () ty::ParamTy, (self, cx) { display { - write!(f, "{}", self.name) + print!(cx, write("{}", self.name)) } debug { - write!(f, "{}/#{}", self.name, self.idx) + print!(cx, write("{}/#{}", self.name, self.idx)) } } } @@ -1375,37 +1365,37 @@ define_print_multi! { ('tcx) ty::OutlivesPredicate, ty::Region<'tcx>>, ('tcx) ty::OutlivesPredicate, ty::Region<'tcx>> ] - (self, f, cx) { + (self, cx) { display { - print!(f, cx, print(self.0), write(" : "), print(self.1)) + print!(cx, print(self.0), write(" : "), print(self.1)) } } } define_print! { - ('tcx) ty::SubtypePredicate<'tcx>, (self, f, cx) { + ('tcx) ty::SubtypePredicate<'tcx>, (self, cx) { display { - print!(f, cx, print(self.a), write(" <: "), print(self.b)) + print!(cx, print(self.a), write(" <: "), print(self.b)) } } } define_print! { - ('tcx) ty::TraitPredicate<'tcx>, (self, f, cx) { + ('tcx) ty::TraitPredicate<'tcx>, (self, cx) { debug { - write!(f, "TraitPredicate({:?})", - self.trait_ref) + print!(cx, write("TraitPredicate({:?})", + self.trait_ref)) } display { - print!(f, cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) + print!(cx, print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) } } } define_print! { - ('tcx) ty::ProjectionPredicate<'tcx>, (self, f, cx) { + ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) { debug { - print!(f, cx, + print!(cx, write("ProjectionPredicate("), print(self.projection_ty), write(", "), @@ -1413,71 +1403,73 @@ define_print! { write(")")) } display { - print!(f, cx, print(self.projection_ty), write(" == "), print(self.ty)) + print!(cx, print(self.projection_ty), write(" == "), print(self.ty)) } } } define_print! { - ('tcx) ty::ProjectionTy<'tcx>, (self, f, cx) { + ('tcx) ty::ProjectionTy<'tcx>, (self, cx) { display { - cx.parameterized(f, self.item_def_id, self.substs, iter::empty()) + cx.parameterized(self.item_def_id, self.substs, iter::empty()) } } } define_print! { - () ty::ClosureKind, (self, f, cx) { + () ty::ClosureKind, (self, cx) { display { match *self { - ty::ClosureKind::Fn => write!(f, "Fn"), - ty::ClosureKind::FnMut => write!(f, "FnMut"), - ty::ClosureKind::FnOnce => write!(f, "FnOnce"), + ty::ClosureKind::Fn => print!(cx, write("Fn")), + ty::ClosureKind::FnMut => print!(cx, write("FnMut")), + ty::ClosureKind::FnOnce => print!(cx, write("FnOnce")), } } } } define_print! { - ('tcx) ty::Predicate<'tcx>, (self, f, cx) { + ('tcx) ty::Predicate<'tcx>, (self, cx) { display { match *self { - ty::Predicate::Trait(ref data) => data.print(f, cx), - ty::Predicate::Subtype(ref predicate) => predicate.print(f, cx), - ty::Predicate::RegionOutlives(ref predicate) => predicate.print(f, cx), - ty::Predicate::TypeOutlives(ref predicate) => predicate.print(f, cx), - ty::Predicate::Projection(ref predicate) => predicate.print(f, cx), - ty::Predicate::WellFormed(ty) => print!(f, cx, print(ty), write(" well-formed")), + ty::Predicate::Trait(ref data) => data.print(cx), + ty::Predicate::Subtype(ref predicate) => predicate.print(cx), + ty::Predicate::RegionOutlives(ref predicate) => predicate.print(cx), + ty::Predicate::TypeOutlives(ref predicate) => predicate.print(cx), + ty::Predicate::Projection(ref predicate) => predicate.print(cx), + ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { - write!(f, "the trait `{}` is object-safe", cx.tcx.item_path_str(trait_def_id)) + print!(cx, write("the trait `{}` is object-safe", + cx.tcx.item_path_str(trait_def_id))) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { - write!(f, "the closure `{}` implements the trait `{}`", - cx.tcx.item_path_str(closure_def_id), kind) + print!(cx, write("the closure `{}` implements the trait `{}`", + cx.tcx.item_path_str(closure_def_id), kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { - write!(f, "the constant `")?; - cx.parameterized(f, def_id, substs, iter::empty())?; - write!(f, "` can be evaluated") + print!(cx, write("the constant `"))?; + cx.parameterized(def_id, substs, iter::empty())?; + print!(cx, write("` can be evaluated")) } } } debug { match *self { - ty::Predicate::Trait(ref a) => a.print(f, cx), - ty::Predicate::Subtype(ref pair) => pair.print(f, cx), - ty::Predicate::RegionOutlives(ref pair) => pair.print(f, cx), - ty::Predicate::TypeOutlives(ref pair) => pair.print(f, cx), - ty::Predicate::Projection(ref pair) => pair.print(f, cx), - ty::Predicate::WellFormed(ty) => ty.print(f, cx), + ty::Predicate::Trait(ref a) => a.print(cx), + ty::Predicate::Subtype(ref pair) => pair.print(cx), + ty::Predicate::RegionOutlives(ref pair) => pair.print(cx), + ty::Predicate::TypeOutlives(ref pair) => pair.print(cx), + ty::Predicate::Projection(ref pair) => pair.print(cx), + ty::Predicate::WellFormed(ty) => ty.print(cx), ty::Predicate::ObjectSafe(trait_def_id) => { - write!(f, "ObjectSafe({:?})", trait_def_id) + print!(cx, write("ObjectSafe({:?})", trait_def_id)) } ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind) + print!(cx, write("ClosureKind({:?}, {:?}, {:?})", + closure_def_id, closure_substs, kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { - write!(f, "ConstEvaluatable({:?}, {:?})", def_id, substs) + print!(cx, write("ConstEvaluatable({:?}, {:?})", def_id, substs)) } } } @@ -1485,17 +1477,17 @@ define_print! { } define_print! { - ('tcx) Kind<'tcx>, (self, f, cx) { + ('tcx) Kind<'tcx>, (self, cx) { display { match self.unpack() { - UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), - UnpackedKind::Type(ty) => print!(f, cx, print(ty)), + UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), + UnpackedKind::Type(ty) => print!(cx, print(ty)), } } debug { match self.unpack() { - UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), - UnpackedKind::Type(ty) => print!(f, cx, print(ty)), + UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), + UnpackedKind::Type(ty) => print!(cx, print(ty)), } } } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 1f590d46ed8c6..0d0da0da5c365 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -6,6 +6,7 @@ html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(custom_attribute)] diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c8fe517621ab5..030860fddd7f7 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -223,8 +223,7 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { item_path::with_forced_absolute_paths(|| { - let mut cx = PrintCx::new(tcx); - SymbolPathPrinter::print_item_path(&mut cx, def_id).into_interned() + PrintCx::new(tcx, SymbolPathPrinter).print_item_path(def_id).into_interned() }) } @@ -396,17 +395,21 @@ struct SymbolPathPrinter; impl ItemPathPrinter for SymbolPathPrinter { type Path = SymbolPath; - fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { let mut path = SymbolPath::new(); - path.push(&cx.tcx.original_crate_name(cnum).as_str()); + path.push(&self.tcx.original_crate_name(cnum).as_str()); path } - fn path_impl(text: &str) -> Self::Path { + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { let mut path = SymbolPath::new(); path.push(text); path } - fn path_append(mut path: Self::Path, text: &str) -> Self::Path { + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + mut path: Self::Path, + text: &str, + ) -> Self::Path { path.push(text); path } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7e355a440791b..a272f3b72cde2 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4053,20 +4053,23 @@ where F: Fn(DefId) -> Def { impl ItemPathPrinter for AbsolutePathPrinter { type Path = Vec; - fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { - vec![cx.tcx.original_crate_name(cnum).to_string()] + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + vec![self.tcx.original_crate_name(cnum).to_string()] } - fn path_impl(text: &str) -> Self::Path { + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { vec![text.to_string()] } - fn path_append(mut path: Self::Path, text: &str) -> Self::Path { + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + mut path: Self::Path, + text: &str, + ) -> Self::Path { path.push(text.to_string()); path } } - let mut cx = PrintCx::new(tcx); - let names = AbsolutePathPrinter::print_item_path(&mut cx, def_id); + let names = PrintCx::new(tcx, AbsolutePathPrinter).print_item_path(def_id); hir::Path { span: DUMMY_SP, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index f4149b5f35736..3ec25e2219ed5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -5,6 +5,7 @@ #![feature(bind_by_move_pattern_guards)] #![feature(rustc_private)] +#![feature(arbitrary_self_types)] #![feature(box_patterns)] #![feature(box_syntax)] #![feature(nll)] From 87c27fd6092ecb8f3c7ea3f6c9b11b0a6f273209 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Dec 2018 15:12:48 +0200 Subject: [PATCH 20/68] rustc: explicitly pass the namespace to PrintCx::parameterized. --- src/librustc/mir/mod.rs | 4 +- src/librustc/ty/instance.rs | 3 +- src/librustc/util/ppaux.rs | 76 +++++++++++++++------------ src/test/mir-opt/basic_assignment.rs | 2 +- src/test/mir-opt/match_false_edges.rs | 6 +-- src/test/mir-opt/storage_ranges.rs | 2 +- 6 files changed, 51 insertions(+), 42 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index eb2d4846eec72..06e0f2a587202 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2,7 +2,7 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html -use hir::def::CtorKind; +use hir::def::{CtorKind, Namespace}; use hir::def_id::DefId; use hir::{self, HirId, InlineAsm}; use mir::interpret::{ConstValue, EvalErrorKind, Scalar}; @@ -2377,7 +2377,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { AggregateKind::Adt(adt_def, variant, substs, _user_ty, _) => { let variant_def = &adt_def.variants[variant]; - ppaux::parameterized(fmt, variant_def.did, substs)?; + ppaux::parameterized(fmt, variant_def.did, substs, Namespace::ValueNS)?; match variant_def.ctor_kind { CtorKind::Const => Ok(()), diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index fd0c8170510c9..480d4c6d73a2c 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,4 +1,5 @@ use hir::Unsafety; +use hir::def::Namespace; use hir::def_id::DefId; use ty::{self, Ty, PolyFnSig, TypeFoldable, Substs, TyCtxt}; use traits; @@ -174,7 +175,7 @@ impl<'tcx> InstanceDef<'tcx> { impl<'tcx> fmt::Display for Instance<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - ppaux::parameterized(f, self.def_id(), self.substs)?; + ppaux::parameterized(f, self.def_id(), self.substs, Namespace::ValueNS)?; match self.def { InstanceDef::Item(_) => Ok(()), InstanceDef::VtableShim(_) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 94cf91f2547a4..6c1c30ec96c94 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,3 +1,4 @@ +use hir::def::Namespace; use hir::def_id::DefId; use hir::map::definitions::DefPathData; use middle::region; @@ -285,26 +286,12 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { fn parameterized( &mut self, - mut def_id: DefId, + def_id: DefId, substs: &Substs<'tcx>, + ns: Namespace, projections: impl Iterator>, ) -> fmt::Result { - let mut key = self.tcx.def_key(def_id); - let is_value_ns = match key.disambiguated_data.data { - DefPathData::ValueNs(_) | - DefPathData::EnumVariant(_) => true, - - // Skip `StructCtor` so that `Struct::` will be printed, - // instead of the less pretty `Struct::{{constructor}}`. - DefPathData::StructCtor => { - def_id.index = key.parent.unwrap(); - key = self.tcx.def_key(def_id); - true - } - - _ => false, - }; - + let key = self.tcx.def_key(def_id); let generics = self.tcx.generics_of(def_id); if let Some(parent_def_id) = generics.parent { @@ -315,13 +302,20 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { parent_generics.has_self && parent_generics.parent_count == 0; if parent_has_own_self { print!(self, write("<"), print_display(substs.type_at(0)), write(" as "))?; - } - self.parameterized(parent_def_id, substs, iter::empty())?; - if parent_has_own_self { + self.parameterized(parent_def_id, substs, Namespace::TypeNS, iter::empty())?; print!(self, write(">"))?; + } else { + self.parameterized(parent_def_id, substs, ns, iter::empty())?; } - print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?; + // Skip `::{{constructor}}` on tuple/unit structs. + match key.disambiguated_data.data { + DefPathData::StructCtor => {} + + _ => { + print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?; + } + } } else { // Try to print `impl`s more like how you'd refer to their associated items. if let DefPathData::Impl = key.disambiguated_data.data { @@ -352,7 +346,7 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { } }; - let start = if is_value_ns { "::<" } else { "<" }; + let start = if ns == Namespace::ValueNS { "::<" } else { "<" }; let has_own_self = generics.has_self && generics.parent_count == 0; let params = &generics.params[has_own_self as usize..]; @@ -491,10 +485,15 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { } } -pub fn parameterized(f: &mut F, did: DefId, substs: &Substs<'_>) -> fmt::Result { +pub fn parameterized( + f: &mut F, + did: DefId, + substs: &Substs<'_>, + ns: Namespace, +) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.parameterized(did, substs, iter::empty()) + cx.parameterized(did, substs, ns, iter::empty()) }) } @@ -533,6 +532,7 @@ define_print! { cx.parameterized( principal.def_id, principal.substs, + Namespace::TypeNS, self.projection_bounds(), )?; } @@ -657,7 +657,7 @@ define_print! { let trait_ref = *ty::Binder::bind(*self) .with_self_ty(cx.tcx, dummy_self) .skip_binder(); - cx.parameterized(trait_ref.def_id, trait_ref.substs, iter::empty()) + cx.parameterized(trait_ref.def_id, trait_ref.substs, Namespace::TypeNS, iter::empty()) } debug { self.print_display(cx) @@ -1100,12 +1100,16 @@ define_print_multi! { define_print! { ('tcx) ty::TraitRef<'tcx>, (self, cx) { display { - cx.parameterized(self.def_id, self.substs, iter::empty()) + cx.parameterized(self.def_id, self.substs, Namespace::TypeNS, iter::empty()) } debug { - print!(cx, write("<"), print(self.self_ty()), write(" as "))?; - cx.parameterized(self.def_id, self.substs, iter::empty())?; - print!(cx, write(">")) + print!(cx, + write("<"), + print(self.self_ty()), + write(" as "), + print_display(self), + write(">") + ) } } } @@ -1151,7 +1155,7 @@ define_print! { FnDef(def_id, substs) => { let sig = cx.tcx.fn_sig(def_id).subst(cx.tcx, substs); print!(cx, print(sig), write(" {{"))?; - cx.parameterized(def_id, substs, iter::empty())?; + cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?; print!(cx, write("}}")) } FnPtr(ref bare_fn) => { @@ -1173,7 +1177,9 @@ define_print! { ty::BoundTyKind::Param(p) => print!(cx, write("{}", p)), } } - Adt(def, substs) => cx.parameterized(def.did, substs, iter::empty()), + Adt(def, substs) => { + cx.parameterized(def.did, substs, Namespace::TypeNS, iter::empty()) + } Dynamic(data, r) => { let print_r = r.display_outputs_anything(cx); if print_r { @@ -1186,7 +1192,9 @@ define_print! { } Ok(()) } - Foreign(def_id) => cx.parameterized(def_id, Substs::empty(), iter::empty()), + Foreign(def_id) => { + cx.parameterized(def_id, Substs::empty(), Namespace::TypeNS, iter::empty()) + } Projection(ref data) => data.print(cx), UnnormalizedProjection(ref data) => { print!(cx, write("Unnormalized("))?; @@ -1411,7 +1419,7 @@ define_print! { define_print! { ('tcx) ty::ProjectionTy<'tcx>, (self, cx) { display { - cx.parameterized(self.item_def_id, self.substs, iter::empty()) + cx.parameterized(self.item_def_id, self.substs, Namespace::TypeNS, iter::empty()) } } } @@ -1448,7 +1456,7 @@ define_print! { } ty::Predicate::ConstEvaluatable(def_id, substs) => { print!(cx, write("the constant `"))?; - cx.parameterized(def_id, substs, iter::empty())?; + cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?; print!(cx, write("` can be evaluated")) } } diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index 1bbbe67a12cb8..3ce43cc4a224f 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -35,7 +35,7 @@ fn main() { // _2 = move _3; // StorageDead(_3); // StorageLive(_4); -// _4 = std::option::Option>::None; +// _4 = std::option::Option::>::None; // FakeRead(ForLet, _4); // AscribeUserType(_4, o, UserTypeProjection { base: UserType(1), projs: [] }); // StorageLive(_5); diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index b512172de64ee..6e0caee3cfe7f 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -42,7 +42,7 @@ fn main() { // START rustc.full_tested_match.QualifyAndPromoteConstants.after.mir // bb0: { // ... -// _2 = std::option::Option::Some(const 42i32,); +// _2 = std::option::Option::::Some(const 42i32,); // FakeRead(ForMatchedPlace, _2); // _7 = discriminant(_2); // _9 = &shallow (promoted[2]: std::option::Option); @@ -116,7 +116,7 @@ fn main() { // START rustc.full_tested_match2.QualifyAndPromoteConstants.before.mir // bb0: { // ... -// _2 = std::option::Option::Some(const 42i32,); +// _2 = std::option::Option::::Some(const 42i32,); // FakeRead(ForMatchedPlace, _2); // _7 = discriminant(_2); // _9 = &shallow _2; @@ -190,7 +190,7 @@ fn main() { // START rustc.main.QualifyAndPromoteConstants.before.mir // bb0: { // ... -// _2 = std::option::Option::Some(const 1i32,); +// _2 = std::option::Option::::Some(const 1i32,); // FakeRead(ForMatchedPlace, _2); // _11 = discriminant(_2); // _16 = &shallow _2; diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index a5d6ced2b1772..9a22f57116ed8 100644 --- a/src/test/mir-opt/storage_ranges.rs +++ b/src/test/mir-opt/storage_ranges.rs @@ -18,7 +18,7 @@ fn main() { // StorageLive(_4); // StorageLive(_5); // _5 = _1; -// _4 = std::option::Option::Some(move _5,); +// _4 = std::option::Option::::Some(move _5,); // StorageDead(_5); // _3 = &_4; // FakeRead(ForLet, _3); From 10fbc5580063219b89ef7ff523311976a4263cb8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Dec 2018 18:28:29 +0200 Subject: [PATCH 21/68] rustc: move the FORCE_IMPL_FILENAME_LINE handling into LocalPathPrinter. --- src/librustc/ty/item_path.rs | 52 ++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index dbaafc5527621..32c5fec787798 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -91,7 +91,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } DefPathData::Impl => { - self.default_print_impl_path(def_id) + self.print_impl_path(def_id) } // Unclear if there is any value in distinguishing these. @@ -131,18 +131,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = !impl_def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; - - if !use_types { - return self.default_print_impl_path_fallback(impl_def_id); - } - // Decide whether to print the parent path for the impl. // Logically, since impls are global, it's never needed, but // users may find it useful. Currently, we omit the parent if @@ -209,19 +197,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } } } - - fn default_print_impl_path_fallback(&mut self, impl_def_id: DefId) -> P::Path { - // If no type info is available, fall back to - // pretty printing some span information. This should - // only occur very early in the compiler pipeline. - // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` - let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); - let path = self.print_item_path(parent_def_id); - let node_id = self.tcx.hir().as_local_node_id(impl_def_id).unwrap(); - let item = self.tcx.hir().expect_item(node_id); - let span_str = self.tcx.sess.source_map().span_to_string(item.span); - self.path_append(path, &format!("", span_str)) - } } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { @@ -290,6 +265,9 @@ pub trait ItemPathPrinter: Sized { fn print_item_path(self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId) -> Self::Path { self.default_print_item_path(def_id) } + fn print_impl_path(self: &mut PrintCx<'_, '_, '_, Self>, impl_def_id: DefId) -> Self::Path { + self.default_print_impl_path(impl_def_id) + } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; @@ -472,6 +450,28 @@ impl ItemPathPrinter for LocalPathPrinter { self.try_print_visible_item_path(def_id) .unwrap_or_else(|| self.default_print_item_path(def_id)) } + fn print_impl_path(self: &mut PrintCx<'_, '_, '_, Self>, impl_def_id: DefId) -> Self::Path { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = !impl_def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; + + if !use_types { + // If no type info is available, fall back to + // pretty printing some span information. This should + // only occur very early in the compiler pipeline. + // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` + let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); + let path = self.print_item_path(parent_def_id); + let span = self.tcx.def_span(impl_def_id); + return self.path_append(path, &format!("", span)); + } + + self.default_print_impl_path(impl_def_id) + } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { if cnum == LOCAL_CRATE { From e2ac9493010cffcca28bb59b1f88bf29ff2b4243 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 05:01:06 +0200 Subject: [PATCH 22/68] rustc: pass Option<&Substs> and Namespace around in ty::item_path. --- src/librustc/ty/item_path.rs | 135 +++++++++++++----- src/librustc/util/ppaux.rs | 20 +-- src/librustc_codegen_utils/symbol_names.rs | 5 +- src/librustdoc/clean/mod.rs | 5 +- src/test/ui/bad/bad-sized.stderr | 2 +- src/test/ui/hygiene/impl_items.rs | 2 +- src/test/ui/hygiene/impl_items.stderr | 4 +- src/test/ui/issues/issue-17651.stderr | 2 +- src/test/ui/issues/issue-22638.rs | 2 +- src/test/ui/issues/issue-22638.stderr | 4 +- src/test/ui/issues/issue-24322.stderr | 2 +- src/test/ui/issues/issue-29124.rs | 2 +- src/test/ui/issues/issue-29124.stderr | 2 +- .../issue-37311.stderr | 2 +- src/test/ui/issues/issue-39559-2.stderr | 4 +- .../associated-item-privacy-inherent.rs | 6 +- .../associated-item-privacy-inherent.stderr | 6 +- .../ui/privacy/private-inferred-type-3.rs | 2 +- .../ui/privacy/private-inferred-type-3.stderr | 2 +- src/test/ui/privacy/private-inferred-type.rs | 2 +- .../ui/privacy/private-inferred-type.stderr | 2 +- .../ui/qualified/qualified-path-params.stderr | 2 +- src/test/ui/symbol-names/impl1.rs | 2 +- src/test/ui/symbol-names/impl1.stderr | 4 +- 24 files changed, 143 insertions(+), 78 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 32c5fec787798..d84a82e76d68c 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -1,7 +1,9 @@ +use hir::def::Namespace; use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, DefIdTree, Ty, TyCtxt}; use ty::print::PrintCx; +use ty::subst::{Subst, Substs}; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::{keywords, Symbol}; @@ -54,18 +56,48 @@ pub fn with_crate_prefix R, R>(f: F) -> R { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + // HACK(eddyb) get rid of `item_path_str` and/or pass `Namespace` explicitly always + // (but also some things just print a `DefId` generally so maybe we need this?) + fn guess_def_namespace(self, def_id: DefId) -> Namespace { + match self.def_key(def_id).disambiguated_data.data { + DefPathData::ValueNs(..) | + DefPathData::EnumVariant(..) | + DefPathData::Field(..) | + DefPathData::AnonConst | + DefPathData::ClosureExpr | + DefPathData::StructCtor => Namespace::ValueNS, + + DefPathData::MacroDef(..) => Namespace::MacroNS, + + _ => Namespace::TypeNS, + } + } + /// Returns a string identifying this def-id. This string is /// suitable for user output. It is relative to the current crate /// root, unless with_forced_absolute_paths was used. - pub fn item_path_str(self, def_id: DefId) -> String { - debug!("item_path_str: def_id={:?}", def_id); + pub fn item_path_str_with_substs_and_ns( + self, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> String { + debug!("item_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); if FORCE_ABSOLUTE.with(|force| force.get()) { - PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id) + PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id, substs, ns) } else { - PrintCx::new(self, LocalPathPrinter).print_item_path(def_id) + PrintCx::new(self, LocalPathPrinter).print_item_path(def_id, substs, ns) } } + /// Returns a string identifying this def-id. This string is + /// suitable for user output. It is relative to the current crate + /// root, unless with_forced_absolute_paths was used. + pub fn item_path_str(self, def_id: DefId) -> String { + let ns = self.guess_def_namespace(def_id); + self.item_path_str_with_substs_and_ns(def_id, None, ns) + } + /// Returns a string identifying this local node-id. pub fn node_path_str(self, id: ast::NodeId) -> String { self.item_path_str(self.hir().local_def_id(id)) @@ -75,13 +107,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// suitable for user output. It always begins with a crate identifier. pub fn absolute_item_path_str(self, def_id: DefId) -> String { debug!("absolute_item_path_str: def_id={:?}", def_id); - PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id) + let ns = self.guess_def_namespace(def_id); + PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id, None, ns) } } impl PrintCx<'a, 'gcx, 'tcx, P> { - pub fn default_print_item_path(&mut self, def_id: DefId) -> P::Path { - debug!("default_print_item_path: def_id={:?}", def_id); + pub fn default_print_item_path( + &mut self, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> P::Path { + debug!("default_print_item_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); let key = self.tcx.def_key(def_id); debug!("default_print_item_path: key={:?}", key); match key.disambiguated_data.data { @@ -91,7 +129,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } DefPathData::Impl => { - self.print_impl_path(def_id) + self.print_impl_path(def_id, substs, ns) } // Unclear if there is any value in distinguishing these. @@ -116,18 +154,23 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { let parent_did = self.tcx.parent_def_id(def_id).unwrap(); - let path = self.print_item_path(parent_did); + let path = self.print_item_path(parent_did, None, ns); self.path_append(path, &data.as_interned_str().as_symbol().as_str()) }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); - self.print_item_path(parent_def_id) + self.print_item_path(parent_def_id, substs, ns) } } } - fn default_print_impl_path(&mut self, impl_def_id: DefId) -> P::Path { + fn default_print_impl_path( + &mut self, + impl_def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> P::Path { debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); @@ -136,13 +179,19 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // users may find it useful. Currently, we omit the parent if // the impl is either in the same module as the self-type or // as the trait. - let self_ty = self.tcx.type_of(impl_def_id); + let mut self_ty = self.tcx.type_of(impl_def_id); + if let Some(substs) = substs { + self_ty = self_ty.subst(self.tcx, substs); + } let in_self_mod = match characteristic_def_id_of_type(self_ty) { None => false, Some(ty_def_id) => self.tcx.parent_def_id(ty_def_id) == Some(parent_def_id), }; - let impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); + let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); + if let Some(substs) = substs { + impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); + } let in_trait_mod = match impl_trait_ref { None => false, Some(trait_ref) => self.tcx.parent_def_id(trait_ref.def_id) == Some(parent_def_id), @@ -152,7 +201,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - let path = self.print_item_path(parent_def_id); + let path = self.print_item_path(parent_def_id, None, ns); if let Some(trait_ref) = impl_trait_ref { return self.path_append(path, &format!("", trait_ref, self_ty)); } else { @@ -173,15 +222,14 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // anything other than a simple path. match self_ty.sty { ty::Adt(adt_def, substs) => { - // FIXME(eddyb) always print without <> here. - if substs.types().next().is_none() { // ignore regions - self.print_item_path(adt_def.did) - } else { - self.path_impl(&format!("<{}>", self_ty)) - } + // FIXME(eddyb) this should recurse to build the path piecewise. + // self.print_item_path(adt_def.did, Some(substs), ns) + let mut s = String::new(); + ::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap(); + self.path_impl(&s) } - ty::Foreign(did) => self.print_item_path(did), + ty::Foreign(did) => self.print_item_path(did, None, ns), ty::Bool | ty::Char | @@ -262,11 +310,21 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { pub trait ItemPathPrinter: Sized { type Path; - fn print_item_path(self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId) -> Self::Path { - self.default_print_item_path(def_id) + fn print_item_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + self.default_print_item_path(def_id, substs, ns) } - fn print_impl_path(self: &mut PrintCx<'_, '_, '_, Self>, impl_def_id: DefId) -> Self::Path { - self.default_print_impl_path(impl_def_id) + fn print_impl_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + self.default_print_impl_path(impl_def_id, substs, ns) } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; @@ -311,6 +369,7 @@ impl LocalPathPrinter { fn try_print_visible_item_path( self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId, + ns: Namespace, ) -> Option<::Path> { debug!("try_print_visible_item_path: def_id={:?}", def_id); @@ -342,7 +401,7 @@ impl LocalPathPrinter { }) => { debug!("try_print_visible_item_path: def_id={:?}", def_id); let path = if !span.is_dummy() { - self.print_item_path(def_id) + self.print_item_path(def_id, None, ns) } else { self.path_crate(cnum) }; @@ -375,7 +434,7 @@ impl LocalPathPrinter { } let visible_parent = visible_parent_map.get(&def_id).cloned()?; - let path = self.try_print_visible_item_path(visible_parent)?; + let path = self.try_print_visible_item_path(visible_parent, ns)?; let actual_parent = self.tcx.parent(def_id); let data = cur_def_key.disambiguated_data.data; @@ -446,11 +505,21 @@ impl LocalPathPrinter { impl ItemPathPrinter for LocalPathPrinter { type Path = String; - fn print_item_path(self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId) -> Self::Path { - self.try_print_visible_item_path(def_id) - .unwrap_or_else(|| self.default_print_item_path(def_id)) + fn print_item_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + self.try_print_visible_item_path(def_id, ns) + .unwrap_or_else(|| self.default_print_item_path(def_id, substs, ns)) } - fn print_impl_path(self: &mut PrintCx<'_, '_, '_, Self>, impl_def_id: DefId) -> Self::Path { + fn print_impl_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { // Always use types for non-local impls, where types are always // available, and filename/line-number is mostly uninteresting. let use_types = !impl_def_id.is_local() || { @@ -465,12 +534,12 @@ impl ItemPathPrinter for LocalPathPrinter { // only occur very early in the compiler pipeline. // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); - let path = self.print_item_path(parent_def_id); + let path = self.print_item_path(parent_def_id, None, ns); let span = self.tcx.def_span(impl_def_id); return self.path_append(path, &format!("", span)); } - self.default_print_impl_path(impl_def_id) + self.default_print_impl_path(impl_def_id, substs, ns) } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 6c1c30ec96c94..22824a685cd7c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -317,23 +317,15 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { } } } else { - // Try to print `impl`s more like how you'd refer to their associated items. + // FIXME(eddyb) recurse through printing a path via `self`, instead + // instead of using the `tcx` method that produces a `String`. + print!(self, write("{}", + self.tcx.item_path_str_with_substs_and_ns(def_id, Some(substs), ns)))?; + + // For impls, the above call already prints relevant generics args. if let DefPathData::Impl = key.disambiguated_data.data { - if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) { - // HACK(eddyb) this is in lieu of more specific disambiguation. - print!(self, write("{}", self.tcx.item_path_str(def_id)))?; - - let trait_ref = trait_ref.subst(self.tcx, substs); - print!(self, print_debug(trait_ref))?; - } else { - let self_ty = self.tcx.type_of(def_id).subst(self.tcx, substs); - // FIXME(eddyb) omit the <> where possible. - print!(self, write("<"), print(self_ty), write(">"))?; - } return Ok(()); } - - print!(self, write("{}", self.tcx.item_path_str(def_id)))?; } let mut empty = true; diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 030860fddd7f7..64787a0e9875b 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -87,6 +87,7 @@ //! virtually impossible. Thus, symbol hash generation exclusively relies on //! DefPaths which are much more robust in the face of changes to the code base. +use rustc::hir::def::Namespace; use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; @@ -223,7 +224,9 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { item_path::with_forced_absolute_paths(|| { - PrintCx::new(tcx, SymbolPathPrinter).print_item_path(def_id).into_interned() + PrintCx::new(tcx, SymbolPathPrinter) + .print_item_path(def_id, None, Namespace::ValueNS) + .into_interned() }) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a272f3b72cde2..fc0e1d5e5ca79 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -18,7 +18,7 @@ use rustc::middle::lang_items; use rustc::middle::stability; use rustc::mir::interpret::GlobalId; use rustc::hir::{self, GenericArg, HirVec}; -use rustc::hir::def::{self, Def, CtorKind}; +use rustc::hir::def::{self, Def, CtorKind, Namespace}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; @@ -4069,7 +4069,8 @@ where F: Fn(DefId) -> Def { } } - let names = PrintCx::new(tcx, AbsolutePathPrinter).print_item_path(def_id); + let names = PrintCx::new(tcx, AbsolutePathPrinter) + .print_item_path(def_id, None, Namespace::TypeNS); hir::Path { span: DUMMY_SP, diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 9565888dcc022..51b8474555293 100644 --- a/src/test/ui/bad/bad-sized.stderr +++ b/src/test/ui/bad/bad-sized.stderr @@ -22,7 +22,7 @@ LL | let x: Vec = Vec::new(); | = help: the trait `std::marker::Sized` is not implemented for `dyn Trait` = note: to learn more, visit - = note: required by `>::new` + = note: required by `std::vec::Vec::::new` error: aborting due to 3 previous errors diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs index d628573d51707..37794c6e0773c 100644 --- a/src/test/ui/hygiene/impl_items.rs +++ b/src/test/ui/hygiene/impl_items.rs @@ -9,7 +9,7 @@ mod foo { } pub macro m() { - let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {::f}` is private + let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private } } diff --git a/src/test/ui/hygiene/impl_items.stderr b/src/test/ui/hygiene/impl_items.stderr index 487d9059cf97b..cb3705e5513cc 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -1,7 +1,7 @@ -error: type `for<'r> fn(&'r foo::S) {::f}` is private +error: type `for<'r> fn(&'r foo::S) {foo::S::f}` is private --> $DIR/impl_items.rs:12:23 | -LL | let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {::f}` is private +LL | let _: () = S.f(); //~ ERROR type `for<'r> fn(&'r foo::S) {foo::S::f}` is private | ^ ... LL | foo::m!(); diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr index 72c40ff4b3a0c..ce9af1524b087 100644 --- a/src/test/ui/issues/issue-17651.stderr +++ b/src/test/ui/issues/issue-17651.stderr @@ -6,7 +6,7 @@ LL | (|| Box::new(*(&[0][..])))(); | = help: the trait `std::marker::Sized` is not implemented for `[{integer}]` = note: to learn more, visit - = note: required by `>::new` + = note: required by `std::boxed::Box::::new` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs index ff58c7aaced03..fab24404eba7d 100644 --- a/src/test/ui/issues/issue-22638.rs +++ b/src/test/ui/issues/issue-22638.rs @@ -50,7 +50,7 @@ struct D (Box); impl D { pub fn matches(&self, f: &F) { - //~^ ERROR reached the type-length limit while instantiating `::matches::<[closure + //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure let &D(ref a) = self; a.matches(f) } diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr index 6d23c896f594f..ba7d5f070170d 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -1,8 +1,8 @@ -error: reached the type-length limit while instantiating `::matches::$CLOSURE` +error: reached the type-length limit while instantiating `D::matches::$CLOSURE` --> $DIR/issue-22638.rs:52:5 | LL | / pub fn matches(&self, f: &F) { -LL | | //~^ ERROR reached the type-length limit while instantiating `::matches::<[closure +LL | | //~^ ERROR reached the type-length limit while instantiating `D::matches::<[closure LL | | let &D(ref a) = self; LL | | a.matches(f) LL | | } diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr index 14b10dbe978a5..b42854387518e 100644 --- a/src/test/ui/issues/issue-24322.stderr +++ b/src/test/ui/issues/issue-24322.stderr @@ -5,7 +5,7 @@ LL | let x: &fn(&B) -> u32 = &B::func; //~ ERROR mismatched types | ^^^^^^^^ expected fn pointer, found fn item | = note: expected type `&for<'r> fn(&'r B) -> u32` - found type `&for<'r> fn(&'r B) -> u32 {::func}` + found type `&for<'r> fn(&'r B) -> u32 {B::func}` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-29124.rs b/src/test/ui/issues/issue-29124.rs index 8062045a6c058..1cd3f84f7a227 100644 --- a/src/test/ui/issues/issue-29124.rs +++ b/src/test/ui/issues/issue-29124.rs @@ -13,7 +13,7 @@ fn func() -> Ret { fn main() { Obj::func.x(); - //~^ ERROR no method named `x` found for type `fn() -> Ret {::func}` in the current scope + //~^ ERROR no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope func.x(); //~^ ERROR no method named `x` found for type `fn() -> Ret {func}` in the current scope } diff --git a/src/test/ui/issues/issue-29124.stderr b/src/test/ui/issues/issue-29124.stderr index 67f188e0588e2..3beb728978884 100644 --- a/src/test/ui/issues/issue-29124.stderr +++ b/src/test/ui/issues/issue-29124.stderr @@ -1,4 +1,4 @@ -error[E0599]: no method named `x` found for type `fn() -> Ret {::func}` in the current scope +error[E0599]: no method named `x` found for type `fn() -> Ret {Obj::func}` in the current scope --> $DIR/issue-29124.rs:15:15 | LL | Obj::func.x(); diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr index fa1ee227f0bf2..d98da3f10d0eb 100644 --- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr +++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr @@ -1,4 +1,4 @@ -error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(), &()), &(&()...` +error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(), &()), &(&(), &())), &...` --> $DIR/issue-37311.rs:13:5 | LL | / fn recurse(&self) { //~ ERROR reached the type-length limit diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr index ca2f2a5ba2845..700dbe3647497 100644 --- a/src/test/ui/issues/issue-39559-2.stderr +++ b/src/test/ui/issues/issue-39559-2.stderr @@ -8,7 +8,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-39559-2.rs:14:24 | LL | let array: [usize; Dim3::dim()] - | ^^^^^^^^^^^ calling non-const function `::dim` + | ^^^^^^^^^^^ calling non-const function `::dim` error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-39559-2.rs:17:15 @@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed --> $DIR/issue-39559-2.rs:17:15 | LL | = [0; Dim3::dim()]; - | ^^^^^^^^^^^ calling non-const function `::dim` + | ^^^^^^^^^^^ calling non-const function `::dim` error: aborting due to 4 previous errors diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.rs b/src/test/ui/privacy/associated-item-privacy-inherent.rs index b6fd22fa669e0..c3ae920238f18 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.rs +++ b/src/test/ui/privacy/associated-item-privacy-inherent.rs @@ -11,11 +11,11 @@ mod priv_nominal { pub macro mac() { let value = Pub::method; - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private + //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private value; - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private + //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private Pub.method(); - //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private + //~^ ERROR type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private Pub::CONST; //~^ ERROR associated constant `CONST` is private // let _: Pub::AssocTy; diff --git a/src/test/ui/privacy/associated-item-privacy-inherent.stderr b/src/test/ui/privacy/associated-item-privacy-inherent.stderr index 69be9d2cea6df..6471a7914e103 100644 --- a/src/test/ui/privacy/associated-item-privacy-inherent.stderr +++ b/src/test/ui/privacy/associated-item-privacy-inherent.stderr @@ -1,4 +1,4 @@ -error: type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private +error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:13:21 | LL | let value = Pub::method; @@ -7,7 +7,7 @@ LL | let value = Pub::method; LL | priv_nominal::mac!(); | --------------------- in this macro invocation -error: type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private +error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:15:9 | LL | value; @@ -16,7 +16,7 @@ LL | value; LL | priv_nominal::mac!(); | --------------------- in this macro invocation -error: type `for<'r> fn(&'r priv_nominal::Pub) {::method}` is private +error: type `for<'r> fn(&'r priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:17:13 | LL | Pub.method(); diff --git a/src/test/ui/privacy/private-inferred-type-3.rs b/src/test/ui/privacy/private-inferred-type-3.rs index d885407a1cd37..39f2e5d4af2aa 100644 --- a/src/test/ui/privacy/private-inferred-type-3.rs +++ b/src/test/ui/privacy/private-inferred-type-3.rs @@ -6,7 +6,7 @@ // error-pattern:type `fn() {::method}` is private // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct}` is private // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct}` is private -// error-pattern:type `for<'r> fn(&'r ext::Pub) {>::priv_method}` is private +// error-pattern:type `for<'r> fn(&'r ext::Pub) {ext::Pub::::priv_method}` is private #![feature(decl_macro)] diff --git a/src/test/ui/privacy/private-inferred-type-3.stderr b/src/test/ui/privacy/private-inferred-type-3.stderr index f8b757ea09820..61cd84762978c 100644 --- a/src/test/ui/privacy/private-inferred-type-3.stderr +++ b/src/test/ui/privacy/private-inferred-type-3.stderr @@ -46,7 +46,7 @@ LL | ext::m!(); | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: type `for<'r> fn(&'r ext::Pub) {>::priv_method}` is private +error: type `for<'r> fn(&'r ext::Pub) {ext::Pub::::priv_method}` is private --> $DIR/private-inferred-type-3.rs:16:5 | LL | ext::m!(); diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs index 69b60a56c67f1..6d0c8887e8e95 100644 --- a/src/test/ui/privacy/private-inferred-type.rs +++ b/src/test/ui/privacy/private-inferred-type.rs @@ -47,7 +47,7 @@ mod m { PubTupleStruct; //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct}` is private Pub(0u8).priv_method(); - //~^ ERROR type `for<'r> fn(&'r m::Pub) {>::priv_method}` is private + //~^ ERROR type `for<'r> fn(&'r m::Pub) {m::Pub::::priv_method}` is private } trait Trait {} diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index 80a475f7dceea..84df88268dae1 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -133,7 +133,7 @@ LL | PubTupleStruct; LL | m::m!(); | -------- in this macro invocation -error: type `for<'r> fn(&'r m::Pub) {>::priv_method}` is private +error: type `for<'r> fn(&'r m::Pub) {m::Pub::::priv_method}` is private --> $DIR/private-inferred-type.rs:49:18 | LL | Pub(0u8).priv_method(); diff --git a/src/test/ui/qualified/qualified-path-params.stderr b/src/test/ui/qualified/qualified-path-params.stderr index 8a7edb6015eed..18fca2e304696 100644 --- a/src/test/ui/qualified/qualified-path-params.stderr +++ b/src/test/ui/qualified/qualified-path-params.stderr @@ -11,7 +11,7 @@ LL | 0 ..= ::A::f:: => {} //~ ERROR only char and numeric t | ^^^^^^^^^^^^^^^^^^^^^ ranges require char or numeric types | = note: start type: {integer} - = note: end type: fn() {::f::} + = note: end type: fn() {S::f::} error: aborting due to 2 previous errors diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 97169c33b8cbf..69cd49e39512e 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -5,7 +5,7 @@ mod foo { pub struct Foo { x: u32 } impl Foo { - #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar + #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar) fn bar() { } } diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index 75d3e40e1b2fc..0e2e81f31ef76 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,7 +1,7 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) +error: symbol-name(_ZN15impl1..foo..Foo3bar17hc487d6ec13fe9124E) --> $DIR/impl1.rs:8:9 | -LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar +LL | #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar | ^^^^^^^^^^^^^^^^^^^^ error: item-path(foo::Foo::bar) From 4e280d90a5fd08a3de54620ab0bd20ee370ee71f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 06:39:33 +0200 Subject: [PATCH 23/68] rustc_mir: adjust the type_length_limit diagnostic to be more useful. --- src/librustc_mir/monomorphize/collector.rs | 38 +++++++++++++------ src/test/ui/issues/issue-22638.stderr | 2 +- .../issue-37311.stderr | 4 +- src/test/ui/type_length_limit.stderr | 8 +++- 4 files changed, 35 insertions(+), 17 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index ad21e0d339303..980b61d772c1b 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -198,6 +198,8 @@ use monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMode}; use rustc_data_structures::bit_set::GrowableBitSet; use rustc_data_structures::sync::{MTRef, MTLock, ParallelIterator, par_iter}; +use std::iter; + #[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)] pub enum MonoItemCollectionMode { Eager, @@ -476,21 +478,33 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Bail out in these cases to avoid that bad user experience. let type_length_limit = *tcx.sess.type_length_limit.get(); if type_length > type_length_limit { - // The instance name is already known to be too long for rustc. Use - // `{:.64}` to avoid blasting the user's terminal with thousands of - // lines of type-name. - let instance_name = instance.to_string(); - let msg = format!("reached the type-length limit while instantiating `{:.64}...`", - instance_name); - let mut diag = if let Some(node_id) = tcx.hir().as_local_node_id(instance.def_id()) { - tcx.sess.struct_span_fatal(tcx.hir().span(node_id), &msg) - } else { - tcx.sess.struct_fatal(&msg) + // The instance name is already known to be too long for rustc. + // Show only the first and last 32 characters to avoid blasting + // the user's terminal with thousands of lines of type-name. + let shrink = |s: String, before: usize, after: usize| { + // An iterator of all byte positions including the end of the string. + let positions = || s.char_indices().map(|(i, _)| i).chain(iter::once(s.len())); + + let shrunk = format!( + "{before}...{after}", + before = &s[..positions().nth(before).unwrap_or(s.len())], + after = &s[positions().rev().nth(after).unwrap_or(0)..], + ); + + // Only use the shrunk version if it's really shorter. + // This also avoids the case where before and after slices overlap. + if shrunk.len() < s.len() { + shrunk + } else { + s + } }; - + let msg = format!("reached the type-length limit while instantiating `{}`", + shrink(instance.to_string(), 32, 32)); + let mut diag = tcx.sess.struct_span_fatal(tcx.def_span(instance.def_id()), &msg); diag.note(&format!( "consider adding a `#![type_length_limit=\"{}\"]` attribute to your crate", - type_length_limit*2)); + type_length)); diag.emit(); tcx.sess.abort_if_errors(); } diff --git a/src/test/ui/issues/issue-22638.stderr b/src/test/ui/issues/issue-22638.stderr index ba7d5f070170d..000ae328c88df 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -8,7 +8,7 @@ LL | | a.matches(f) LL | | } | |_____^ | - = note: consider adding a `#![type_length_limit="40000000"]` attribute to your crate + = note: consider adding a `#![type_length_limit="26214380"]` attribute to your crate error: aborting due to previous error diff --git a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr index d98da3f10d0eb..7965ff70f693d 100644 --- a/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr +++ b/src/test/ui/issues/issue-37311-type-length-limit/issue-37311.stderr @@ -1,4 +1,4 @@ -error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(), &()), &(&(), &())), &...` +error: reached the type-length limit while instantiating `<(&(&(&(&(&(&(&(&(&(&(&(&(&(&(&(...))))))))))))))) as Foo>::recurse` --> $DIR/issue-37311.rs:13:5 | LL | / fn recurse(&self) { //~ ERROR reached the type-length limit @@ -6,7 +6,7 @@ LL | | (self, self).recurse(); LL | | } | |_____^ | - = note: consider adding a `#![type_length_limit="2097152"]` attribute to your crate + = note: consider adding a `#![type_length_limit="2097149"]` attribute to your crate error: aborting due to previous error diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index 910eca075948a..9d07c86356b67 100644 --- a/src/test/ui/type_length_limit.stderr +++ b/src/test/ui/type_length_limit.stderr @@ -1,6 +1,10 @@ -error: reached the type-length limit while instantiating `std::mem::drop::>` + --> $SRC_DIR/libcore/mem.rs:LL:COL | - = note: consider adding a `#![type_length_limit="512"]` attribute to your crate +LL | pub fn drop(_x: T) { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: consider adding a `#![type_length_limit="1094"]` attribute to your crate error: aborting due to previous error From c50ec78e1d042ef7eb7cf0cd3b8ff6cf982c5fe8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 12:20:59 +0200 Subject: [PATCH 24/68] rustc: remove TyCtxt::parent_def_id in favor of TyCtxt::parent. --- .../error_reporting/nice_region_error/util.rs | 4 ++-- src/librustc/middle/dead.rs | 4 ++-- src/librustc/middle/mem_categorization.rs | 6 ++--- src/librustc/middle/region.rs | 6 ++--- src/librustc/ty/context.rs | 4 ++-- src/librustc/ty/item_path.rs | 22 +++++-------------- src/librustc/ty/mod.rs | 4 ++-- src/librustc/ty/sty.rs | 4 ++-- src/librustc/ty/util.rs | 4 ++-- src/librustc_mir/borrow_check/mod.rs | 4 ++-- src/librustc_mir/hair/pattern/mod.rs | 4 ++-- src/librustc_save_analysis/dump_visitor.rs | 6 ++--- src/librustc_save_analysis/lib.rs | 4 ++-- src/librustc_typeck/astconv.rs | 6 ++--- src/librustdoc/clean/mod.rs | 4 ++-- 15 files changed, 38 insertions(+), 48 deletions(-) diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc/infer/error_reporting/nice_region_error/util.rs index 43590a606ae90..8abe3d8467229 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/util.rs @@ -3,7 +3,7 @@ use hir; use infer::error_reporting::nice_region_error::NiceRegionError; -use ty::{self, Region, Ty}; +use ty::{self, DefIdTree, Region, Ty}; use hir::def_id::DefId; use syntax_pos::Span; @@ -44,7 +44,7 @@ impl<'a, 'gcx, 'tcx> NiceRegionError<'a, 'gcx, 'tcx> { let (id, bound_region) = match *anon_region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), ty::ReEarlyBound(ref ebr) => ( - self.tcx.parent_def_id(ebr.def_id).unwrap(), + self.tcx.parent(ebr.def_id).unwrap(), ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), ), _ => return None, // not a free region diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index abbf0ae210c25..b1332b27db026 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -12,7 +12,7 @@ use hir::CodegenFnAttrFlags; use hir::def_id::{DefId, LOCAL_CRATE}; use lint; use middle::privacy; -use ty::{self, TyCtxt}; +use ty::{self, DefIdTree, TyCtxt}; use util::nodemap::FxHashSet; use rustc_data_structures::fx::FxHashMap; @@ -78,7 +78,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { Def::PrimTy(..) | Def::SelfTy(..) | Def::SelfCtor(..) | Def::Local(..) | Def::Upvar(..) => {} Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => { - if let Some(enum_id) = self.tcx.parent_def_id(variant_id) { + if let Some(enum_id) = self.tcx.parent(variant_id) { self.check_def_id(enum_id); } if !self.ignore_variant_stack.contains(&variant_id) { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 158d5bf9fb394..51cb60c610c1b 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -64,7 +64,7 @@ use hir::Node; use infer::InferCtxt; use hir::def::{Def, CtorKind}; use ty::adjustment; -use ty::{self, Ty, TyCtxt}; +use ty::{self, DefIdTree, Ty, TyCtxt}; use ty::fold::TypeFoldable; use ty::layout::VariantIdx; @@ -1133,7 +1133,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { variant_did: DefId) -> cmt<'tcx> { // univariant enums do not need downcasts - let base_did = self.tcx.parent_def_id(variant_did).unwrap(); + let base_did = self.tcx.parent(variant_did).unwrap(); if self.tcx.adt_def(base_did).variants.len() != 1 { let base_ty = base_cmt.ty; let ret = Rc::new(cmt_ { @@ -1275,7 +1275,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { return Err(()) } Def::VariantCtor(def_id, CtorKind::Fn) => { - let enum_def = self.tcx.parent_def_id(def_id).unwrap(); + let enum_def = self.tcx.parent(def_id).unwrap(); (self.cat_downcast_if_needed(pat, cmt, def_id), self.tcx.adt_def(enum_def).variant_with_id(def_id).fields.len()) } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 31f91a1bae57f..1cb6ee26e225e 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -16,7 +16,7 @@ use rustc_data_structures::sync::Lrc; use syntax::source_map; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; -use ty::TyCtxt; +use ty::{DefIdTree, TyCtxt}; use ty::query::Providers; use hir; @@ -648,7 +648,7 @@ impl<'tcx> ScopeTree { pub fn early_free_scope<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, br: &ty::EarlyBoundRegion) -> Scope { - let param_owner = tcx.parent_def_id(br.def_id).unwrap(); + let param_owner = tcx.parent(br.def_id).unwrap(); let param_owner_id = tcx.hir().as_local_node_id(param_owner).unwrap(); let scope = tcx.hir().maybe_body_owned_by(param_owner_id).map(|body_id| { @@ -677,7 +677,7 @@ impl<'tcx> ScopeTree { -> Scope { let param_owner = match fr.bound_region { ty::BoundRegion::BrNamed(def_id, _) => { - tcx.parent_def_id(def_id).unwrap() + tcx.parent(def_id).unwrap() } _ => fr.scope }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a0da7cf2137d0..65df198dcdc56 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -27,7 +27,7 @@ use ty::subst::{Kind, Substs, Subst}; use ty::ReprOptions; use traits; use traits::{Clause, Clauses, GoalKind, Goal, Goals}; -use ty::{self, Ty, TypeAndMut}; +use ty::{self, DefIdTree, Ty, TypeAndMut}; use ty::{TyS, TyKind, List}; use ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst}; use ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; @@ -1599,7 +1599,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let (suitable_region_binding_scope, bound_region) = match *region { ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region), ty::ReEarlyBound(ref ebr) => ( - self.parent_def_id(ebr.def_id).unwrap(), + self.parent(ebr.def_id).unwrap(), ty::BoundRegion::BrNamed(ebr.def_id, ebr.name), ), _ => return None, // not a free region diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index d84a82e76d68c..26dd6c5341c2e 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -153,13 +153,13 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { data @ DefPathData::ClosureExpr | data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { - let parent_did = self.tcx.parent_def_id(def_id).unwrap(); + let parent_did = self.tcx.parent(def_id).unwrap(); let path = self.print_item_path(parent_did, None, ns); self.path_append(path, &data.as_interned_str().as_symbol().as_str()) }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` - let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); + let parent_def_id = self.tcx.parent(def_id).unwrap(); self.print_item_path(parent_def_id, substs, ns) } } @@ -172,7 +172,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { ns: Namespace, ) -> P::Path { debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); - let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); + let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); // Decide whether to print the parent path for the impl. // Logically, since impls are global, it's never needed, but @@ -185,7 +185,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } let in_self_mod = match characteristic_def_id_of_type(self_ty) { None => false, - Some(ty_def_id) => self.tcx.parent_def_id(ty_def_id) == Some(parent_def_id), + Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id), }; let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); @@ -194,7 +194,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } let in_trait_mod = match impl_trait_ref { None => false, - Some(trait_ref) => self.tcx.parent_def_id(trait_ref.def_id) == Some(parent_def_id), + Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), }; if !in_self_mod && !in_trait_mod { @@ -247,16 +247,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - /// Returns the def-id of `def_id`'s parent in the def tree. If - /// this returns `None`, then `def_id` represents a crate root or - /// inlined root. - pub fn parent_def_id(self, def_id: DefId) -> Option { - let key = self.def_key(def_id); - key.parent.map(|index| DefId { krate: def_id.krate, index: index }) - } -} - /// As a heuristic, when we see an impl, if we see that the /// 'self-type' is a type defined in the same module as the impl, /// we can omit including the path to the impl itself. This @@ -533,7 +523,7 @@ impl ItemPathPrinter for LocalPathPrinter { // pretty printing some span information. This should // only occur very early in the compiler pipeline. // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` - let parent_def_id = self.tcx.parent_def_id(impl_def_id).unwrap(); + let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); let path = self.print_item_path(parent_def_id, None, ns); let span = self.tcx.def_span(impl_def_id); return self.path_append(path, &format!("", span)); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 291b4c7cf8640..c686ca3f6e963 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2871,14 +2871,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn expect_variant_def(self, def: Def) -> &'tcx VariantDef { match def { Def::Variant(did) | Def::VariantCtor(did, ..) => { - let enum_did = self.parent_def_id(did).unwrap(); + let enum_did = self.parent(did).unwrap(); self.adt_def(enum_did).variant_with_id(did) } Def::Struct(did) | Def::Union(did) => { self.adt_def(did).non_enum_variant() } Def::StructCtor(ctor_did, ..) => { - let did = self.parent_def_id(ctor_did).expect("struct ctor has no parent"); + let did = self.parent(ctor_did).expect("struct ctor has no parent"); self.adt_def(did).non_enum_variant() } _ => bug!("expect_variant_def used with unexpected def {:?}", def) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index f4185c9201540..e324b52e52062 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -8,7 +8,7 @@ use middle::region; use polonius_engine::Atom; use rustc_data_structures::indexed_vec::Idx; use ty::subst::{Substs, Subst, Kind, UnpackedKind}; -use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; +use ty::{self, AdtDef, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{List, TyS, ParamEnvAnd, ParamEnv}; use util::captures::Captures; use mir::interpret::{Scalar, Pointer}; @@ -1550,7 +1550,7 @@ impl RegionKind { pub fn free_region_binding_scope(&self, tcx: TyCtxt<'_, '_, '_>) -> DefId { match self { ty::ReEarlyBound(br) => { - tcx.parent_def_id(br.def_id).unwrap() + tcx.parent(br.def_id).unwrap() } ty::ReFree(fr) => fr.scope, _ => bug!("free_region_binding_scope invoked on inappropriate region: {:?}", self), diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 75fc0f716a2f6..ea40d6096181d 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -6,7 +6,7 @@ use hir::map::DefPathData; use hir::{self, Node}; use ich::NodeIdHashingMode; use traits::{self, ObligationCause}; -use ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; +use ty::{self, DefIdTree, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; use ty::subst::{Subst, Substs, UnpackedKind}; use ty::query::TyCtxtAt; use ty::TyKind::*; @@ -551,7 +551,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn closure_base_def_id(self, def_id: DefId) -> DefId { let mut def_id = def_id; while self.is_closure(def_id) { - def_id = self.parent_def_id(def_id).unwrap_or_else(|| { + def_id = self.parent(def_id).unwrap_or_else(|| { bug!("closure {:?} has no parent", def_id); }); } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 5597e4a6c597e..1e9215751ccfd 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -12,7 +12,7 @@ use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Pla use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::bit_set::BitSet; @@ -345,7 +345,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } if tcx.is_closure(curr_def_id) { - curr_def_id = tcx.parent_def_id(curr_def_id) + curr_def_id = tcx.parent(curr_def_id) .expect("a closure must have a parent_def_id"); } else { break SignalledError::NoErrorsSeen; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index fd2f59afda0e6..0387ac276c78b 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -14,7 +14,7 @@ use hair::constant::*; use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability}; use rustc::mir::{UserTypeProjection}; use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; -use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift, UserType}; +use rustc::ty::{self, DefIdTree, Region, TyCtxt, AdtDef, Ty, Lift, UserType}; use rustc::ty::{CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations}; use rustc::ty::subst::{Substs, Kind}; use rustc::ty::layout::VariantIdx; @@ -690,7 +690,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ) -> PatternKind<'tcx> { let mut kind = match def { Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => { - let enum_id = self.tcx.parent_def_id(variant_id).unwrap(); + let enum_id = self.tcx.parent(variant_id).unwrap(); let adt_def = self.tcx.adt_def(enum_id); if adt_def.is_enum() { let substs = match ty.sty { diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 995df3802aabd..0f4fbb37541df 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -16,7 +16,7 @@ use rustc::hir::def::Def as HirDef; use rustc::hir::def_id::DefId; use rustc::session::config::Input; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::path::Path; @@ -1195,7 +1195,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { // The parent def id of a given use tree is always the enclosing item. let parent = self.save_ctxt.tcx.hir().opt_local_def_id(id) - .and_then(|id| self.save_ctxt.tcx.parent_def_id(id)) + .and_then(|id| self.save_ctxt.tcx.parent(id)) .map(::id_from_def_id); match use_tree.kind { @@ -1344,7 +1344,7 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc if !self.span.filter_generated(name_span) { let span = self.span_from_span(name_span); let parent = self.save_ctxt.tcx.hir().opt_local_def_id(item.id) - .and_then(|id| self.save_ctxt.tcx.parent_def_id(id)) + .and_then(|id| self.save_ctxt.tcx.parent(id)) .map(::id_from_def_id); self.dumper.import( &Access { diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 73eb5de5c76f0..f58811a158450 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -38,7 +38,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::privacy::AccessLevels; use rustc::middle::cstore::ExternCrate; use rustc::session::config::{CrateType, Input, OutputType}; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc_typeck::hir_ty_to_ty; use rustc_codegen_utils::link::{filename_for_metadata, out_filename}; use rustc_data_structures::sync::Lrc; @@ -766,7 +766,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { // This is a reference to a tuple struct where the def_id points // to an invisible constructor function. That is not a very useful // def, so adjust to point to the tuple struct itself. - let parent_def_id = self.tcx.parent_def_id(def_id).unwrap(); + let parent_def_id = self.tcx.parent(def_id).unwrap(); Some(Ref { kind: RefKind::Type, span, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 173a851a2f524..1fd7fcc4ad814 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -12,7 +12,7 @@ use middle::resolve_lifetime as rl; use namespace::Namespace; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::traits; -use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; +use rustc::ty::{self, DefIdTree, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::ty::wf::object_region_bounds; @@ -1429,7 +1429,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { -> Ty<'tcx> { let tcx = self.tcx(); - let trait_def_id = tcx.parent_def_id(item_def_id).unwrap(); + let trait_def_id = tcx.parent(item_def_id).unwrap(); self.prohibit_generics(slice::from_ref(item_segment)); @@ -1589,7 +1589,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { } else if last >= 1 && segments[last - 1].args.is_some() { // Everything but the penultimate segment should have no // parameters at all. - let enum_def_id = tcx.parent_def_id(def_id).unwrap(); + let enum_def_id = tcx.parent(def_id).unwrap(); (enum_def_id, last - 1) } else { // FIXME: lint here recommending `Enum::<...>::Variant` form diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index fc0e1d5e5ca79..59d364b1a08c6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -21,7 +21,7 @@ use rustc::hir::{self, GenericArg, HirVec}; use rustc::hir::def::{self, Def, CtorKind, Namespace}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::ty::subst::Substs; -use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; +use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; use rustc::ty::layout::VariantIdx; use rustc::util::nodemap::{FxHashMap, FxHashSet}; @@ -3794,7 +3794,7 @@ pub fn register_def(cx: &DocContext, def: Def) -> DefId { Def::ForeignTy(i) => (i, TypeKind::Foreign), Def::Const(i) => (i, TypeKind::Const), Def::Static(i, _) => (i, TypeKind::Static), - Def::Variant(i) => (cx.tcx.parent_def_id(i).expect("cannot get parent def id"), + Def::Variant(i) => (cx.tcx.parent(i).expect("cannot get parent def id"), TypeKind::Enum), Def::Macro(i, mac_kind) => match mac_kind { MacroKind::Bang => (i, TypeKind::Macro), From bce552a8bbcfc63b88c8bbed36cf25bff0f4b9e3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 12:31:35 +0200 Subject: [PATCH 25/68] rustc: rename item_path to def_path (except the module in ty). --- src/librustc/dep_graph/dep_node.rs | 4 +- src/librustc/hir/def_id.rs | 2 +- src/librustc/infer/error_reporting/mod.rs | 16 ++--- .../nice_region_error/placeholder_error.rs | 4 +- src/librustc/middle/stability.rs | 6 +- src/librustc/mir/mod.rs | 8 +-- src/librustc/traits/error_reporting.rs | 8 +-- src/librustc/traits/mod.rs | 8 +-- src/librustc/traits/object_safety.rs | 2 +- src/librustc/traits/on_unimplemented.rs | 2 +- src/librustc/traits/project.rs | 2 +- src/librustc/ty/error.rs | 14 ++-- src/librustc/ty/item_path.rs | 68 +++++++++---------- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/query/config.rs | 32 ++++----- src/librustc/util/ppaux.rs | 14 ++-- src/librustc_borrowck/borrowck/mod.rs | 8 +-- src/librustc_codegen_utils/symbol_names.rs | 2 +- .../symbol_names_test.rs | 12 ++-- src/librustc_incremental/assert_dep_graph.rs | 2 +- .../persist/dirty_clean.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- .../borrow_check/nll/explain_borrow/mod.rs | 2 +- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/hair/pattern/check_match.rs | 2 +- src/librustc_mir/hair/pattern/mod.rs | 4 +- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 4 +- src/librustc_mir/util/graphviz.rs | 2 +- src/librustc_mir/util/liveness.rs | 2 +- src/librustc_mir/util/pretty.rs | 8 +-- src/librustc_privacy/lib.rs | 2 +- src/librustc_save_analysis/lib.rs | 4 +- src/librustc_typeck/astconv.rs | 6 +- src/librustc_typeck/check/_match.rs | 4 +- src/librustc_typeck/check/compare_method.rs | 2 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/method/suggest.rs | 16 ++--- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/wfcheck.rs | 4 +- src/librustc_typeck/coherence/builtin.rs | 8 +-- src/librustc_typeck/coherence/mod.rs | 6 +- src/librustc_typeck/coherence/orphan.rs | 4 +- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/libsyntax/feature_gate.rs | 2 +- src/test/mir-opt/issue-41697.rs | 2 +- src/test/ui/symbol-names/basic.rs | 2 +- src/test/ui/symbol-names/basic.stderr | 6 +- src/test/ui/symbol-names/impl1.rs | 4 +- src/test/ui/symbol-names/impl1.stderr | 12 ++-- 54 files changed, 175 insertions(+), 175 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 05f331145afe2..3011bf921457a 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -721,7 +721,7 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefId { } fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { - tcx.item_path_str(*self) + tcx.def_path_str(*self) } } @@ -733,7 +733,7 @@ impl<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> DepNodeParams<'a, 'gcx, 'tcx> for DefIndex { } fn to_debug_str(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> String { - tcx.item_path_str(DefId::local(*self)) + tcx.def_path_str(DefId::local(*self)) } } diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs index 9181076740ba0..50358383bb155 100644 --- a/src/librustc/hir/def_id.rs +++ b/src/librustc/hir/def_id.rs @@ -249,7 +249,7 @@ impl DefId { if self.is_local() && self.index == CRATE_DEF_INDEX { format!("top-level module") } else { - format!("module `{}`", tcx.item_path_str(*self)) + format!("module `{}`", tcx.def_path_str(*self)) } } } diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 0d3262f1c8356..3e09b1a78ba98 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -449,10 +449,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Only external crates, if either is from a local // module we could have false positives if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { - let exp_path = self.tcx.item_path_str(did1); - let found_path = self.tcx.item_path_str(did2); - let exp_abs_path = self.tcx.absolute_item_path_str(did1); - let found_abs_path = self.tcx.absolute_item_path_str(did2); + let exp_path = self.tcx.def_path_str(did1); + let found_path = self.tcx.def_path_str(did2); + let exp_abs_path = self.tcx.absolute_def_path_str(did1); + let found_abs_path = self.tcx.absolute_def_path_str(did2); // We compare strings because DefPath can be different // for imported and non-imported crates if exp_path == found_path || exp_abs_path == found_abs_path { @@ -650,7 +650,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return Some(()); } if let &ty::Adt(def, _) = &ta.sty { - let path_ = self.tcx.item_path_str(def.did.clone()); + let path_ = self.tcx.def_path_str(def.did.clone()); if path_ == other_path { self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); return Some(()); @@ -755,8 +755,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let sub_no_defaults_1 = self.strip_generic_default_params(def1.did, sub1); let sub_no_defaults_2 = self.strip_generic_default_params(def2.did, sub2); let mut values = (DiagnosticStyledString::new(), DiagnosticStyledString::new()); - let path1 = self.tcx.item_path_str(def1.did.clone()); - let path2 = self.tcx.item_path_str(def2.did.clone()); + let path1 = self.tcx.def_path_str(def1.did.clone()); + let path2 = self.tcx.def_path_str(def2.did.clone()); if def1.did == def2.did { // Easy case. Replace same types with `_` to shorten the output and highlight // the differing ones. @@ -1011,7 +1011,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if exp_is_struct && &exp_found.expected == ret_ty.skip_binder() { let message = format!( "did you mean `{}(/* fields */)`?", - self.tcx.item_path_str(def_id) + self.tcx.def_path_str(def_id) ); diag.span_label(span, message); } diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs index 0dda636a9bd53..e534ae3b29a38 100644 --- a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -186,7 +186,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { cause.span(&self.tcx), &format!( "implementation of `{}` is not general enough", - self.tcx.item_path_str(trait_def_id), + self.tcx.def_path_str(trait_def_id), ), ); @@ -194,7 +194,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { ObligationCauseCode::ItemObligation(def_id) => { err.note(&format!( "Due to a where-clause on `{}`,", - self.tcx.item_path_str(def_id), + self.tcx.def_path_str(def_id), )); } _ => (), diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 918e286c435bc..3e62fca636641 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -604,7 +604,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); if let Some(since) = deprecated_in_future_version { - let path = self.item_path_str(def_id); + let path = self.def_path_str(def_id); let message = format!("use of item '{}' \ that will be deprecated in future version {}", path, @@ -616,7 +616,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { &message, lint::builtin::DEPRECATED_IN_FUTURE); } else if !skip { - let path = self.item_path_str(def_id); + let path = self.def_path_str(def_id); let message = format!("use of deprecated item '{}'", path); lint_deprecated(def_id, id, @@ -642,7 +642,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(&Stability{rustc_depr: Some(attr::RustcDeprecation { reason, since }), ..}) = stability { if let Some(id) = id { - let path = self.item_path_str(def_id); + let path = self.def_path_str(def_id); if deprecation_in_effect(&since.as_str()) { let message = format!("use of deprecated item '{}'", path); lint_deprecated(def_id, diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 06e0f2a587202..00bc28ef0cb18 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2043,7 +2043,7 @@ impl<'tcx> Debug for Place<'tcx> { Static(box self::Static { def_id, ty }) => write!( fmt, "({}: {:?})", - ty::tls::with(|tcx| tcx.item_path_str(def_id)), + ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty ), Promoted(ref promoted) => write!(fmt, "({:?}: {:?})", promoted.0, promoted.1), @@ -2701,7 +2701,7 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul } // print function definitions if let FnDef(did, _) = ty.sty { - return write!(f, "{}", item_path_str(did)); + return write!(f, "{}", def_path_str(did)); } // print string literals if let ConstValue::Slice(ptr, len) = value { @@ -2726,8 +2726,8 @@ pub fn fmt_const_val(f: &mut impl Write, const_val: ty::Const<'_>) -> fmt::Resul write!(f, "{:?}:{}", value, ty) } -fn item_path_str(def_id: DefId) -> String { - ty::tls::with(|tcx| tcx.item_path_str(def_id)) +fn def_path_str(def_id: DefId) -> String { + ty::tls::with(|tcx| tcx.def_path_str(def_id)) } impl<'tcx> graph::DirectedGraph for Mir<'tcx> { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index d13562d7b29c3..89585cdef8495 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1239,11 +1239,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size", - self.item_path_str(type_def_id)); + self.def_path_str(type_def_id)); err.span_label(span, "recursive type has infinite size"); err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \ at some point to make `{}` representable", - self.item_path_str(type_def_id))); + self.def_path_str(type_def_id))); err } @@ -1253,7 +1253,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { violations: Vec) -> DiagnosticBuilder<'tcx> { - let trait_str = self.item_path_str(trait_def_id); + let trait_str = self.def_path_str(trait_def_id); let span = self.sess.source_map().def_span(span); let mut err = struct_span_err!( self.sess, span, E0038, @@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { region, object_ty)); } ObligationCauseCode::ItemObligation(item_def_id) => { - let item_name = tcx.item_path_str(item_def_id); + let item_name = tcx.def_path_str(item_def_id); let msg = format!("required by `{}`", item_name); if let Some(sp) = tcx.hir().span_if_local(item_def_id) { diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 68383bef37a6a..2172427e9c6ff 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -647,7 +647,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( ) -> bool { debug!("type_known_to_meet_bound_modulo_regions(ty={:?}, bound={:?})", ty, - infcx.tcx.item_path_str(def_id)); + infcx.tcx.def_path_str(def_id)); let trait_ref = ty::TraitRef { def_id, @@ -662,7 +662,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( let result = infcx.predicate_must_hold_modulo_regions(&obligation); debug!("type_known_to_meet_ty={:?} bound={} => {:?}", - ty, infcx.tcx.item_path_str(def_id), result); + ty, infcx.tcx.def_path_str(def_id), result); if result && (ty.has_infer_types() || ty.has_closure_types()) { // Because of inference "guessing", selection can sometimes claim @@ -689,13 +689,13 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'gcx, 'tcx>( Ok(()) => { debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} success", ty, - infcx.tcx.item_path_str(def_id)); + infcx.tcx.def_path_str(def_id)); true } Err(e) => { debug!("type_known_to_meet_bound_modulo_regions: ty={:?} bound={} errors={:?}", ty, - infcx.tcx.item_path_str(def_id), + infcx.tcx.def_path_str(def_id), e); false } diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index c37dc2a855ed0..7e1e6d207ebd5 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { ast::CRATE_NODE_ID, *span, &format!("the trait `{}` cannot be made into an object", - self.item_path_str(trait_def_id)), + self.def_path_str(trait_def_id)), &violation.error_msg()); false } else { diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc/traits/on_unimplemented.rs index 3ec901f50e4cc..37e7486e89084 100644 --- a/src/librustc/traits/on_unimplemented.rs +++ b/src/librustc/traits/on_unimplemented.rs @@ -276,7 +276,7 @@ impl<'a, 'gcx, 'tcx> OnUnimplementedFormatString { -> String { let name = tcx.item_name(trait_ref.def_id); - let trait_str = tcx.item_path_str(trait_ref.def_id); + let trait_str = tcx.def_path_str(trait_ref.def_id); let generics = tcx.generics_of(trait_ref.def_id); let generic_map = generics.params.iter().filter_map(|param| { let value = match param.kind { diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index bec45046cb93e..99cc4d27692cc 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1546,7 +1546,7 @@ fn assoc_ty_def<'cx, 'gcx, 'tcx>( // should have failed in astconv. bug!("No associated type `{}` for {}", assoc_ty_name, - tcx.item_path_str(impl_def_id)) + tcx.def_path_str(impl_def_id)) } } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index f444013e2a3bd..00e3de826d551 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -111,9 +111,9 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { Traits(values) => ty::tls::with(|tcx| { report_maybe_different(f, &format!("trait `{}`", - tcx.item_path_str(values.expected)), + tcx.def_path_str(values.expected)), &format!("trait `{}`", - tcx.item_path_str(values.found))) + tcx.def_path_str(values.found))) }), IntMismatch(ref values) => { write!(f, "expected `{:?}`, found `{:?}`", @@ -132,8 +132,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { } ProjectionMismatched(ref values) => ty::tls::with(|tcx| { write!(f, "expected {}, found {}", - tcx.item_path_str(values.expected), - tcx.item_path_str(values.found)) + tcx.def_path_str(values.expected), + tcx.def_path_str(values.found)) }), ProjectionBoundsLength(ref values) => { write!(f, "expected {} associated type bindings, found {}", @@ -155,8 +155,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::Uint(_) | ty::Float(_) | ty::Str | ty::Never => self.to_string().into(), ty::Tuple(ref tys) if tys.is_empty() => self.to_string().into(), - ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.item_path_str(def.did)).into(), - ty::Foreign(def_id) => format!("extern type `{}`", tcx.item_path_str(def_id)).into(), + ty::Adt(def, _) => format!("{} `{}`", def.descr(), tcx.def_path_str(def.did)).into(), + ty::Foreign(def_id) => format!("extern type `{}`", tcx.def_path_str(def_id)).into(), ty::Array(_, n) => match n { ty::LazyConst::Evaluated(n) => match n.assert_usize(tcx) { Some(n) => format!("array of {} elements", n).into(), @@ -185,7 +185,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::FnPtr(_) => "fn pointer".into(), ty::Dynamic(ref inner, ..) => { if let Some(principal) = inner.principal() { - format!("trait {}", tcx.item_path_str(principal.def_id())).into() + format!("trait {}", tcx.def_path_str(principal.def_id())).into() } else { "trait".into() } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 26dd6c5341c2e..7969046d0cb05 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -16,7 +16,7 @@ thread_local! { static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); } -/// Enforces that item_path_str always returns an absolute path and +/// Enforces that def_path_str always returns an absolute path and /// also enables "type-based" impl paths. This is used when building /// symbols that contain types, where we want the crate name to be /// part of the symbol. @@ -56,7 +56,7 @@ pub fn with_crate_prefix R, R>(f: F) -> R { } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - // HACK(eddyb) get rid of `item_path_str` and/or pass `Namespace` explicitly always + // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always // (but also some things just print a `DefId` generally so maybe we need this?) fn guess_def_namespace(self, def_id: DefId) -> Namespace { match self.def_key(def_id).disambiguated_data.data { @@ -76,52 +76,52 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns a string identifying this def-id. This string is /// suitable for user output. It is relative to the current crate /// root, unless with_forced_absolute_paths was used. - pub fn item_path_str_with_substs_and_ns( + pub fn def_path_str_with_substs_and_ns( self, def_id: DefId, substs: Option<&Substs<'tcx>>, ns: Namespace, ) -> String { - debug!("item_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); + debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); if FORCE_ABSOLUTE.with(|force| force.get()) { - PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id, substs, ns) + PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns) } else { - PrintCx::new(self, LocalPathPrinter).print_item_path(def_id, substs, ns) + PrintCx::new(self, LocalPathPrinter).print_def_path(def_id, substs, ns) } } /// Returns a string identifying this def-id. This string is /// suitable for user output. It is relative to the current crate /// root, unless with_forced_absolute_paths was used. - pub fn item_path_str(self, def_id: DefId) -> String { + pub fn def_path_str(self, def_id: DefId) -> String { let ns = self.guess_def_namespace(def_id); - self.item_path_str_with_substs_and_ns(def_id, None, ns) + self.def_path_str_with_substs_and_ns(def_id, None, ns) } /// Returns a string identifying this local node-id. pub fn node_path_str(self, id: ast::NodeId) -> String { - self.item_path_str(self.hir().local_def_id(id)) + self.def_path_str(self.hir().local_def_id(id)) } /// Returns a string identifying this def-id. This string is /// suitable for user output. It always begins with a crate identifier. - pub fn absolute_item_path_str(self, def_id: DefId) -> String { - debug!("absolute_item_path_str: def_id={:?}", def_id); + pub fn absolute_def_path_str(self, def_id: DefId) -> String { + debug!("absolute_def_path_str: def_id={:?}", def_id); let ns = self.guess_def_namespace(def_id); - PrintCx::new(self, AbsolutePathPrinter).print_item_path(def_id, None, ns) + PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns) } } impl PrintCx<'a, 'gcx, 'tcx, P> { - pub fn default_print_item_path( + pub fn default_print_def_path( &mut self, def_id: DefId, substs: Option<&Substs<'tcx>>, ns: Namespace, ) -> P::Path { - debug!("default_print_item_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); + debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); let key = self.tcx.def_key(def_id); - debug!("default_print_item_path: key={:?}", key); + debug!("default_print_def_path: key={:?}", key); match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); @@ -154,13 +154,13 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { data @ DefPathData::ImplTrait | data @ DefPathData::GlobalMetaData(..) => { let parent_did = self.tcx.parent(def_id).unwrap(); - let path = self.print_item_path(parent_did, None, ns); + let path = self.print_def_path(parent_did, None, ns); self.path_append(path, &data.as_interned_str().as_symbol().as_str()) }, DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` let parent_def_id = self.tcx.parent(def_id).unwrap(); - self.print_item_path(parent_def_id, substs, ns) + self.print_def_path(parent_def_id, substs, ns) } } } @@ -201,7 +201,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - let path = self.print_item_path(parent_def_id, None, ns); + let path = self.print_def_path(parent_def_id, None, ns); if let Some(trait_ref) = impl_trait_ref { return self.path_append(path, &format!("", trait_ref, self_ty)); } else { @@ -223,13 +223,13 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { match self_ty.sty { ty::Adt(adt_def, substs) => { // FIXME(eddyb) this should recurse to build the path piecewise. - // self.print_item_path(adt_def.did, Some(substs), ns) + // self.print_def_path(adt_def.did, Some(substs), ns) let mut s = String::new(); ::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap(); self.path_impl(&s) } - ty::Foreign(did) => self.print_item_path(did, None, ns), + ty::Foreign(did) => self.print_def_path(did, None, ns), ty::Bool | ty::Char | @@ -300,13 +300,13 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { pub trait ItemPathPrinter: Sized { type Path; - fn print_item_path( + fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&Substs<'tcx>>, ns: Namespace, ) -> Self::Path { - self.default_print_item_path(def_id, substs, ns) + self.default_print_def_path(def_id, substs, ns) } fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, @@ -356,12 +356,12 @@ impl LocalPathPrinter { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_item_path( + fn try_print_visible_def_path( self: &mut PrintCx<'_, '_, '_, Self>, def_id: DefId, ns: Namespace, ) -> Option<::Path> { - debug!("try_print_visible_item_path: def_id={:?}", def_id); + debug!("try_print_visible_def_path: def_id={:?}", def_id); // If `def_id` is a direct or injected extern crate, return the // path to the crate followed by the path to the item within the crate. @@ -389,9 +389,9 @@ impl LocalPathPrinter { span, .. }) => { - debug!("try_print_visible_item_path: def_id={:?}", def_id); + debug!("try_print_visible_def_path: def_id={:?}", def_id); let path = if !span.is_dummy() { - self.print_item_path(def_id, None, ns) + self.print_def_path(def_id, None, ns) } else { self.path_crate(cnum) }; @@ -411,7 +411,7 @@ impl LocalPathPrinter { let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); let mut cur_def_key = self.tcx.def_key(def_id); - debug!("try_print_visible_item_path: cur_def_key={:?}", cur_def_key); + debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); // For a UnitStruct or TupleStruct we want the name of its parent rather than . if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { @@ -424,12 +424,12 @@ impl LocalPathPrinter { } let visible_parent = visible_parent_map.get(&def_id).cloned()?; - let path = self.try_print_visible_item_path(visible_parent, ns)?; + let path = self.try_print_visible_def_path(visible_parent, ns)?; let actual_parent = self.tcx.parent(def_id); let data = cur_def_key.disambiguated_data.data; debug!( - "try_print_visible_item_path: data={:?} visible_parent={:?} actual_parent={:?}", + "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}", data, visible_parent, actual_parent, ); @@ -487,7 +487,7 @@ impl LocalPathPrinter { }) }, }; - debug!("try_print_visible_item_path: symbol={:?}", symbol); + debug!("try_print_visible_def_path: symbol={:?}", symbol); Some(self.path_append(path, &symbol)) } } @@ -495,14 +495,14 @@ impl LocalPathPrinter { impl ItemPathPrinter for LocalPathPrinter { type Path = String; - fn print_item_path( + fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option<&Substs<'tcx>>, ns: Namespace, ) -> Self::Path { - self.try_print_visible_item_path(def_id, ns) - .unwrap_or_else(|| self.default_print_item_path(def_id, substs, ns)) + self.try_print_visible_def_path(def_id, ns) + .unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns)) } fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, @@ -524,7 +524,7 @@ impl ItemPathPrinter for LocalPathPrinter { // only occur very early in the compiler pipeline. // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); - let path = self.print_item_path(parent_def_id, None, ns); + let path = self.print_def_path(parent_def_id, None, ns); let span = self.tcx.def_span(impl_def_id); return self.path_append(path, &format!("", span)); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c686ca3f6e963..4852193e8c3f6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2021,7 +2021,7 @@ impl ReprOptions { } // This is here instead of layout because the choice must make it into metadata. - if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) { + if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { flags.insert(ReprFlags::IS_LINEAR); } ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags } diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index c4757574ffe4d..f4bf2156aa617 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -65,7 +65,7 @@ pub(super) trait QueryDescription<'tcx>: QueryAccessors<'tcx> { impl<'tcx, M: QueryAccessors<'tcx, Key=DefId>> QueryDescription<'tcx> for M { default fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { if !tcx.sess.verbose() { - format!("processing `{}`", tcx.item_path_str(def_id)).into() + format!("processing `{}`", tcx.def_path_str(def_id)).into() } else { let name = unsafe { ::std::intrinsics::type_name::() }; format!("processing {:?} with query `{}`", def_id, name).into() @@ -286,7 +286,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::layout_raw<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::super_predicates_of<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("computing the supertraits of `{}`", - tcx.item_path_str(def_id)).into() + tcx.def_path_str(def_id)).into() } } @@ -307,7 +307,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::type_param_predicates<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::coherent_trait<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("coherence checking all impls of trait `{}`", - tcx.item_path_str(def_id)).into() + tcx.def_path_str(def_id)).into() } } @@ -344,7 +344,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::inferred_outlives_crate<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::mir_shims<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> { format!("generating MIR shim for `{}`", - tcx.item_path_str(def.def_id())).into() + tcx.def_path_str(def.def_id())).into() } } @@ -373,7 +373,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_eval<'tcx> { ) -> Cow<'static, str> { format!( "const-evaluating + checking `{}`", - tcx.item_path_str(key.value.instance.def.def_id()), + tcx.def_path_str(key.value.instance.def.def_id()), ).into() } @@ -394,7 +394,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_eval_raw<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> Cow<'static, str> { - format!("const-evaluating `{}`", tcx.item_path_str(key.value.instance.def.def_id())).into() + format!("const-evaluating `{}`", tcx.def_path_str(key.value.instance.def.def_id())).into() } #[inline] @@ -492,7 +492,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::trait_of_item<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_static<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("const checking if rvalue is promotable to static `{}`", - tcx.item_path_str(def_id)).into() + tcx.def_path_str(def_id)).into() } #[inline] @@ -511,21 +511,21 @@ impl<'tcx> QueryDescription<'tcx> for queries::const_is_rvalue_promotable_to_sta impl<'tcx> QueryDescription<'tcx> for queries::rvalue_promotable_map<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("checking which parts of `{}` are promotable to static", - tcx.item_path_str(def_id)).into() + tcx.def_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_mir_available<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { format!("checking if item is mir available: `{}`", - tcx.item_path_str(def_id)).into() + tcx.def_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>)) -> Cow<'static, str> { - format!("checking if `{}` fulfills its obligations", tcx.item_path_str(key.1.def_id())) + format!("checking if `{}` fulfills its obligations", tcx.def_path_str(key.1.def_id())) .into() } @@ -544,19 +544,19 @@ impl<'tcx> QueryDescription<'tcx> for queries::codegen_fulfill_obligation<'tcx> impl<'tcx> QueryDescription<'tcx> for queries::trait_impls_of<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { - format!("trait impls of `{}`", tcx.item_path_str(def_id)).into() + format!("trait impls of `{}`", tcx.def_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_object_safe<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { - format!("determine object safety of trait `{}`", tcx.item_path_str(def_id)).into() + format!("determine object safety of trait `{}`", tcx.def_path_str(def_id)).into() } } impl<'tcx> QueryDescription<'tcx> for queries::is_const_fn_raw<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def_id: DefId) -> Cow<'static, str> { - format!("checking if item is const fn: `{}`", tcx.item_path_str(def_id)).into() + format!("checking if item is const fn: `{}`", tcx.def_path_str(def_id)).into() } } @@ -856,7 +856,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::output_filenames<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::vtable_methods<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, key: ty::PolyTraitRef<'tcx> ) -> Cow<'static, str> { - format!("finding all methods for trait {}", tcx.item_path_str(key.def_id())).into() + format!("finding all methods for trait {}", tcx.def_path_str(key.def_id())).into() } } @@ -900,7 +900,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::optimized_mir<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::substitute_normalize_and_test_predicates<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, key: (DefId, &'tcx Substs<'tcx>)) -> Cow<'static, str> { - format!("testing substituted normalized predicates:`{}`", tcx.item_path_str(key.0)).into() + format!("testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0)).into() } } @@ -918,7 +918,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::target_features_whitelist<'tcx> { impl<'tcx> QueryDescription<'tcx> for queries::instance_def_size_estimate<'tcx> { fn describe(tcx: TyCtxt<'_, '_, '_>, def: ty::InstanceDef<'tcx>) -> Cow<'static, str> { - format!("estimating size for `{}`", tcx.item_path_str(def.def_id())).into() + format!("estimating size for `{}`", tcx.def_path_str(def.def_id())).into() } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 22824a685cd7c..c351807ef5b91 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -320,7 +320,7 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { // FIXME(eddyb) recurse through printing a path via `self`, instead // instead of using the `tcx` method that produces a `String`. print!(self, write("{}", - self.tcx.item_path_str_with_substs_and_ns(def_id, Some(substs), ns)))?; + self.tcx.def_path_str_with_substs_and_ns(def_id, Some(substs), ns)))?; // For impls, the above call already prints relevant generics args. if let DefPathData::Impl = key.disambiguated_data.data { @@ -510,7 +510,7 @@ define_print! { if let Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - print!(cx, write("{}", cx.tcx.item_path_str(principal.def_id)))?; + print!(cx, write("{}", cx.tcx.def_path_str(principal.def_id)))?; cx.fn_sig(args, false, proj.ty)?; resugared_principal = true; } @@ -533,7 +533,7 @@ define_print! { // Builtin bounds. let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { - cx.tcx.item_path_str(did) + cx.tcx.def_path_str(did) }).collect(); // The auto traits come ordered by `DefPathHash`. While @@ -576,7 +576,7 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |cx| { - print!(cx, write("{}", cx.tcx.item_path_str(self.def_id))) + print!(cx, write("{}", cx.tcx.def_path_str(self.def_id))) }) } } @@ -584,7 +584,7 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |cx| { - print!(cx, write("{}", cx.tcx.item_path_str(self.did))) + print!(cx, write("{}", cx.tcx.def_path_str(self.did))) }) } } @@ -1440,11 +1440,11 @@ define_print! { ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")), ty::Predicate::ObjectSafe(trait_def_id) => { print!(cx, write("the trait `{}` is object-safe", - cx.tcx.item_path_str(trait_def_id))) + cx.tcx.def_path_str(trait_def_id))) } ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => { print!(cx, write("the closure `{}` implements the trait `{}`", - cx.tcx.item_path_str(closure_def_id), kind)) + cx.tcx.def_path_str(closure_def_id), kind)) } ty::Predicate::ConstEvaluatable(def_id, substs) => { print!(cx, write("the constant `"))?; diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 5c11d622d0a8a..194c37a6179ea 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1407,7 +1407,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out.push('('); self.append_loan_path_to_string(&lp_base, out); out.push_str(DOWNCAST_PRINTED_OPERATOR); - out.push_str(&self.tcx.item_path_str(variant_def_id)); + out.push_str(&self.tcx.def_path_str(variant_def_id)); out.push(')'); } @@ -1444,7 +1444,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { out.push('('); self.append_autoderefd_loan_path_to_string(&lp_base, out); out.push_str(DOWNCAST_PRINTED_OPERATOR); - out.push_str(&self.tcx.item_path_str(variant_def_id)); + out.push_str(&self.tcx.def_path_str(variant_def_id)); out.push(')'); } @@ -1524,7 +1524,7 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> { LpDowncast(ref lp, variant_def_id) => { let variant_str = if variant_def_id.is_local() { - ty::tls::with(|tcx| tcx.item_path_str(variant_def_id)) + ty::tls::with(|tcx| tcx.def_path_str(variant_def_id)) } else { format!("{:?}", variant_def_id) }; @@ -1559,7 +1559,7 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> { LpDowncast(ref lp, variant_def_id) => { let variant_str = if variant_def_id.is_local() { - ty::tls::with(|tcx| tcx.item_path_str(variant_def_id)) + ty::tls::with(|tcx| tcx.def_path_str(variant_def_id)) } else { format!("{:?}", variant_def_id) }; diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 64787a0e9875b..6e159ca9e57aa 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -225,7 +225,7 @@ fn get_symbol_hash<'a, 'tcx>( fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { item_path::with_forced_absolute_paths(|| { PrintCx::new(tcx, SymbolPathPrinter) - .print_item_path(def_id, None, Namespace::ValueNS) + .print_def_path(def_id, None, Namespace::ValueNS) .into_interned() }) } diff --git a/src/librustc_codegen_utils/symbol_names_test.rs b/src/librustc_codegen_utils/symbol_names_test.rs index a11eb4da66ade..265f100c34d6d 100644 --- a/src/librustc_codegen_utils/symbol_names_test.rs +++ b/src/librustc_codegen_utils/symbol_names_test.rs @@ -1,7 +1,7 @@ //! Walks the crate looking for items/impl-items/trait-items that have -//! either a `rustc_symbol_name` or `rustc_item_path` attribute and +//! either a `rustc_symbol_name` or `rustc_def_path` attribute and //! generates an error giving, respectively, the symbol name or -//! item-path. This is used for unit testing the code that generates +//! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. use rustc::hir; @@ -11,7 +11,7 @@ use syntax::ast; use rustc_mir::monomorphize::Instance; const SYMBOL_NAME: &'static str = "rustc_symbol_name"; -const ITEM_PATH: &'static str = "rustc_item_path"; +const DEF_PATH: &'static str = "rustc_def_path"; pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // if the `rustc_attrs` feature is not enabled, then the @@ -42,9 +42,9 @@ impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { let instance = Instance::mono(tcx, def_id); let name = self.tcx.symbol_name(instance); tcx.sess.span_err(attr.span, &format!("symbol-name({})", name)); - } else if attr.check_name(ITEM_PATH) { - let path = tcx.item_path_str(def_id); - tcx.sess.span_err(attr.span, &format!("item-path({})", path)); + } else if attr.check_name(DEF_PATH) { + let path = tcx.def_path_str(def_id); + tcx.sess.span_err(attr.span, &format!("def-path({})", path)); } // (*) The formatting of `tag({})` is chosen so that tests can elect diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 57ab48493fa93..9a10a497ff165 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -206,7 +206,7 @@ fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx.sess.span_err( target_span, &format!("no path from `{}` to `{}`", - tcx.item_path_str(source_def_id), + tcx.def_path_str(source_def_id), target_pass)); } else { tcx.sess.span_err( diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 3ff4d2ec38dff..0f7aa69c97af7 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> DirtyCleanVisitor<'a, 'tcx> { if let Some(def_id) = dep_node.extract_def_id(self.tcx) { format!("{:?}({})", dep_node.kind, - self.tcx.item_path_str(def_id)) + self.tcx.def_path_str(def_id)) } else { format!("{:?}({:?})", dep_node.kind, dep_node.hash) } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index acf5da1e1886a..143c0af00f220 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -177,7 +177,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { for attr in cx.tcx.get_attrs(def_id).iter() { if attr.check_name("must_use") { let msg = format!("unused {}`{}`{} that must be used", - descr_pre_path, cx.tcx.item_path_str(def_id), descr_post_path); + descr_pre_path, cx.tcx.def_path_str(def_id), descr_post_path); let mut err = cx.struct_span_lint(UNUSED_MUST_USE, sp, &msg); // check for #[must_use = "..."] if let Some(note) = attr.value_str() { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 1e9215751ccfd..a035f3fab68a6 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -68,7 +68,7 @@ pub fn provide(providers: &mut Providers) { fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> BorrowCheckResult<'tcx> { let input_mir = tcx.mir_validated(def_id); - debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); + debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); let mut return_early; diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 968c0f53a4852..068bc2bfa9011 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -86,7 +86,7 @@ impl BorrowExplanation { // If type is an ADT that implements Drop, then // simplify output by reporting just the ADT name. ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => - ("`Drop` code", format!("type `{}`", tcx.item_path_str(adt.did))), + ("`Drop` code", format!("type `{}`", tcx.def_path_str(adt.did))), // Otherwise, just report the whole type (and use // the intentionally fuzzy phrase "destructor") diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index f83a930353b73..aa59c31fb3dad 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -149,7 +149,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( assert!(!layout.is_unsized()); let ret = ecx.allocate(layout, MemoryKind::Stack); - let name = ty::tls::with(|tcx| tcx.item_path_str(cid.instance.def_id())); + let name = ty::tls::with(|tcx| tcx.def_path_str(cid.instance.def_id())); let prom = cid.promoted.map_or(String::new(), |p| format!("::promoted[{:?}]", p)); trace!("eval_body_using_ecx: pushing stack frame for global: {}{}", name, prom); assert!(mir.arg_count == 0); diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 10a4575d81220..6e19ac7ddf866 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -308,7 +308,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor, pat: &Pat) { if edef.is_enum() && edef.variants.iter().any(|variant| { variant.ident == ident && variant.ctor_kind == CtorKind::Const }) { - let ty_path = cx.tcx.item_path_str(edef.did); + let ty_path = cx.tcx.def_path_str(edef.did); let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170, "pattern binding `{}` is named the same as one \ of the variants of the type `{}`", diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 0387ac276c78b..6eccbda72caae 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -924,8 +924,8 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { ty::Adt(adt_def, _) if !self.tcx.has_attr(adt_def.did, "structural_match") => { let msg = format!("to use a constant of type `{}` in a pattern, \ `{}` must be annotated with `#[derive(PartialEq, Eq)]`", - self.tcx.item_path_str(adt_def.did), - self.tcx.item_path_str(adt_def.did)); + self.tcx.def_path_str(adt_def.did), + self.tcx.def_path_str(adt_def.did)); self.tcx.sess.span_err(span, &msg); PatternKind::Wild }, diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 34443bb353e0e..6435e96b1d3e1 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -276,7 +276,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { Ok(self.tcx.optimized_mir(did)) } else { - err!(NoMirFor(self.tcx.item_path_str(def_id))) + err!(NoMirFor(self.tcx.def_path_str(def_id))) }, _ => Ok(self.tcx.instance_mir(instance)), } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 2d941902debc3..8402460035aca 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -891,7 +891,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { } else { let mut err = self.tcx.sess.struct_span_err(self.span, &format!("`{}` is not yet stable as a const fn", - self.tcx.item_path_str(def_id))); + self.tcx.def_path_str(def_id))); if nightly_options::is_nightly_build() { help!(&mut err, "add `#![feature({})]` to the \ diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 36a6279e50320..bae2bf7824ecd 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -26,10 +26,10 @@ impl MirPass for SanityCheck { let def_id = src.def_id; let id = tcx.hir().as_local_node_id(def_id).unwrap(); if !tcx.has_attr(def_id, "rustc_mir") { - debug!("skipping rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); return; } else { - debug!("running rustc_peek::SanityCheck on {}", tcx.item_path_str(def_id)); + debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); } let attributes = tcx.get_attrs(def_id); diff --git a/src/librustc_mir/util/graphviz.rs b/src/librustc_mir/util/graphviz.rs index e7cc3ba0c4d72..2995ac9362bb7 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -128,7 +128,7 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &Mir, w: &mut W) -> io::Result<()> { - write!(w, " label=( } let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below - tcx.item_path_str(source.def_id) + tcx.def_path_str(source.def_id) }); dump_matched_mir_node(tcx, pass_name, &node_path, source, mir, map, result); } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 3a15356806a97..e441345b61c1d 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -81,7 +81,7 @@ pub fn dump_mir<'a, 'gcx, 'tcx, F>( let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below - tcx.item_path_str(source.def_id) + tcx.def_path_str(source.def_id) }); dump_matched_mir_node( tcx, @@ -106,7 +106,7 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>( }; let node_path = item_path::with_forced_impl_filename_line(|| { // see notes on #41697 below - tcx.item_path_str(source.def_id) + tcx.def_path_str(source.def_id) }); filters.split('|').any(|or_filter| { or_filter.split('&').all(|and_filter| { @@ -116,7 +116,7 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>( } // #41697 -- we use `with_forced_impl_filename_line()` because -// `item_path_str()` would otherwise trigger `type_of`, and this can +// `def_path_str()` would otherwise trigger `type_of`, and this can // run while we are already attempting to evaluate `type_of`. fn dump_matched_mir_node<'a, 'gcx, 'tcx, F>( @@ -582,7 +582,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> i item_path::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere - write!(w, " {}", tcx.item_path_str(src.def_id)) + write!(w, " {}", tcx.def_path_str(src.def_id)) })?; match (body_owner_kind, src.promoted) { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 9004f4c35e6b5..127c68957dd7c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -768,7 +768,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { let def_id = self.tcx.adjust_ident(ident, def.did, self.current_item).1; if !def.is_enum() && !field.vis.is_accessible_from(def_id, self.tcx) { struct_span_err!(self.tcx.sess, span, E0451, "field `{}` of {} `{}` is private", - field.ident, def.variant_descr(), self.tcx.item_path_str(def.did)) + field.ident, def.variant_descr(), self.tcx.def_path_str(def.did)) .span_label(span, format!("field `{}` is private", field.ident)) .emit(); } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index f58811a158450..a14454c2fa639 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -426,7 +426,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { if let Some(def_id) = trait_id { // A method in a trait impl. qualname.push_str(" as "); - qualname.push_str(&self.tcx.item_path_str(def_id)); + qualname.push_str(&self.tcx.def_path_str(def_id)); self.tcx .associated_items(def_id) .find(|item| item.ident.name == ident.name) @@ -466,7 +466,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } ( - format!("::{}", self.tcx.item_path_str(def_id)), + format!("::{}", self.tcx.def_path_str(def_id)), Some(def_id), None, docs, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1fd7fcc4ad814..8cec3fed8a7ba 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -898,7 +898,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { "the value of the associated type `{}` (from the trait `{}`) \ is already specified", binding.item_name, - tcx.item_path_str(assoc_ty.container.id())) + tcx.def_path_str(assoc_ty.container.id())) .span_label(binding.span, "re-bound here") .span_label(*prev_span, format!("`{}` bound here first", binding.item_name)) .emit(); @@ -1047,7 +1047,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { format!( "`{}` (from the trait `{}`)", assoc_item.ident, - tcx.item_path_str(trait_def_id), + tcx.def_path_str(trait_def_id), ) }).collect::>().join(", "); let mut err = struct_span_err!( @@ -1436,7 +1436,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o { let self_ty = if let Some(ty) = opt_self_ty { ty } else { - let path_str = tcx.item_path_str(trait_def_id); + let path_str = tcx.def_path_str(trait_def_id); self.report_ambiguous_associated_type(span, "Type", &path_str, diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 22b33e1d2f613..c06d3fc0e89d8 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -976,13 +976,13 @@ https://doc.rust-lang.org/reference/types.html#trait-objects"); E0026, "{} `{}` does not have {}", kind_name, - tcx.item_path_str(variant.did), + tcx.def_path_str(variant.did), field_names); if let Some((span, ident)) = inexistent_fields.last() { err.span_label(*span, format!("{} `{}` does not have {} field{}", kind_name, - tcx.item_path_str(variant.did), + tcx.def_path_str(variant.did), t, plural)); if plural == "" { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 0eb8d7d06b1f6..c5db27cab604e 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -692,7 +692,7 @@ fn compare_number_of_method_arguments<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait `{}` has {}", trait_m.ident, potentially_plural_count(impl_number_args, "parameter"), - tcx.item_path_str(trait_m.def_id), + tcx.def_path_str(trait_m.def_id), trait_number_args); if let Some(trait_span) = trait_span { err.span_label(trait_span, format!("trait requires {}", diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0d4690c83170a..7bae174d7b808 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -131,7 +131,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { let sole_field = &variant.fields[0]; let sole_field_ty = sole_field.ty(self.tcx, substs); if self.can_coerce(expr_ty, sole_field_ty) { - let variant_path = self.tcx.item_path_str(variant.did); + let variant_path = self.tcx.def_path_str(variant.did); // FIXME #56861: DRYer prelude filtering Some(variant_path.trim_start_matches("std::prelude::v1::").to_string()) } else { diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 623677482db34..5f6a75857d1c3 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1150,7 +1150,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { // `report_method_error()`. diag.help(&format!( "call with fully qualified syntax `{}(...)` to keep using the current method", - self.tcx.item_path_str(stable_pick.item.def_id), + self.tcx.def_path_str(stable_pick.item.def_id), )); if nightly_options::is_nightly_build() { @@ -1158,7 +1158,7 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { diag.help(&format!( "add #![feature({})] to the crate attributes to enable `{}`", feature, - self.tcx.item_path_str(candidate.item.def_id), + self.tcx.def_path_str(candidate.item.def_id), )); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 55b6e8f099ea9..f28ebf4f64430 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -101,7 +101,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { None => String::new(), Some(trait_ref) => { format!(" of the trait `{}`", - self.tcx.item_path_str(trait_ref.def_id)) + self.tcx.def_path_str(trait_ref.def_id)) } }; @@ -134,16 +134,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { item_span, "candidate #{} is defined in the trait `{}`", idx + 1, - self.tcx.item_path_str(trait_did)); + self.tcx.def_path_str(trait_did)); } else { span_note!(err, item_span, "the candidate is defined in the trait `{}`", - self.tcx.item_path_str(trait_did)); + self.tcx.def_path_str(trait_did)); } err.help(&format!("to disambiguate the method call, write `{}::{}({}{})` \ instead", - self.tcx.item_path_str(trait_did), + self.tcx.def_path_str(trait_did), item_name, if rcvr_ty.is_region_ptr() && args.is_some() { if rcvr_ty.is_mutable_pointer() { @@ -514,7 +514,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { }; format!( "use {};\n{}", - with_crate_prefix(|| self.tcx.item_path_str(*did)), + with_crate_prefix(|| self.tcx.def_path_str(*did)), additional_newline ) }); @@ -528,14 +528,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { &format!( "\ncandidate #{}: `use {};`", i + 1, - with_crate_prefix(|| self.tcx.item_path_str(*trait_did)) + with_crate_prefix(|| self.tcx.def_path_str(*trait_did)) ) ); } else { msg.push_str( &format!( "\n`use {};`", - with_crate_prefix(|| self.tcx.item_path_str(*trait_did)) + with_crate_prefix(|| self.tcx.def_path_str(*trait_did)) ) ); } @@ -636,7 +636,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { for (i, trait_info) in candidates.iter().enumerate() { msg.push_str(&format!("\ncandidate #{}: `{}`", i + 1, - self.tcx.item_path_str(trait_info.def_id))); + self.tcx.def_path_str(trait_info.def_id))); } err.note(&msg[..]); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 48296e8e441c6..e8d98161ca1dd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1342,7 +1342,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite debug!( "check_item_type(it.id={}, it.name={})", it.id, - tcx.item_path_str(tcx.hir().local_def_id(it.id)) + tcx.def_path_str(tcx.hir().local_def_id(it.id)) ); let _indenter = indenter(); match it.node { @@ -3541,7 +3541,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { autoderef.unambiguous_final_ty(self); if let Some((did, field_ty)) = private_candidate { - let struct_path = self.tcx().item_path_str(did); + let struct_path = self.tcx().def_path_str(did); let mut err = struct_span_err!(self.tcx().sess, expr.span, E0616, "field `{}` of struct `{}` is private", field, struct_path); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index efbc4aef5f235..d8c5ec3e18d15 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -67,7 +67,7 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def debug!("check_item_well_formed(it.id={}, it.name={})", item.id, - tcx.item_path_str(def_id)); + tcx.def_path_str(def_id)); match item.node { // Right now we check that every default trait implementation @@ -932,7 +932,7 @@ fn report_bivariance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if let Some(def_id) = suggested_marker_id { err.help(&format!("consider removing `{}` or using a marker such as `{}`", param_name, - tcx.item_path_str(def_id))); + tcx.def_path_str(def_id))); } err.emit(); } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index bd2373d1659c9..04759a7c24fb6 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -198,8 +198,8 @@ fn visit_implementation_of_dispatch_from_dyn<'a, 'tcx>( if def_a.is_struct() && def_b.is_struct() => { if def_a != def_b { - let source_path = tcx.item_path_str(def_a.did); - let target_path = tcx.item_path_str(def_b.did); + let source_path = tcx.def_path_str(def_a.did); + let target_path = tcx.def_path_str(def_b.did); create_err( &format!( @@ -388,8 +388,8 @@ pub fn coerce_unsized_info<'a, 'gcx>(gcx: TyCtxt<'a, 'gcx, 'gcx>, (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) if def_a.is_struct() && def_b.is_struct() => { if def_a != def_b { - let source_path = gcx.item_path_str(def_a.did); - let target_path = gcx.item_path_str(def_b.did); + let source_path = gcx.def_path_str(def_a.did); + let target_path = gcx.def_path_str(def_b.did); span_err!(gcx.sess, span, E0377, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 8053ed130e91b..f07c6a11218ca 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -27,7 +27,7 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) { if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) { debug!("(checking implementation) adding impl for trait '{:?}', item '{}'", trait_ref, - tcx.item_path_str(impl_def_id)); + tcx.def_path_str(impl_def_id)); // Skip impls where one of the self type is an error type. // This occurs with e.g., resolve failures (#30589). @@ -195,10 +195,10 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI E0371, "the object type `{}` automatically implements the trait `{}`", trait_ref.self_ty(), - tcx.item_path_str(trait_def_id)) + tcx.def_path_str(trait_def_id)) .span_label(sp, format!("`{}` automatically implements trait `{}`", trait_ref.self_ty(), - tcx.item_path_str(trait_def_id))) + tcx.def_path_str(trait_def_id))) .emit(); } } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 2df137c3f5094..c292db6812f81 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -121,7 +121,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { format!("cross-crate traits with a default impl, like `{}`, \ can only be implemented for a struct/enum type \ defined in the current crate", - self.tcx.item_path_str(trait_def_id)), + self.tcx.def_path_str(trait_def_id)), "can't implement cross-crate trait for type in another crate" )) } @@ -129,7 +129,7 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> { _ => { Some((format!("cross-crate traits with a default impl, like `{}`, can \ only be implemented for a struct/enum type, not `{}`", - self.tcx.item_path_str(trait_def_id), + self.tcx.def_path_str(trait_def_id), self_ty), "can't implement cross-crate trait with a default impl for \ non-struct/enum type")) diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 868c1132e44c5..1b382775e5f49 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { fn build_constraints_for_item(&mut self, def_id: DefId) { let tcx = self.tcx(); - debug!("build_constraints_for_item({})", tcx.item_path_str(def_id)); + debug!("build_constraints_for_item({})", tcx.def_path_str(def_id)); // Skip items with no generics - there's nothing to infer in them. if tcx.generics_of(def_id).count() == 0 { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 59d364b1a08c6..05c30c32f30ce 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4070,7 +4070,7 @@ where F: Fn(DefId) -> Def { } let names = PrintCx::new(tcx, AbsolutePathPrinter) - .print_item_path(def_id, None, Namespace::TypeNS); + .print_def_path(def_id, None, Namespace::TypeNS); hir::Path { span: DUMMY_SP, diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 2820924824697..e6bc821a880f8 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1027,7 +1027,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu "rustc_attrs", "internal rustc attributes will never be stable", cfg_fn!(rustc_attrs))), - ("rustc_item_path", Whitelisted, template!(Word), Gated(Stability::Unstable, + ("rustc_def_path", Whitelisted, template!(Word), Gated(Stability::Unstable, "rustc_attrs", "internal rustc attributes will never be stable", cfg_fn!(rustc_attrs))), diff --git a/src/test/mir-opt/issue-41697.rs b/src/test/mir-opt/issue-41697.rs index 9db25b15f6835..5a461d6148254 100644 --- a/src/test/mir-opt/issue-41697.rs +++ b/src/test/mir-opt/issue-41697.rs @@ -1,7 +1,7 @@ // Regression test for #41697. Using dump-mir was triggering // artificial cycles: during type-checking, we had to get the MIR for // the constant expressions in `[u8; 2]`, which in turn would trigger -// an attempt to get the item-path, which in turn would request the +// an attempt to get the def-path, which in turn would request the // types of the impl, which would trigger a cycle. We suppressed this // cycle now by forcing mir-dump to avoid asking for types of an impl. diff --git a/src/test/ui/symbol-names/basic.rs b/src/test/ui/symbol-names/basic.rs index 2a051a5e144da..086b903b973b0 100644 --- a/src/test/ui/symbol-names/basic.rs +++ b/src/test/ui/symbol-names/basic.rs @@ -1,6 +1,6 @@ #![feature(rustc_attrs)] #[rustc_symbol_name] //~ ERROR _ZN5basic4main -#[rustc_item_path] //~ ERROR item-path(main) +#[rustc_def_path] //~ ERROR def-path(main) fn main() { } diff --git a/src/test/ui/symbol-names/basic.stderr b/src/test/ui/symbol-names/basic.stderr index ca789df9bd187..d0dda9062b2a8 100644 --- a/src/test/ui/symbol-names/basic.stderr +++ b/src/test/ui/symbol-names/basic.stderr @@ -4,11 +4,11 @@ error: symbol-name(_ZN5basic4main17h08bcaf310214ed52E) LL | #[rustc_symbol_name] //~ ERROR _ZN5basic4main | ^^^^^^^^^^^^^^^^^^^^ -error: item-path(main) +error: def-path(main) --> $DIR/basic.rs:4:1 | -LL | #[rustc_item_path] //~ ERROR item-path(main) - | ^^^^^^^^^^^^^^^^^^ +LL | #[rustc_def_path] //~ ERROR def-path(main) + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 69cd49e39512e..992527017fb7c 100644 --- a/src/test/ui/symbol-names/impl1.rs +++ b/src/test/ui/symbol-names/impl1.rs @@ -6,7 +6,7 @@ mod foo { impl Foo { #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar - #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar) + #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar) fn bar() { } } } @@ -16,7 +16,7 @@ mod bar { impl Foo { #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz - #[rustc_item_path] //~ ERROR item-path(bar::::baz) + #[rustc_def_path] //~ ERROR def-path(bar::::baz) fn baz() { } } } diff --git a/src/test/ui/symbol-names/impl1.stderr b/src/test/ui/symbol-names/impl1.stderr index 0e2e81f31ef76..c547262e52b72 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -4,11 +4,11 @@ error: symbol-name(_ZN15impl1..foo..Foo3bar17hc487d6ec13fe9124E) LL | #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar | ^^^^^^^^^^^^^^^^^^^^ -error: item-path(foo::Foo::bar) +error: def-path(foo::Foo::bar) --> $DIR/impl1.rs:9:9 | -LL | #[rustc_item_path] //~ ERROR item-path(foo::Foo::bar) - | ^^^^^^^^^^^^^^^^^^ +LL | #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar) + | ^^^^^^^^^^^^^^^^^ error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h38577281258e1527E) --> $DIR/impl1.rs:18:9 @@ -16,11 +16,11 @@ error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17h385772 LL | #[rustc_symbol_name] //~ ERROR _ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz | ^^^^^^^^^^^^^^^^^^^^ -error: item-path(bar::::baz) +error: def-path(bar::::baz) --> $DIR/impl1.rs:19:9 | -LL | #[rustc_item_path] //~ ERROR item-path(bar::::baz) - | ^^^^^^^^^^^^^^^^^^ +LL | #[rustc_def_path] //~ ERROR def-path(bar::::baz) + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors From 755d919c6785ab4db93c2b69d8052fb250c1ffce Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 13:25:31 +0200 Subject: [PATCH 26/68] rustc: move the contents of ty::item_path to ty::print. --- src/librustc/ty/item_path.rs | 562 ------------------ src/librustc/ty/mod.rs | 1 - src/librustc/ty/print.rs | 562 +++++++++++++++++- src/librustc/ty/query/plumbing.rs | 5 +- src/librustc_codegen_utils/symbol_names.rs | 7 +- src/librustc_mir/monomorphize/partitioning.rs | 2 +- src/librustc_mir/util/liveness.rs | 4 +- src/librustc_mir/util/pretty.rs | 7 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustdoc/clean/mod.rs | 5 +- 10 files changed, 575 insertions(+), 582 deletions(-) delete mode 100644 src/librustc/ty/item_path.rs diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs deleted file mode 100644 index 7969046d0cb05..0000000000000 --- a/src/librustc/ty/item_path.rs +++ /dev/null @@ -1,562 +0,0 @@ -use hir::def::Namespace; -use hir::map::DefPathData; -use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use ty::{self, DefIdTree, Ty, TyCtxt}; -use ty::print::PrintCx; -use ty::subst::{Subst, Substs}; -use middle::cstore::{ExternCrate, ExternCrateSource}; -use syntax::ast; -use syntax::symbol::{keywords, Symbol}; - -use std::cell::Cell; - -thread_local! { - static FORCE_ABSOLUTE: Cell = Cell::new(false); - static FORCE_IMPL_FILENAME_LINE: Cell = Cell::new(false); - static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); -} - -/// Enforces that def_path_str always returns an absolute path and -/// also enables "type-based" impl paths. This is used when building -/// symbols that contain types, where we want the crate name to be -/// part of the symbol. -pub fn with_forced_absolute_paths R, R>(f: F) -> R { - FORCE_ABSOLUTE.with(|force| { - let old = force.get(); - force.set(true); - let result = f(); - force.set(old); - result - }) -} - -/// Force us to name impls with just the filename/line number. We -/// normally try to use types. But at some points, notably while printing -/// cycle errors, this can result in extra or suboptimal error output, -/// so this variable disables that check. -pub fn with_forced_impl_filename_line R, R>(f: F) -> R { - FORCE_IMPL_FILENAME_LINE.with(|force| { - let old = force.get(); - force.set(true); - let result = f(); - force.set(old); - result - }) -} - -/// Add the `crate::` prefix to paths where appropriate. -pub fn with_crate_prefix R, R>(f: F) -> R { - SHOULD_PREFIX_WITH_CRATE.with(|flag| { - let old = flag.get(); - flag.set(true); - let result = f(); - flag.set(old); - result - }) -} - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always - // (but also some things just print a `DefId` generally so maybe we need this?) - fn guess_def_namespace(self, def_id: DefId) -> Namespace { - match self.def_key(def_id).disambiguated_data.data { - DefPathData::ValueNs(..) | - DefPathData::EnumVariant(..) | - DefPathData::Field(..) | - DefPathData::AnonConst | - DefPathData::ClosureExpr | - DefPathData::StructCtor => Namespace::ValueNS, - - DefPathData::MacroDef(..) => Namespace::MacroNS, - - _ => Namespace::TypeNS, - } - } - - /// Returns a string identifying this def-id. This string is - /// suitable for user output. It is relative to the current crate - /// root, unless with_forced_absolute_paths was used. - pub fn def_path_str_with_substs_and_ns( - self, - def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> String { - debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); - if FORCE_ABSOLUTE.with(|force| force.get()) { - PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns) - } else { - PrintCx::new(self, LocalPathPrinter).print_def_path(def_id, substs, ns) - } - } - - /// Returns a string identifying this def-id. This string is - /// suitable for user output. It is relative to the current crate - /// root, unless with_forced_absolute_paths was used. - pub fn def_path_str(self, def_id: DefId) -> String { - let ns = self.guess_def_namespace(def_id); - self.def_path_str_with_substs_and_ns(def_id, None, ns) - } - - /// Returns a string identifying this local node-id. - pub fn node_path_str(self, id: ast::NodeId) -> String { - self.def_path_str(self.hir().local_def_id(id)) - } - - /// Returns a string identifying this def-id. This string is - /// suitable for user output. It always begins with a crate identifier. - pub fn absolute_def_path_str(self, def_id: DefId) -> String { - debug!("absolute_def_path_str: def_id={:?}", def_id); - let ns = self.guess_def_namespace(def_id); - PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns) - } -} - -impl PrintCx<'a, 'gcx, 'tcx, P> { - pub fn default_print_def_path( - &mut self, - def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> P::Path { - debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); - let key = self.tcx.def_key(def_id); - debug!("default_print_def_path: key={:?}", key); - match key.disambiguated_data.data { - DefPathData::CrateRoot => { - assert!(key.parent.is_none()); - self.path_crate(def_id.krate) - } - - DefPathData::Impl => { - self.print_impl_path(def_id, substs, ns) - } - - // Unclear if there is any value in distinguishing these. - // Probably eventually (and maybe we would even want - // finer-grained distinctions, e.g., between enum/struct). - data @ DefPathData::Misc | - data @ DefPathData::TypeNs(..) | - data @ DefPathData::Trait(..) | - data @ DefPathData::TraitAlias(..) | - data @ DefPathData::AssocTypeInTrait(..) | - data @ DefPathData::AssocTypeInImpl(..) | - data @ DefPathData::AssocExistentialInImpl(..) | - data @ DefPathData::ValueNs(..) | - data @ DefPathData::Module(..) | - data @ DefPathData::TypeParam(..) | - data @ DefPathData::LifetimeParam(..) | - data @ DefPathData::EnumVariant(..) | - data @ DefPathData::Field(..) | - data @ DefPathData::AnonConst | - data @ DefPathData::MacroDef(..) | - data @ DefPathData::ClosureExpr | - data @ DefPathData::ImplTrait | - data @ DefPathData::GlobalMetaData(..) => { - let parent_did = self.tcx.parent(def_id).unwrap(); - let path = self.print_def_path(parent_did, None, ns); - self.path_append(path, &data.as_interned_str().as_symbol().as_str()) - }, - - DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` - let parent_def_id = self.tcx.parent(def_id).unwrap(); - self.print_def_path(parent_def_id, substs, ns) - } - } - } - - fn default_print_impl_path( - &mut self, - impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> P::Path { - debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); - let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); - - // Decide whether to print the parent path for the impl. - // Logically, since impls are global, it's never needed, but - // users may find it useful. Currently, we omit the parent if - // the impl is either in the same module as the self-type or - // as the trait. - let mut self_ty = self.tcx.type_of(impl_def_id); - if let Some(substs) = substs { - self_ty = self_ty.subst(self.tcx, substs); - } - let in_self_mod = match characteristic_def_id_of_type(self_ty) { - None => false, - Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id), - }; - - let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); - if let Some(substs) = substs { - impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); - } - let in_trait_mod = match impl_trait_ref { - None => false, - Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), - }; - - if !in_self_mod && !in_trait_mod { - // If the impl is not co-located with either self-type or - // trait-type, then fallback to a format that identifies - // the module more clearly. - let path = self.print_def_path(parent_def_id, None, ns); - if let Some(trait_ref) = impl_trait_ref { - return self.path_append(path, &format!("", trait_ref, self_ty)); - } else { - return self.path_append(path, &format!("", self_ty)); - } - } - - // Otherwise, try to give a good form that would be valid language - // syntax. Preferably using associated item notation. - - if let Some(trait_ref) = impl_trait_ref { - // Trait impls. - return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref)); - } - - // Inherent impls. Try to print `Foo::bar` for an inherent - // impl on `Foo`, but fallback to `::bar` if self-type is - // anything other than a simple path. - match self_ty.sty { - ty::Adt(adt_def, substs) => { - // FIXME(eddyb) this should recurse to build the path piecewise. - // self.print_def_path(adt_def.did, Some(substs), ns) - let mut s = String::new(); - ::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap(); - self.path_impl(&s) - } - - ty::Foreign(did) => self.print_def_path(did, None, ns), - - ty::Bool | - ty::Char | - ty::Int(_) | - ty::Uint(_) | - ty::Float(_) | - ty::Str => { - self.path_impl(&self_ty.to_string()) - } - - _ => { - self.path_impl(&format!("<{}>", self_ty)) - } - } - } -} - -/// As a heuristic, when we see an impl, if we see that the -/// 'self-type' is a type defined in the same module as the impl, -/// we can omit including the path to the impl itself. This -/// function tries to find a "characteristic def-id" for a -/// type. It's just a heuristic so it makes some questionable -/// decisions and we may want to adjust it later. -pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { - match ty.sty { - ty::Adt(adt_def, _) => Some(adt_def.did), - - ty::Dynamic(data, ..) => data.principal_def_id(), - - ty::Array(subty, _) | - ty::Slice(subty) => characteristic_def_id_of_type(subty), - - ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty), - - ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty), - - ty::Tuple(ref tys) => tys.iter() - .filter_map(|ty| characteristic_def_id_of_type(ty)) - .next(), - - ty::FnDef(def_id, _) | - ty::Closure(def_id, _) | - ty::Generator(def_id, _, _) | - ty::Foreign(def_id) => Some(def_id), - - ty::Bool | - ty::Char | - ty::Int(_) | - ty::Uint(_) | - ty::Str | - ty::FnPtr(_) | - ty::Projection(_) | - ty::Placeholder(..) | - ty::UnnormalizedProjection(..) | - ty::Param(_) | - ty::Opaque(..) | - ty::Infer(_) | - ty::Bound(..) | - ty::Error | - ty::GeneratorWitness(..) | - ty::Never | - ty::Float(_) => None, - } -} - -/// Unifying Trait for different kinds of item paths we might -/// construct. The basic interface is that components get appended. -pub trait ItemPathPrinter: Sized { - type Path; - - fn print_def_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> Self::Path { - self.default_print_def_path(def_id, substs, ns) - } - fn print_impl_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> Self::Path { - self.default_print_impl_path(impl_def_id, substs, ns) - } - - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - path: Self::Path, - text: &str, - ) -> Self::Path; -} - -struct AbsolutePathPrinter; - -impl ItemPathPrinter for AbsolutePathPrinter { - type Path = String; - - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { - self.tcx.original_crate_name(cnum).to_string() - } - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - text.to_string() - } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, - text: &str, - ) -> Self::Path { - if !path.is_empty() { - path.push_str("::"); - } - path.push_str(text); - path - } -} - -struct LocalPathPrinter; - -impl LocalPathPrinter { - /// If possible, this returns a global path resolving to `def_id` that is visible - /// from at least one local module and returns true. If the crate defining `def_id` is - /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path( - self: &mut PrintCx<'_, '_, '_, Self>, - def_id: DefId, - ns: Namespace, - ) -> Option<::Path> { - debug!("try_print_visible_def_path: def_id={:?}", def_id); - - // If `def_id` is a direct or injected extern crate, return the - // path to the crate followed by the path to the item within the crate. - if def_id.index == CRATE_DEF_INDEX { - let cnum = def_id.krate; - - if cnum == LOCAL_CRATE { - return Some(self.path_crate(cnum)); - } - - // In local mode, when we encounter a crate other than - // LOCAL_CRATE, execution proceeds in one of two ways: - // - // 1. for a direct dependency, where user added an - // `extern crate` manually, we put the `extern - // crate` as the parent. So you wind up with - // something relative to the current crate. - // 2. for an extern inferred from a path or an indirect crate, - // where there is no explicit `extern crate`, we just prepend - // the crate name. - match *self.tcx.extern_crate(def_id) { - Some(ExternCrate { - src: ExternCrateSource::Extern(def_id), - direct: true, - span, - .. - }) => { - debug!("try_print_visible_def_path: def_id={:?}", def_id); - let path = if !span.is_dummy() { - self.print_def_path(def_id, None, ns) - } else { - self.path_crate(cnum) - }; - return Some(path); - } - None => { - return Some(self.path_crate(cnum)); - } - _ => {}, - } - } - - if def_id.is_local() { - return None; - } - - let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); - - let mut cur_def_key = self.tcx.def_key(def_id); - debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); - - // For a UnitStruct or TupleStruct we want the name of its parent rather than . - if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { - let parent = DefId { - krate: def_id.krate, - index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), - }; - - cur_def_key = self.tcx.def_key(parent); - } - - let visible_parent = visible_parent_map.get(&def_id).cloned()?; - let path = self.try_print_visible_def_path(visible_parent, ns)?; - let actual_parent = self.tcx.parent(def_id); - - let data = cur_def_key.disambiguated_data.data; - debug!( - "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}", - data, visible_parent, actual_parent, - ); - - let symbol = match data { - // In order to output a path that could actually be imported (valid and visible), - // we need to handle re-exports correctly. - // - // For example, take `std::os::unix::process::CommandExt`, this trait is actually - // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). - // - // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is - // private so the "true" path to `CommandExt` isn't accessible. - // - // In this case, the `visible_parent_map` will look something like this: - // - // (child) -> (parent) - // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` - // `std::sys::unix::ext::process` -> `std::sys::unix::ext` - // `std::sys::unix::ext` -> `std::os` - // - // This is correct, as the visible parent of `std::sys::unix::ext` is in fact - // `std::os`. - // - // When printing the path to `CommandExt` and looking at the `cur_def_key` that - // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go - // to the parent - resulting in a mangled path like - // `std::os::ext::process::CommandExt`. - // - // Instead, we must detect that there was a re-export and instead print `unix` - // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To - // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with - // the visible parent (`std::os`). If these do not match, then we iterate over - // the children of the visible parent (as was done when computing - // `visible_parent_map`), looking for the specific child we currently have and then - // have access to the re-exported name. - DefPathData::Module(actual_name) | - DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { - visible_parent - .and_then(|parent| { - self.tcx.item_children(parent) - .iter() - .find(|child| child.def.def_id() == cur_def) - .map(|child| child.ident.as_str()) - }) - .unwrap_or_else(|| actual_name.as_str()) - } - _ => { - data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { - // Re-exported `extern crate` (#43189). - if let DefPathData::CrateRoot = data { - self.tcx.original_crate_name(def_id.krate).as_str() - } else { - Symbol::intern("").as_str() - } - }) - }, - }; - debug!("try_print_visible_def_path: symbol={:?}", symbol); - Some(self.path_append(path, &symbol)) - } -} - -impl ItemPathPrinter for LocalPathPrinter { - type Path = String; - - fn print_def_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> Self::Path { - self.try_print_visible_def_path(def_id, ns) - .unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns)) - } - fn print_impl_path( - self: &mut PrintCx<'_, '_, 'tcx, Self>, - impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, - ns: Namespace, - ) -> Self::Path { - // Always use types for non-local impls, where types are always - // available, and filename/line-number is mostly uninteresting. - let use_types = !impl_def_id.is_local() || { - // Otherwise, use filename/line-number if forced. - let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); - !force_no_types - }; - - if !use_types { - // If no type info is available, fall back to - // pretty printing some span information. This should - // only occur very early in the compiler pipeline. - // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` - let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); - let path = self.print_def_path(parent_def_id, None, ns); - let span = self.tcx.def_span(impl_def_id); - return self.path_append(path, &format!("", span)); - } - - self.default_print_impl_path(impl_def_id, substs, ns) - } - - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { - if cnum == LOCAL_CRATE { - if self.tcx.sess.rust_2018() { - // We add the `crate::` keyword on Rust 2018, only when desired. - if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - return keywords::Crate.name().to_string(); - } - } - String::new() - } else { - self.tcx.crate_name(cnum).to_string() - } - } - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - text.to_string() - } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, - text: &str, - ) -> Self::Path { - if !path.is_empty() { - path.push_str("::"); - } - path.push_str(text); - path - } -} diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4852193e8c3f6..f71cf01f83067 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -94,7 +94,6 @@ mod erase_regions; pub mod fast_reject; pub mod fold; pub mod inhabitedness; -pub mod item_path; pub mod layout; pub mod _match; pub mod outlives; diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index df96cb55663be..1a2d8e0233e58 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -1,11 +1,64 @@ -use ty::{self, TyCtxt, TypeFoldable}; +use hir::def::Namespace; +use hir::map::DefPathData; +use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use ty::subst::{Subst, Substs}; +use middle::cstore::{ExternCrate, ExternCrateSource}; +use syntax::ast; +use syntax::symbol::{keywords, Symbol}; use rustc_data_structures::fx::FxHashSet; use syntax::symbol::InternedString; +use std::cell::Cell; use std::fmt; use std::ops::Deref; +thread_local! { + static FORCE_ABSOLUTE: Cell = Cell::new(false); + static FORCE_IMPL_FILENAME_LINE: Cell = Cell::new(false); + static SHOULD_PREFIX_WITH_CRATE: Cell = Cell::new(false); +} + +/// Enforces that def_path_str always returns an absolute path and +/// also enables "type-based" impl paths. This is used when building +/// symbols that contain types, where we want the crate name to be +/// part of the symbol. +pub fn with_forced_absolute_paths R, R>(f: F) -> R { + FORCE_ABSOLUTE.with(|force| { + let old = force.get(); + force.set(true); + let result = f(); + force.set(old); + result + }) +} + +/// Force us to name impls with just the filename/line number. We +/// normally try to use types. But at some points, notably while printing +/// cycle errors, this can result in extra or suboptimal error output, +/// so this variable disables that check. +pub fn with_forced_impl_filename_line R, R>(f: F) -> R { + FORCE_IMPL_FILENAME_LINE.with(|force| { + let old = force.get(); + force.set(true); + let result = f(); + force.set(old); + result + }) +} + +/// Add the `crate::` prefix to paths where appropriate. +pub fn with_crate_prefix R, R>(f: F) -> R { + SHOULD_PREFIX_WITH_CRATE.with(|flag| { + let old = flag.get(); + flag.set(true); + let result = f(); + flag.set(old); + result + }) +} + // FIXME(eddyb) this module uses `pub(crate)` for things used only // from `ppaux` - when that is removed, they can be re-privatized. @@ -89,6 +142,513 @@ pub trait Print<'tcx, P> { } } +pub trait Printer: Sized { + type Path; + + fn print_def_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + self.default_print_def_path(def_id, substs, ns) + } + fn print_impl_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + self.default_print_impl_path(impl_def_id, substs, ns) + } + + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + path: Self::Path, + text: &str, + ) -> Self::Path; +} + +impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { + // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always + // (but also some things just print a `DefId` generally so maybe we need this?) + fn guess_def_namespace(self, def_id: DefId) -> Namespace { + match self.def_key(def_id).disambiguated_data.data { + DefPathData::ValueNs(..) | + DefPathData::EnumVariant(..) | + DefPathData::Field(..) | + DefPathData::AnonConst | + DefPathData::ClosureExpr | + DefPathData::StructCtor => Namespace::ValueNS, + + DefPathData::MacroDef(..) => Namespace::MacroNS, + + _ => Namespace::TypeNS, + } + } + + /// Returns a string identifying this def-id. This string is + /// suitable for user output. It is relative to the current crate + /// root, unless with_forced_absolute_paths was used. + pub fn def_path_str_with_substs_and_ns( + self, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> String { + debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); + if FORCE_ABSOLUTE.with(|force| force.get()) { + PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns) + } else { + PrintCx::new(self, LocalPathPrinter).print_def_path(def_id, substs, ns) + } + } + + /// Returns a string identifying this def-id. This string is + /// suitable for user output. It is relative to the current crate + /// root, unless with_forced_absolute_paths was used. + pub fn def_path_str(self, def_id: DefId) -> String { + let ns = self.guess_def_namespace(def_id); + self.def_path_str_with_substs_and_ns(def_id, None, ns) + } + + /// Returns a string identifying this local node-id. + // FIXME(eddyb) remove in favor of calling `def_path_str` directly. + pub fn node_path_str(self, id: ast::NodeId) -> String { + self.def_path_str(self.hir().local_def_id(id)) + } + + /// Returns a string identifying this def-id. This string is + /// suitable for user output. It always begins with a crate identifier. + pub fn absolute_def_path_str(self, def_id: DefId) -> String { + debug!("absolute_def_path_str: def_id={:?}", def_id); + let ns = self.guess_def_namespace(def_id); + PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns) + } +} + +impl PrintCx<'a, 'gcx, 'tcx, P> { + pub fn default_print_def_path( + &mut self, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> P::Path { + debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); + let key = self.tcx.def_key(def_id); + debug!("default_print_def_path: key={:?}", key); + match key.disambiguated_data.data { + DefPathData::CrateRoot => { + assert!(key.parent.is_none()); + self.path_crate(def_id.krate) + } + + DefPathData::Impl => { + self.print_impl_path(def_id, substs, ns) + } + + // Unclear if there is any value in distinguishing these. + // Probably eventually (and maybe we would even want + // finer-grained distinctions, e.g., between enum/struct). + data @ DefPathData::Misc | + data @ DefPathData::TypeNs(..) | + data @ DefPathData::Trait(..) | + data @ DefPathData::TraitAlias(..) | + data @ DefPathData::AssocTypeInTrait(..) | + data @ DefPathData::AssocTypeInImpl(..) | + data @ DefPathData::AssocExistentialInImpl(..) | + data @ DefPathData::ValueNs(..) | + data @ DefPathData::Module(..) | + data @ DefPathData::TypeParam(..) | + data @ DefPathData::LifetimeParam(..) | + data @ DefPathData::EnumVariant(..) | + data @ DefPathData::Field(..) | + data @ DefPathData::AnonConst | + data @ DefPathData::MacroDef(..) | + data @ DefPathData::ClosureExpr | + data @ DefPathData::ImplTrait | + data @ DefPathData::GlobalMetaData(..) => { + let parent_did = self.tcx.parent(def_id).unwrap(); + let path = self.print_def_path(parent_did, None, ns); + self.path_append(path, &data.as_interned_str().as_symbol().as_str()) + }, + + DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` + let parent_def_id = self.tcx.parent(def_id).unwrap(); + self.print_def_path(parent_def_id, substs, ns) + } + } + } + + fn default_print_impl_path( + &mut self, + impl_def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> P::Path { + debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); + let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); + + // Decide whether to print the parent path for the impl. + // Logically, since impls are global, it's never needed, but + // users may find it useful. Currently, we omit the parent if + // the impl is either in the same module as the self-type or + // as the trait. + let mut self_ty = self.tcx.type_of(impl_def_id); + if let Some(substs) = substs { + self_ty = self_ty.subst(self.tcx, substs); + } + let in_self_mod = match characteristic_def_id_of_type(self_ty) { + None => false, + Some(ty_def_id) => self.tcx.parent(ty_def_id) == Some(parent_def_id), + }; + + let mut impl_trait_ref = self.tcx.impl_trait_ref(impl_def_id); + if let Some(substs) = substs { + impl_trait_ref = impl_trait_ref.subst(self.tcx, substs); + } + let in_trait_mod = match impl_trait_ref { + None => false, + Some(trait_ref) => self.tcx.parent(trait_ref.def_id) == Some(parent_def_id), + }; + + if !in_self_mod && !in_trait_mod { + // If the impl is not co-located with either self-type or + // trait-type, then fallback to a format that identifies + // the module more clearly. + let path = self.print_def_path(parent_def_id, None, ns); + if let Some(trait_ref) = impl_trait_ref { + return self.path_append(path, &format!("", trait_ref, self_ty)); + } else { + return self.path_append(path, &format!("", self_ty)); + } + } + + // Otherwise, try to give a good form that would be valid language + // syntax. Preferably using associated item notation. + + if let Some(trait_ref) = impl_trait_ref { + // Trait impls. + return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref)); + } + + // Inherent impls. Try to print `Foo::bar` for an inherent + // impl on `Foo`, but fallback to `::bar` if self-type is + // anything other than a simple path. + match self_ty.sty { + ty::Adt(adt_def, substs) => { + // FIXME(eddyb) this should recurse to build the path piecewise. + // self.print_def_path(adt_def.did, Some(substs), ns) + let mut s = String::new(); + ::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap(); + self.path_impl(&s) + } + + ty::Foreign(did) => self.print_def_path(did, None, ns), + + ty::Bool | + ty::Char | + ty::Int(_) | + ty::Uint(_) | + ty::Float(_) | + ty::Str => { + self.path_impl(&self_ty.to_string()) + } + + _ => { + self.path_impl(&format!("<{}>", self_ty)) + } + } + } +} + +/// As a heuristic, when we see an impl, if we see that the +/// 'self-type' is a type defined in the same module as the impl, +/// we can omit including the path to the impl itself. This +/// function tries to find a "characteristic def-id" for a +/// type. It's just a heuristic so it makes some questionable +/// decisions and we may want to adjust it later. +pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { + match ty.sty { + ty::Adt(adt_def, _) => Some(adt_def.did), + + ty::Dynamic(data, ..) => data.principal_def_id(), + + ty::Array(subty, _) | + ty::Slice(subty) => characteristic_def_id_of_type(subty), + + ty::RawPtr(mt) => characteristic_def_id_of_type(mt.ty), + + ty::Ref(_, ty, _) => characteristic_def_id_of_type(ty), + + ty::Tuple(ref tys) => tys.iter() + .filter_map(|ty| characteristic_def_id_of_type(ty)) + .next(), + + ty::FnDef(def_id, _) | + ty::Closure(def_id, _) | + ty::Generator(def_id, _, _) | + ty::Foreign(def_id) => Some(def_id), + + ty::Bool | + ty::Char | + ty::Int(_) | + ty::Uint(_) | + ty::Str | + ty::FnPtr(_) | + ty::Projection(_) | + ty::Placeholder(..) | + ty::UnnormalizedProjection(..) | + ty::Param(_) | + ty::Opaque(..) | + ty::Infer(_) | + ty::Bound(..) | + ty::Error | + ty::GeneratorWitness(..) | + ty::Never | + ty::Float(_) => None, + } +} + +// FIXME(eddyb) remove, alongside `FORCE_ABSOLUTE` and `absolute_def_path_str`. +struct AbsolutePathPrinter; + +impl Printer for AbsolutePathPrinter { + type Path = String; + + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + self.tcx.original_crate_name(cnum).to_string() + } + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { + text.to_string() + } + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + mut path: Self::Path, + text: &str, + ) -> Self::Path { + if !path.is_empty() { + path.push_str("::"); + } + path.push_str(text); + path + } +} + pub struct FmtPrinter { pub fmt: F, } + +// FIXME(eddyb) integrate into `FmtPrinter`. +struct LocalPathPrinter; + +impl LocalPathPrinter { + /// If possible, this returns a global path resolving to `def_id` that is visible + /// from at least one local module and returns true. If the crate defining `def_id` is + /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. + fn try_print_visible_def_path( + self: &mut PrintCx<'_, '_, '_, Self>, + def_id: DefId, + ns: Namespace, + ) -> Option<::Path> { + debug!("try_print_visible_def_path: def_id={:?}", def_id); + + // If `def_id` is a direct or injected extern crate, return the + // path to the crate followed by the path to the item within the crate. + if def_id.index == CRATE_DEF_INDEX { + let cnum = def_id.krate; + + if cnum == LOCAL_CRATE { + return Some(self.path_crate(cnum)); + } + + // In local mode, when we encounter a crate other than + // LOCAL_CRATE, execution proceeds in one of two ways: + // + // 1. for a direct dependency, where user added an + // `extern crate` manually, we put the `extern + // crate` as the parent. So you wind up with + // something relative to the current crate. + // 2. for an extern inferred from a path or an indirect crate, + // where there is no explicit `extern crate`, we just prepend + // the crate name. + match *self.tcx.extern_crate(def_id) { + Some(ExternCrate { + src: ExternCrateSource::Extern(def_id), + direct: true, + span, + .. + }) => { + debug!("try_print_visible_def_path: def_id={:?}", def_id); + let path = if !span.is_dummy() { + self.print_def_path(def_id, None, ns) + } else { + self.path_crate(cnum) + }; + return Some(path); + } + None => { + return Some(self.path_crate(cnum)); + } + _ => {}, + } + } + + if def_id.is_local() { + return None; + } + + let visible_parent_map = self.tcx.visible_parent_map(LOCAL_CRATE); + + let mut cur_def_key = self.tcx.def_key(def_id); + debug!("try_print_visible_def_path: cur_def_key={:?}", cur_def_key); + + // For a UnitStruct or TupleStruct we want the name of its parent rather than . + if let DefPathData::StructCtor = cur_def_key.disambiguated_data.data { + let parent = DefId { + krate: def_id.krate, + index: cur_def_key.parent.expect("DefPathData::StructCtor missing a parent"), + }; + + cur_def_key = self.tcx.def_key(parent); + } + + let visible_parent = visible_parent_map.get(&def_id).cloned()?; + let path = self.try_print_visible_def_path(visible_parent, ns)?; + let actual_parent = self.tcx.parent(def_id); + + let data = cur_def_key.disambiguated_data.data; + debug!( + "try_print_visible_def_path: data={:?} visible_parent={:?} actual_parent={:?}", + data, visible_parent, actual_parent, + ); + + let symbol = match data { + // In order to output a path that could actually be imported (valid and visible), + // we need to handle re-exports correctly. + // + // For example, take `std::os::unix::process::CommandExt`, this trait is actually + // defined at `std::sys::unix::ext::process::CommandExt` (at time of writing). + // + // `std::os::unix` rexports the contents of `std::sys::unix::ext`. `std::sys` is + // private so the "true" path to `CommandExt` isn't accessible. + // + // In this case, the `visible_parent_map` will look something like this: + // + // (child) -> (parent) + // `std::sys::unix::ext::process::CommandExt` -> `std::sys::unix::ext::process` + // `std::sys::unix::ext::process` -> `std::sys::unix::ext` + // `std::sys::unix::ext` -> `std::os` + // + // This is correct, as the visible parent of `std::sys::unix::ext` is in fact + // `std::os`. + // + // When printing the path to `CommandExt` and looking at the `cur_def_key` that + // corresponds to `std::sys::unix::ext`, we would normally print `ext` and then go + // to the parent - resulting in a mangled path like + // `std::os::ext::process::CommandExt`. + // + // Instead, we must detect that there was a re-export and instead print `unix` + // (which is the name `std::sys::unix::ext` was re-exported as in `std::os`). To + // do this, we compare the parent of `std::sys::unix::ext` (`std::sys::unix`) with + // the visible parent (`std::os`). If these do not match, then we iterate over + // the children of the visible parent (as was done when computing + // `visible_parent_map`), looking for the specific child we currently have and then + // have access to the re-exported name. + DefPathData::Module(actual_name) | + DefPathData::TypeNs(actual_name) if visible_parent != actual_parent => { + visible_parent + .and_then(|parent| { + self.tcx.item_children(parent) + .iter() + .find(|child| child.def.def_id() == cur_def) + .map(|child| child.ident.as_str()) + }) + .unwrap_or_else(|| actual_name.as_str()) + } + _ => { + data.get_opt_name().map(|n| n.as_str()).unwrap_or_else(|| { + // Re-exported `extern crate` (#43189). + if let DefPathData::CrateRoot = data { + self.tcx.original_crate_name(def_id.krate).as_str() + } else { + Symbol::intern("").as_str() + } + }) + }, + }; + debug!("try_print_visible_def_path: symbol={:?}", symbol); + Some(self.path_append(path, &symbol)) + } +} + +impl Printer for LocalPathPrinter { + type Path = String; + + fn print_def_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + self.try_print_visible_def_path(def_id, ns) + .unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns)) + } + fn print_impl_path( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + impl_def_id: DefId, + substs: Option<&Substs<'tcx>>, + ns: Namespace, + ) -> Self::Path { + // Always use types for non-local impls, where types are always + // available, and filename/line-number is mostly uninteresting. + let use_types = !impl_def_id.is_local() || { + // Otherwise, use filename/line-number if forced. + let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); + !force_no_types + }; + + if !use_types { + // If no type info is available, fall back to + // pretty printing some span information. This should + // only occur very early in the compiler pipeline. + // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` + let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); + let path = self.print_def_path(parent_def_id, None, ns); + let span = self.tcx.def_span(impl_def_id); + return self.path_append(path, &format!("", span)); + } + + self.default_print_impl_path(impl_def_id, substs, ns) + } + + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + if cnum == LOCAL_CRATE { + if self.tcx.sess.rust_2018() { + // We add the `crate::` keyword on Rust 2018, only when desired. + if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { + return keywords::Crate.name().to_string(); + } + } + String::new() + } else { + self.tcx.crate_name(cnum).to_string() + } + } + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { + text.to_string() + } + fn path_append( + self: &mut PrintCx<'_, '_, '_, Self>, + mut path: Self::Path, + text: &str, + ) -> Self::Path { + if !path.is_empty() { + path.push_str("::"); + } + path.push_str(text); + path + } +} diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 541f5b75aa5c7..7574ff53a8b1c 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -8,11 +8,10 @@ use errors::Level; use errors::Diagnostic; use errors::FatalError; use ty::tls; -use ty::{TyCtxt}; +use ty::{self, TyCtxt}; use ty::query::Query; use ty::query::config::{QueryConfig, QueryDescription}; use ty::query::job::{QueryJob, QueryResult, QueryInfo}; -use ty::item_path; use util::common::{profq_msg, ProfileQueriesMsg, QueryMsg}; @@ -282,7 +281,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // sometimes cycles itself, leading to extra cycle errors. // (And cycle errors around impls tend to occur during the // collect/coherence phases anyhow.) - item_path::with_forced_impl_filename_line(|| { + ty::print::with_forced_impl_filename_line(|| { let span = fix_span(stack[1 % stack.len()].span, &stack[0].query); let mut err = struct_span_err!(self.sess, span, diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 6e159ca9e57aa..6fc838d1b22a2 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -93,8 +93,7 @@ use rustc::hir::Node; use rustc::hir::CodegenFnAttrFlags; use rustc::hir::map::definitions::DefPathData; use rustc::ich::NodeIdHashingMode; -use rustc::ty::item_path::{self, ItemPathPrinter}; -use rustc::ty::print::PrintCx; +use rustc::ty::print::{PrintCx, Printer}; use rustc::ty::query::Providers; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -223,7 +222,7 @@ fn get_symbol_hash<'a, 'tcx>( } fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName { - item_path::with_forced_absolute_paths(|| { + ty::print::with_forced_absolute_paths(|| { PrintCx::new(tcx, SymbolPathPrinter) .print_def_path(def_id, None, Namespace::ValueNS) .into_interned() @@ -395,7 +394,7 @@ impl SymbolPath { struct SymbolPathPrinter; -impl ItemPathPrinter for SymbolPathPrinter { +impl Printer for SymbolPathPrinter { type Path = SymbolPath; fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 569e4c828f601..613a17ce9a466 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -105,7 +105,7 @@ use rustc::hir::map::DefPathData; use rustc::mir::mono::{Linkage, Visibility, CodegenUnitNameBuilder}; use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::ty::{self, TyCtxt, InstanceDef}; -use rustc::ty::item_path::characteristic_def_id_of_type; +use rustc::ty::print::characteristic_def_id_of_type; use rustc::ty::query::Providers; use rustc::util::common::time; use rustc::util::nodemap::{DefIdSet, FxHashMap, FxHashSet}; diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index e0e346b6d14cb..c58b6d47f7513 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -28,7 +28,7 @@ use rustc::mir::visit::{ }; use rustc::mir::Local; use rustc::mir::*; -use rustc::ty::{item_path, TyCtxt}; +use rustc::ty::{self, TyCtxt}; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::work_queue::WorkQueue; @@ -315,7 +315,7 @@ pub fn dump_mir<'a, 'tcx, V: Idx>( if !dump_enabled(tcx, pass_name, source) { return; } - let node_path = item_path::with_forced_impl_filename_line(|| { + let node_path = ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 below tcx.def_path_str(source.def_id) }); diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index e441345b61c1d..232765f52f998 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -3,7 +3,6 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::*; use rustc::mir::visit::Visitor; use rustc::ty::{self, TyCtxt}; -use rustc::ty::item_path; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use std::fmt::Display; @@ -79,7 +78,7 @@ pub fn dump_mir<'a, 'gcx, 'tcx, F>( return; } - let node_path = item_path::with_forced_impl_filename_line(|| { + let node_path = ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 below tcx.def_path_str(source.def_id) }); @@ -104,7 +103,7 @@ pub fn dump_enabled<'a, 'gcx, 'tcx>( None => return false, Some(ref filters) => filters, }; - let node_path = item_path::with_forced_impl_filename_line(|| { + let node_path = ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 below tcx.def_path_str(source.def_id) }); @@ -580,7 +579,7 @@ fn write_mir_sig(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut dyn Write) -> i (hir::BodyOwnerKind::Static(hir::MutMutable), _) => write!(w, "static mut")?, } - item_path::with_forced_impl_filename_line(|| { + ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere write!(w, " {}", tcx.def_path_str(src.def_id)) })?; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f28ebf4f64430..4841c6037698a 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -14,7 +14,7 @@ use rustc::hir::print; use rustc::infer::type_variable::TypeVariableOrigin; use rustc::traits::Obligation; use rustc::ty::{self, Adt, Ty, TyCtxt, ToPolyTraitRef, ToPredicate, TypeFoldable}; -use rustc::ty::item_path::with_crate_prefix; +use rustc::ty::print::with_crate_prefix; use util::nodemap::FxHashSet; use syntax_pos::{Span, FileName}; use syntax::ast; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 05c30c32f30ce..16f0bf46bead3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4045,12 +4045,11 @@ pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option { pub fn get_path_for_type(tcx: TyCtxt, def_id: DefId, def_ctor: F) -> hir::Path where F: Fn(DefId) -> Def { - use rustc::ty::item_path::ItemPathPrinter; - use rustc::ty::print::PrintCx; + use rustc::ty::print::{PrintCx, Printer}; struct AbsolutePathPrinter; - impl ItemPathPrinter for AbsolutePathPrinter { + impl Printer for AbsolutePathPrinter { type Path = Vec; fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { From fb94c0612c6fe3f142c7cd031cfae175c1744924 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 14:49:32 +0200 Subject: [PATCH 27/68] rustc: integrate LocalPathPrinter's behavior into FmtPrinter. --- src/librustc/lib.rs | 1 + src/librustc/ty/print.rs | 67 ++++++++++++++++++++++++++++---------- src/librustc/util/ppaux.rs | 35 ++++++++------------ 3 files changed, 64 insertions(+), 39 deletions(-) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index c41ede91a0e55..f9bf1a061fb29 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -60,6 +60,7 @@ #![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] +#![feature(underscore_imports)] #![recursion_limit="512"] diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 1a2d8e0233e58..f6052f7b66434 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashSet; use syntax::symbol::InternedString; use std::cell::Cell; -use std::fmt; +use std::fmt::{self, Write as _}; use std::ops::Deref; thread_local! { @@ -145,6 +145,7 @@ pub trait Print<'tcx, P> { pub trait Printer: Sized { type Path; + #[must_use] fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, @@ -153,6 +154,7 @@ pub trait Printer: Sized { ) -> Self::Path { self.default_print_def_path(def_id, substs, ns) } + #[must_use] fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, @@ -162,8 +164,11 @@ pub trait Printer: Sized { self.default_print_impl_path(impl_def_id, substs, ns) } + #[must_use] fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; + #[must_use] fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; + #[must_use] fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, path: Self::Path, @@ -171,6 +176,14 @@ pub trait Printer: Sized { ) -> Self::Path; } +#[must_use] +pub struct PrettyPath { + pub empty: bool, +} + +/// Trait for printers that pretty-print using `fmt::Write` to the printer. +pub trait PrettyPrinter: Printer> + fmt::Write {} + impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // HACK(eddyb) get rid of `def_path_str` and/or pass `Namespace` explicitly always // (but also some things just print a `DefId` generally so maybe we need this?) @@ -202,7 +215,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if FORCE_ABSOLUTE.with(|force| force.get()) { PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns) } else { - PrintCx::new(self, LocalPathPrinter).print_def_path(def_id, substs, ns) + let mut s = String::new(); + let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s }) + .print_def_path(def_id, substs, ns); + s } } @@ -441,10 +457,7 @@ pub struct FmtPrinter { pub fmt: F, } -// FIXME(eddyb) integrate into `FmtPrinter`. -struct LocalPathPrinter; - -impl LocalPathPrinter { +impl FmtPrinter { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. @@ -584,8 +597,14 @@ impl LocalPathPrinter { } } -impl Printer for LocalPathPrinter { - type Path = String; +impl fmt::Write for FmtPrinter { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.fmt.write_str(s) + } +} + +impl Printer for FmtPrinter { + type Path = Result; fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, @@ -614,7 +633,6 @@ impl Printer for LocalPathPrinter { // If no type info is available, fall back to // pretty printing some span information. This should // only occur very early in the compiler pipeline. - // FIXME(eddyb) this should just be using `tcx.def_span(impl_def_id)` let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); let path = self.print_def_path(parent_def_id, None, ns); let span = self.tcx.def_span(impl_def_id); @@ -629,26 +647,39 @@ impl Printer for LocalPathPrinter { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. if SHOULD_PREFIX_WITH_CRATE.with(|flag| flag.get()) { - return keywords::Crate.name().to_string(); + write!(self.printer, "{}", keywords::Crate.name())?; + return Ok(PrettyPath { empty: false }); } } - String::new() + Ok(PrettyPath { empty: true }) } else { - self.tcx.crate_name(cnum).to_string() + write!(self.printer, "{}", self.tcx.crate_name(cnum))?; + Ok(PrettyPath { empty: false }) } } fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - text.to_string() + write!(self.printer, "{}", text)?; + Ok(PrettyPath { empty: false }) } fn path_append( self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, + path: Self::Path, text: &str, ) -> Self::Path { - if !path.is_empty() { - path.push_str("::"); + let path = path?; + + // FIXME(eddyb) this shouldn't happen, but is currently + // the case for `extern { ... }` "foreign modules". + if text.is_empty() { + return Ok(path); } - path.push_str(text); - path + + if !path.empty { + write!(self.printer, "::")?; + } + write!(self.printer, "{}", text)?; + Ok(PrettyPath { empty: false }) } } + +impl PrettyPrinter for FmtPrinter {} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c351807ef5b91..fcee97f0cb7cc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,10 +10,10 @@ use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TypeFoldable}; -use ty::print::{FmtPrinter, PrintCx, Print}; +use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; use std::cell::Cell; -use std::fmt; +use std::fmt::{self, Write as _}; use std::iter; use std::usize; @@ -193,18 +193,18 @@ macro_rules! gen_display_debug { } macro_rules! gen_print_impl { ( ($($x:tt)+) $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { - impl<$($x)+, F: fmt::Write> Print<'tcx, FmtPrinter> for $target { + impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target { type Output = fmt::Result; - fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter>) -> fmt::Result { + fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { if $cx.is_debug $dbg else $disp } } }; ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { - impl Print<'tcx, FmtPrinter> for $target { + impl Print<'tcx, P> for $target { type Output = fmt::Result; - fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter>) -> fmt::Result { + fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result { if $cx.is_debug $dbg else $disp } @@ -235,7 +235,7 @@ macro_rules! define_print { ( $generic:tt $target:ty, ($self:ident, $cx:ident) { display $disp:block } ) => { gen_print_impl! { $generic $target, ($self, $cx) yes $disp no { - write!($cx.printer.fmt, "{:?}", $self) + write!($cx.printer, "{:?}", $self) } } }; } @@ -246,7 +246,7 @@ macro_rules! define_print_multi { } macro_rules! print_inner { ( $cx:expr, write ($($data:expr),+) ) => { - write!($cx.printer.fmt, $($data),+) + write!($cx.printer, $($data),+) }; ( $cx:expr, $kind:ident ($data:expr) ) => { $data.$kind($cx) @@ -258,7 +258,7 @@ macro_rules! print { }; } -impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { +impl PrintCx<'a, 'gcx, 'tcx, P> { fn fn_sig( &mut self, inputs: &[Ty<'tcx>], @@ -404,7 +404,7 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { } fn in_binder(&mut self, value: &ty::Binder) -> fmt::Result - where T: Print<'tcx, FmtPrinter, Output = fmt::Result> + TypeFoldable<'tcx> + where T: Print<'tcx, P, Output = fmt::Result> + TypeFoldable<'tcx> { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -489,13 +489,6 @@ pub fn parameterized( }) } -impl<'a, 'tcx, P, T: Print<'tcx, P>> Print<'tcx, P> for &'a T { - type Output = T::Output; - fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Self::Output { - (*self).print(cx) - } -} - define_print! { ('tcx) &'tcx ty::List>, (self, cx) { display { @@ -575,7 +568,7 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |cx| { + PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { print!(cx, write("{}", cx.tcx.def_path_str(self.def_id))) }) } @@ -583,7 +576,7 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |cx| { + PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { print!(cx, write("{}", cx.tcx.def_path_str(self.did))) }) } @@ -599,7 +592,7 @@ impl<'tcx> fmt::Debug for ty::ClosureUpvar<'tcx> { impl fmt::Debug for ty::UpvarId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - PrintCx::with(FmtPrinter { fmt: f }, |cx| { + PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { print!(cx, write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, cx.tcx.hir().name(cx.tcx.hir().hir_to_node_id(self.var_path.hir_id)), @@ -922,7 +915,7 @@ define_print! { define_print! { () ty::Variance, (self, cx) { debug { - cx.printer.fmt.write_str(match *self { + cx.printer.write_str(match *self { ty::Covariant => "+", ty::Contravariant => "-", ty::Invariant => "o", From 9a278f4e14b221260b18577f36e3d4bc4460ccb0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 21 Dec 2018 17:10:21 +0200 Subject: [PATCH 28/68] rustc: merge PrintCx::parameterized and def_path printing. --- src/librustc/infer/error_reporting/mod.rs | 7 +- src/librustc/ty/print.rs | 336 ++++++++++++++------- src/librustc/util/ppaux.rs | 251 ++++++--------- src/librustc_codegen_utils/lib.rs | 1 + src/librustc_codegen_utils/symbol_names.rs | 114 ++++--- src/librustdoc/clean/mod.rs | 26 +- src/librustdoc/lib.rs | 1 + src/test/ui/symbol-names/impl1.rs | 2 +- src/test/ui/symbol-names/impl1.stderr | 4 +- 9 files changed, 445 insertions(+), 297 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 3e09b1a78ba98..893a9286b678e 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -451,8 +451,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate { let exp_path = self.tcx.def_path_str(did1); let found_path = self.tcx.def_path_str(did2); - let exp_abs_path = self.tcx.absolute_def_path_str(did1); - let found_abs_path = self.tcx.absolute_def_path_str(did2); + // HACK(eddyb) switch form `with_forced_absolute_paths` + // to a custom implementation of `ty::print::Printer`. + let (exp_abs_path, found_abs_path) = ty::print::with_forced_absolute_paths(|| { + (self.tcx.def_path_str(did1), self.tcx.def_path_str(did2)) + }); // We compare strings because DefPath can be different // for imported and non-imported crates if exp_path == found_path || exp_abs_path == found_abs_path { diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index f6052f7b66434..bc2c2d9f78425 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -2,7 +2,7 @@ use hir::def::Namespace; use hir::map::DefPathData; use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use ty::subst::{Subst, Substs}; +use ty::subst::{Kind, Subst, Substs, UnpackedKind}; use middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::{keywords, Symbol}; @@ -12,6 +12,7 @@ use syntax::symbol::InternedString; use std::cell::Cell; use std::fmt::{self, Write as _}; +use std::iter; use std::ops::Deref; thread_local! { @@ -149,16 +150,17 @@ pub trait Printer: Sized { fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, + projections: impl Iterator>, ) -> Self::Path { - self.default_print_def_path(def_id, substs, ns) + self.default_print_def_path(def_id, substs, ns, projections) } #[must_use] fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, ) -> Self::Path { self.default_print_impl_path(impl_def_id, substs, ns) @@ -167,6 +169,12 @@ pub trait Printer: Sized { #[must_use] fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path; #[must_use] + fn path_qualified( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Self::Path; + #[must_use] fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path; #[must_use] fn path_append( @@ -174,6 +182,15 @@ pub trait Printer: Sized { path: Self::Path, text: &str, ) -> Self::Path; + #[must_use] + fn path_generic_args( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + path: Self::Path, + params: &[ty::GenericParamDef], + substs: &'tcx Substs<'tcx>, + ns: Namespace, + projections: impl Iterator>, + ) -> Self::Path; } #[must_use] @@ -208,18 +225,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn def_path_str_with_substs_and_ns( self, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, ) -> String { debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); - if FORCE_ABSOLUTE.with(|force| force.get()) { - PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns) - } else { - let mut s = String::new(); - let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s }) - .print_def_path(def_id, substs, ns); - s - } + let mut s = String::new(); + let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s }) + .print_def_path(def_id, substs, ns, iter::empty()); + s } /// Returns a string identifying this def-id. This string is @@ -227,7 +240,11 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// root, unless with_forced_absolute_paths was used. pub fn def_path_str(self, def_id: DefId) -> String { let ns = self.guess_def_namespace(def_id); - self.def_path_str_with_substs_and_ns(def_id, None, ns) + debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns); + let mut s = String::new(); + let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s }) + .print_def_path(def_id, None, ns, iter::empty()); + s } /// Returns a string identifying this local node-id. @@ -235,26 +252,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn node_path_str(self, id: ast::NodeId) -> String { self.def_path_str(self.hir().local_def_id(id)) } - - /// Returns a string identifying this def-id. This string is - /// suitable for user output. It always begins with a crate identifier. - pub fn absolute_def_path_str(self, def_id: DefId) -> String { - debug!("absolute_def_path_str: def_id={:?}", def_id); - let ns = self.guess_def_namespace(def_id); - PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns) - } } impl PrintCx<'a, 'gcx, 'tcx, P> { pub fn default_print_def_path( &mut self, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, + projections: impl Iterator>, ) -> P::Path { debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); let key = self.tcx.def_key(def_id); debug!("default_print_def_path: key={:?}", key); + match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); @@ -265,35 +276,46 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self.print_impl_path(def_id, substs, ns) } - // Unclear if there is any value in distinguishing these. - // Probably eventually (and maybe we would even want - // finer-grained distinctions, e.g., between enum/struct). - data @ DefPathData::Misc | - data @ DefPathData::TypeNs(..) | - data @ DefPathData::Trait(..) | - data @ DefPathData::TraitAlias(..) | - data @ DefPathData::AssocTypeInTrait(..) | - data @ DefPathData::AssocTypeInImpl(..) | - data @ DefPathData::AssocExistentialInImpl(..) | - data @ DefPathData::ValueNs(..) | - data @ DefPathData::Module(..) | - data @ DefPathData::TypeParam(..) | - data @ DefPathData::LifetimeParam(..) | - data @ DefPathData::EnumVariant(..) | - data @ DefPathData::Field(..) | - data @ DefPathData::AnonConst | - data @ DefPathData::MacroDef(..) | - data @ DefPathData::ClosureExpr | - data @ DefPathData::ImplTrait | - data @ DefPathData::GlobalMetaData(..) => { - let parent_did = self.tcx.parent(def_id).unwrap(); - let path = self.print_def_path(parent_did, None, ns); - self.path_append(path, &data.as_interned_str().as_symbol().as_str()) - }, - - DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}` - let parent_def_id = self.tcx.parent(def_id).unwrap(); - self.print_def_path(parent_def_id, substs, ns) + _ => { + let generics = substs.map(|_| self.tcx.generics_of(def_id)); + let generics_parent = generics.as_ref().and_then(|g| g.parent); + let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id }; + let path = if let Some(generics_parent_def_id) = generics_parent { + assert_eq!(parent_def_id, generics_parent_def_id); + + // FIXME(eddyb) try to move this into the parent's printing + // logic, instead of doing it when printing the child. + let parent_generics = self.tcx.generics_of(parent_def_id); + let parent_has_own_self = + parent_generics.has_self && parent_generics.parent_count == 0; + if let (Some(substs), true) = (substs, parent_has_own_self) { + let trait_ref = ty::TraitRef::new(parent_def_id, substs); + self.path_qualified(trait_ref.self_ty(), Some(trait_ref)) + } else { + self.print_def_path(parent_def_id, substs, ns, iter::empty()) + } + } else { + self.print_def_path(parent_def_id, None, ns, iter::empty()) + }; + let path = match key.disambiguated_data.data { + // Skip `::{{constructor}}` on tuple/unit structs. + DefPathData::StructCtor => path, + + _ => { + self.path_append( + path, + &key.disambiguated_data.data.as_interned_str().as_str(), + ) + } + }; + + if let (Some(generics), Some(substs)) = (generics, substs) { + let has_own_self = generics.has_self && generics.parent_count == 0; + let params = &generics.params[has_own_self as usize..]; + self.path_generic_args(path, params, substs, ns, projections) + } else { + path + } } } } @@ -301,7 +323,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { fn default_print_impl_path( &mut self, impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, ) -> P::Path { debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); @@ -334,7 +356,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // If the impl is not co-located with either self-type or // trait-type, then fallback to a format that identifies // the module more clearly. - let path = self.print_def_path(parent_def_id, None, ns); + let path = self.print_def_path(parent_def_id, None, ns, iter::empty()); if let Some(trait_ref) = impl_trait_ref { return self.path_append(path, &format!("", trait_ref, self_ty)); } else { @@ -347,7 +369,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { if let Some(trait_ref) = impl_trait_ref { // Trait impls. - return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref)); + return self.path_qualified(self_ty, Some(trait_ref)); } // Inherent impls. Try to print `Foo::bar` for an inherent @@ -355,14 +377,10 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { // anything other than a simple path. match self_ty.sty { ty::Adt(adt_def, substs) => { - // FIXME(eddyb) this should recurse to build the path piecewise. - // self.print_def_path(adt_def.did, Some(substs), ns) - let mut s = String::new(); - ::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap(); - self.path_impl(&s) + self.print_def_path(adt_def.did, Some(substs), ns, iter::empty()) } - ty::Foreign(did) => self.print_def_path(did, None, ns), + ty::Foreign(did) => self.print_def_path(did, None, ns, iter::empty()), ty::Bool | ty::Char | @@ -374,7 +392,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } _ => { - self.path_impl(&format!("<{}>", self_ty)) + self.path_qualified(self_ty, None) } } } @@ -428,44 +446,15 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { } } -// FIXME(eddyb) remove, alongside `FORCE_ABSOLUTE` and `absolute_def_path_str`. -struct AbsolutePathPrinter; - -impl Printer for AbsolutePathPrinter { - type Path = String; - - fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { - self.tcx.original_crate_name(cnum).to_string() - } - fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { - text.to_string() - } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, - text: &str, - ) -> Self::Path { - if !path.is_empty() { - path.push_str("::"); - } - path.push_str(text); - path - } -} - pub struct FmtPrinter { pub fmt: F, } -impl FmtPrinter { +impl PrintCx<'a, 'gcx, 'tcx, P> { /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module and returns true. If the crate defining `def_id` is /// declared with an `extern crate`, the path is guaranteed to use the `extern crate`. - fn try_print_visible_def_path( - self: &mut PrintCx<'_, '_, '_, Self>, - def_id: DefId, - ns: Namespace, - ) -> Option<::Path> { + fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option { debug!("try_print_visible_def_path: def_id={:?}", def_id); // If `def_id` is a direct or injected extern crate, return the @@ -496,7 +485,7 @@ impl FmtPrinter { }) => { debug!("try_print_visible_def_path: def_id={:?}", def_id); let path = if !span.is_dummy() { - self.print_def_path(def_id, None, ns) + self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty()) } else { self.path_crate(cnum) }; @@ -529,7 +518,7 @@ impl FmtPrinter { } let visible_parent = visible_parent_map.get(&def_id).cloned()?; - let path = self.try_print_visible_def_path(visible_parent, ns)?; + let path = self.try_print_visible_def_path(visible_parent)?; let actual_parent = self.tcx.parent(def_id); let data = cur_def_key.disambiguated_data.data; @@ -595,6 +584,109 @@ impl FmtPrinter { debug!("try_print_visible_def_path: symbol={:?}", symbol); Some(self.path_append(path, &symbol)) } + + pub fn pretty_path_qualified( + &mut self, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> P::Path { + write!(self.printer, "<")?; + self_ty.print_display(self)?; + if let Some(trait_ref) = trait_ref { + write!(self.printer, " as ")?; + let _ = self.print_def_path( + trait_ref.def_id, + Some(trait_ref.substs), + Namespace::TypeNS, + iter::empty(), + )?; + } + write!(self.printer, ">")?; + Ok(PrettyPath { empty: false }) + } + + pub fn pretty_path_generic_args( + &mut self, + path: P::Path, + params: &[ty::GenericParamDef], + substs: &'tcx Substs<'tcx>, + ns: Namespace, + projections: impl Iterator>, + ) -> P::Path { + let path = path?; + + let mut empty = true; + let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { + if empty { + empty = false; + write!(cx.printer, "{}", start) + } else { + write!(cx.printer, "{}", cont) + } + }; + + let start = if ns == Namespace::ValueNS { "::<" } else { "<" }; + + // Don't print any regions if they're all erased. + let print_regions = params.iter().any(|param| { + match substs[param.index as usize].unpack() { + UnpackedKind::Lifetime(r) => *r != ty::ReErased, + _ => false, + } + }); + + // Don't print args that are the defaults of their respective parameters. + let num_supplied_defaults = if self.is_verbose { + 0 + } else { + params.iter().rev().take_while(|param| { + match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default && substs[param.index as usize] == Kind::from( + self.tcx.type_of(param.def_id).subst(self.tcx, substs) + ) + } + } + }).count() + }; + + for param in ¶ms[..params.len() - num_supplied_defaults] { + match substs[param.index as usize].unpack() { + UnpackedKind::Lifetime(region) => { + if !print_regions { + continue; + } + start_or_continue(self, start, ", ")?; + if !region.display_outputs_anything(self) { + // This happens when the value of the region + // parameter is not easily serialized. This may be + // because the user omitted it in the first place, + // or because it refers to some block in the code, + // etc. I'm not sure how best to serialize this. + write!(self.printer, "'_")?; + } else { + region.print_display(self)?; + } + } + UnpackedKind::Type(ty) => { + start_or_continue(self, start, ", ")?; + ty.print_display(self)?; + } + } + } + + for projection in projections { + start_or_continue(self, start, ", ")?; + write!(self.printer, "{}=", + self.tcx.associated_item(projection.item_def_id).ident)?; + projection.ty.print_display(self)?; + } + + start_or_continue(self, "", ">")?; + + Ok(path) + } } impl fmt::Write for FmtPrinter { @@ -609,21 +701,41 @@ impl Printer for FmtPrinter { fn print_def_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, + projections: impl Iterator>, ) -> Self::Path { - self.try_print_visible_def_path(def_id, ns) - .unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns)) + // FIXME(eddyb) avoid querying `tcx.generics_of` + // both here and in `default_print_def_path`. + let generics = substs.map(|_| self.tcx.generics_of(def_id)); + if // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` + !FORCE_ABSOLUTE.with(|force| force.get()) && + generics.as_ref().and_then(|g| g.parent).is_none() { + if let Some(path) = self.try_print_visible_def_path(def_id) { + let path = if let (Some(generics), Some(substs)) = (generics, substs) { + let has_own_self = generics.has_self && generics.parent_count == 0; + let params = &generics.params[has_own_self as usize..]; + self.path_generic_args(path, params, substs, ns, projections) + } else { + path + }; + return path; + } + } + + self.default_print_def_path(def_id, substs, ns, projections) } fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option<&'tcx Substs<'tcx>>, ns: Namespace, ) -> Self::Path { // Always use types for non-local impls, where types are always // available, and filename/line-number is mostly uninteresting. - let use_types = !impl_def_id.is_local() || { + let use_types = // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` + FORCE_ABSOLUTE.with(|force| force.get()) || + !impl_def_id.is_local() || { // Otherwise, use filename/line-number if forced. let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get()); !force_no_types @@ -634,7 +746,7 @@ impl Printer for FmtPrinter { // pretty printing some span information. This should // only occur very early in the compiler pipeline. let parent_def_id = self.tcx.parent(impl_def_id).unwrap(); - let path = self.print_def_path(parent_def_id, None, ns); + let path = self.print_def_path(parent_def_id, None, ns, iter::empty()); let span = self.tcx.def_span(impl_def_id); return self.path_append(path, &format!("", span)); } @@ -643,6 +755,11 @@ impl Printer for FmtPrinter { } fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter` + if FORCE_ABSOLUTE.with(|force| force.get()) { + write!(self.printer, "{}", self.tcx.original_crate_name(cnum))?; + return Ok(PrettyPath { empty: false }); + } if cnum == LOCAL_CRATE { if self.tcx.sess.rust_2018() { // We add the `crate::` keyword on Rust 2018, only when desired. @@ -657,6 +774,13 @@ impl Printer for FmtPrinter { Ok(PrettyPath { empty: false }) } } + fn path_qualified( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + self_ty: Ty<'tcx>, + trait_ref: Option>, + ) -> Self::Path { + self.pretty_path_qualified(self_ty, trait_ref) + } fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { write!(self.printer, "{}", text)?; Ok(PrettyPath { empty: false }) @@ -680,6 +804,16 @@ impl Printer for FmtPrinter { write!(self.printer, "{}", text)?; Ok(PrettyPath { empty: false }) } + fn path_generic_args( + self: &mut PrintCx<'_, '_, 'tcx, Self>, + path: Self::Path, + params: &[ty::GenericParamDef], + substs: &'tcx Substs<'tcx>, + ns: Namespace, + projections: impl Iterator>, + ) -> Self::Path { + self.pretty_path_generic_args(path, params, substs, ns, projections) + } } impl PrettyPrinter for FmtPrinter {} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index fcee97f0cb7cc..2ed6a036a4bd8 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,6 +1,5 @@ use hir::def::Namespace; use hir::def_id::DefId; -use hir::map::definitions::DefPathData; use middle::region; use ty::subst::{Kind, Subst, Substs, UnpackedKind}; use ty::{BrAnon, BrEnv, BrFresh, BrNamed}; @@ -10,7 +9,7 @@ use ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use ty::{self, Ty, TypeFoldable}; -use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; +use ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use std::cell::Cell; use std::fmt::{self, Write as _}; @@ -284,125 +283,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { Ok(()) } - fn parameterized( - &mut self, - def_id: DefId, - substs: &Substs<'tcx>, - ns: Namespace, - projections: impl Iterator>, - ) -> fmt::Result { - let key = self.tcx.def_key(def_id); - let generics = self.tcx.generics_of(def_id); - - if let Some(parent_def_id) = generics.parent { - assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id }); - - let parent_generics = self.tcx.generics_of(parent_def_id); - let parent_has_own_self = - parent_generics.has_self && parent_generics.parent_count == 0; - if parent_has_own_self { - print!(self, write("<"), print_display(substs.type_at(0)), write(" as "))?; - self.parameterized(parent_def_id, substs, Namespace::TypeNS, iter::empty())?; - print!(self, write(">"))?; - } else { - self.parameterized(parent_def_id, substs, ns, iter::empty())?; - } - - // Skip `::{{constructor}}` on tuple/unit structs. - match key.disambiguated_data.data { - DefPathData::StructCtor => {} - - _ => { - print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?; - } - } - } else { - // FIXME(eddyb) recurse through printing a path via `self`, instead - // instead of using the `tcx` method that produces a `String`. - print!(self, write("{}", - self.tcx.def_path_str_with_substs_and_ns(def_id, Some(substs), ns)))?; - - // For impls, the above call already prints relevant generics args. - if let DefPathData::Impl = key.disambiguated_data.data { - return Ok(()); - } - } - - let mut empty = true; - let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| { - if empty { - empty = false; - print!(cx, write("{}", start)) - } else { - print!(cx, write("{}", cont)) - } - }; - - let start = if ns == Namespace::ValueNS { "::<" } else { "<" }; - - let has_own_self = generics.has_self && generics.parent_count == 0; - let params = &generics.params[has_own_self as usize..]; - - // Don't print any regions if they're all erased. - let print_regions = params.iter().any(|param| { - match substs[param.index as usize].unpack() { - UnpackedKind::Lifetime(r) => *r != ty::ReErased, - _ => false, - } - }); - - // Don't print args that are the defaults of their respective parameters. - let num_supplied_defaults = if self.is_verbose { - 0 - } else { - params.iter().rev().take_while(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => false, - ty::GenericParamDefKind::Type { has_default, .. } => { - has_default && substs[param.index as usize] == Kind::from( - self.tcx.type_of(param.def_id).subst(self.tcx, substs) - ) - } - } - }).count() - }; - - for param in ¶ms[..params.len() - num_supplied_defaults] { - match substs[param.index as usize].unpack() { - UnpackedKind::Lifetime(region) => { - if !print_regions { - continue; - } - start_or_continue(self, start, ", ")?; - if !region.display_outputs_anything(self) { - // This happens when the value of the region - // parameter is not easily serialized. This may be - // because the user omitted it in the first place, - // or because it refers to some block in the code, - // etc. I'm not sure how best to serialize this. - print!(self, write("'_"))?; - } else { - region.print_display(self)?; - } - } - UnpackedKind::Type(ty) => { - start_or_continue(self, start, ", ")?; - ty.print_display(self)?; - } - } - } - - for projection in projections { - start_or_continue(self, start, ", ")?; - print!(self, - write("{}=", - self.tcx.associated_item(projection.item_def_id).ident), - print_display(projection.ty))?; - } - - start_or_continue(self, "", ">") - } - fn in_binder(&mut self, value: &ty::Binder) -> fmt::Result where T: Print<'tcx, P, Output = fmt::Result> + TypeFoldable<'tcx> { @@ -485,7 +365,8 @@ pub fn parameterized( ) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { let substs = cx.tcx.lift(&substs).expect("could not lift for printing"); - cx.parameterized(did, substs, ns, iter::empty()) + let _ = cx.print_def_path(did, Some(substs), ns, iter::empty())?; + Ok(()) }) } @@ -503,7 +384,12 @@ define_print! { if let Tuple(ref args) = principal.substs.type_at(0).sty { let mut projections = self.projection_bounds(); if let (Some(proj), None) = (projections.next(), projections.next()) { - print!(cx, write("{}", cx.tcx.def_path_str(principal.def_id)))?; + let _ = cx.print_def_path( + principal.def_id, + None, + Namespace::TypeNS, + iter::empty(), + )?; cx.fn_sig(args, false, proj.ty)?; resugared_principal = true; } @@ -514,9 +400,9 @@ define_print! { // Use a type that can't appear in defaults of type parameters. let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); let principal = principal.with_self_ty(cx.tcx, dummy_self); - cx.parameterized( + let _ = cx.print_def_path( principal.def_id, - principal.substs, + Some(principal.substs), Namespace::TypeNS, self.projection_bounds(), )?; @@ -525,8 +411,10 @@ define_print! { } // Builtin bounds. + // FIXME(eddyb) avoid printing twice (needed to ensure + // that the auto traits are sorted *and* printed via cx). let mut auto_traits: Vec<_> = self.auto_traits().map(|did| { - cx.tcx.def_path_str(did) + (cx.tcx.def_path_str(did), did) }).collect(); // The auto traits come ordered by `DefPathHash`. While @@ -538,13 +426,18 @@ define_print! { // output, sort the auto-traits alphabetically. auto_traits.sort(); - for auto_trait in auto_traits { + for (_, def_id) in auto_traits { if !first { print!(cx, write(" + "))?; } first = false; - print!(cx, write("{}", auto_trait))?; + let _ = cx.print_def_path( + def_id, + None, + Namespace::TypeNS, + iter::empty(), + )?; } Ok(()) @@ -569,7 +462,13 @@ impl fmt::Debug for ty::GenericParamDef { impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { - print!(cx, write("{}", cx.tcx.def_path_str(self.def_id))) + let _ = cx.print_def_path( + self.def_id, + None, + Namespace::TypeNS, + iter::empty(), + )?; + Ok(()) }) } } @@ -577,7 +476,13 @@ impl fmt::Debug for ty::TraitDef { impl fmt::Debug for ty::AdtDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { PrintCx::with(FmtPrinter { fmt: f }, |mut cx| { - print!(cx, write("{}", cx.tcx.def_path_str(self.did))) + let _ = cx.print_def_path( + self.did, + None, + Namespace::TypeNS, + iter::empty(), + )?; + Ok(()) }) } } @@ -639,10 +544,10 @@ define_print! { display { let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0)); - let trait_ref = *ty::Binder::bind(*self) + ty::Binder::bind(*self) .with_self_ty(cx.tcx, dummy_self) - .skip_binder(); - cx.parameterized(trait_ref.def_id, trait_ref.substs, Namespace::TypeNS, iter::empty()) + .skip_binder() + .print_display(cx) } debug { self.print_display(cx) @@ -868,7 +773,8 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::RegionKind { - fn display_outputs_anything