From 228d6f45d8fbf289e6505d12379a41e13a0872a1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Dec 2018 22:42:08 +0200 Subject: [PATCH 01/70] 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 26e2705a7a0..6734e264305 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. @@ -327,36 +325,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 { @@ -372,7 +356,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. @@ -396,7 +380,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 { @@ -420,13 +404,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 | @@ -447,7 +431,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 { @@ -455,7 +438,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 hir_id = self.hir().as_local_hir_id(impl_def_id).unwrap(); let item = self.hir().expect_item_by_hir_id(hir_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 5de5c297c30..91301158abd 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 { let mut buffer = SymbolPathBuffer::new(tcx); 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 f2bf7ead561..af40e417d61 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4243,7 +4243,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 382d24e7d73e36fa150866051e700a2307916f77 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:13:37 +0200 Subject: [PATCH 02/70] 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 68bdae7d744..23fa81f77df 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -99,6 +99,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 00000000000..f58bb2824d1 --- /dev/null +++ b/src/librustc/ty/print.rs @@ -0,0 +1,91 @@ +use crate::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 a1398c69ff0..24b9779654a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,8 +9,8 @@ use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst}; +use crate::ty::print::{PrintContext, Print}; use crate::mir::interpret::ConstValue; -use crate::util::nodemap::FxHashSet; 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 297546e62db0ec681482baf31d0bd6dd733fdd39 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:13:55 +0200 Subject: [PATCH 03/70] 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 f58bb2824d1..569d9d7a3ac 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 24b9779654a..9fc4b179954 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 @@ -527,12 +527,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 { @@ -627,7 +630,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) } @@ -1466,7 +1469,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 372b1a5930f3dc2b878ae0ed3c0d939451c8ac24 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:25:17 +0200 Subject: [PATCH 04/70] 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 9fc4b179954..dc3160b7ab9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -648,11 +648,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)?; @@ -781,7 +781,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 852fc6d2b61e7b1f45f2679d025b824af70f89b1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 19:35:48 +0200 Subject: [PATCH 05/70] 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 dc3160b7ab9..0dc1aea0a96 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -404,17 +404,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; } } } @@ -527,15 +526,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 { @@ -550,12 +547,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); } @@ -1101,7 +1092,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"))) } }*/ @@ -1118,7 +1110,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"))) } } } @@ -1186,10 +1179,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, &[])?; @@ -1260,11 +1252,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; @@ -1331,7 +1321,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 c6848141026853e8d59cf8b6f3a3bb2f76e06128 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 4 Dec 2018 20:04:21 +0200 Subject: [PATCH 06/70] 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 569d9d7a3ac..5f46806e159 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 5f3841ca2fe5cf0ba714db42a29a8004a878b6e6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 16:17:44 +0200 Subject: [PATCH 07/70] 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 c7936534aad..ebed768fa54 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -683,7 +683,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 5f46806e159..3d6dec8a141 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 0dc1aea0a96..683e0aa0dab 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst}; -use crate::ty::print::{PrintContext, Print}; +use crate::ty::print::{PrintCx, Print}; use crate::mir::interpret::ConstValue; use std::cell::Cell; @@ -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<'_>], @@ -618,11 +618,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 0b3ab4018b41c42ce29c265fb8c06b13ac90b355 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 15:22:50 +0200 Subject: [PATCH 08/70] 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 | 337 +++++++++++++++++-------------------- 3 files changed, 189 insertions(+), 207 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3a4422a6239..b04bb5b3d01 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2369,17 +2369,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 3d6dec8a141..fb296519d49 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, TypeFoldable}; +use crate::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 683e0aa0dab..ff66df4e4a3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,7 +8,7 @@ use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst}; +use crate::ty::{self, Ty, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst}; use crate::ty::print::{PrintCx, Print}; use crate::mir::interpret::ConstValue; @@ -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(_) | @@ -360,9 +368,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; @@ -370,7 +377,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 { @@ -404,23 +411,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; @@ -482,12 +488,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))?; } // FIXME(const_generics::defaults) @@ -526,12 +530,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 { @@ -563,7 +562,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) => { @@ -581,10 +580,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, "", "> ")?; @@ -605,24 +604,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: SubstsRef<'_>, 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) } } @@ -631,50 +622,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) + // 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(cx.tcx, dummy_self); + let projections = self.projection_bounds().map(|p| { + cx.tcx.lift(&p) .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; + .with_self_ty(cx.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| { + 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; - // 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; - - write!(f, "{}", auto_trait)?; - } - - Ok(()) - })?; + write!(f, "{}", auto_trait)?; + } Ok(()) } @@ -698,16 +686,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)) }) } } @@ -724,7 +712,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_by_hir_id(self.var_path.hir_id)), + PrintCx::with(|cx| { + cx.tcx.hir().name_by_hir_id(self.var_path.hir_id) + }), self.closure_expr_id) } } @@ -768,14 +758,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, &[]) } } } @@ -1092,7 +1080,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"))) } }*/ @@ -1110,8 +1098,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")) } } } @@ -1178,12 +1166,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, "}}") } @@ -1235,71 +1221,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); + 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()) == tcx.lang_items().sized_trait() { - is_sized = true; - continue; - } - - print!(f, cx, - write("{}", if first { " " } else { "+" }), - print(trait_ref))?; - first = false; + 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(hir_id) = tcx.hir().as_local_hir_id(did) { - write!(f, "@{:?}", tcx.hir().span_by_hir_id(hir_id))?; + if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) { + write!(f, "@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))?; let mut sep = " "; - tcx.with_freevars(hir_id, |freevars| { + cx.tcx.with_freevars(hir_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 = ", "; } @@ -1319,28 +1303,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(hir_id) = tcx.hir().as_local_hir_id(did) { - if tcx.sess.opts.debugging_opts.span_free_formats { + if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) { + if cx.tcx.sess.opts.debugging_opts.span_free_formats { write!(f, "@{:?}", hir_id)?; } else { - write!(f, "@{:?}", tcx.hir().span_by_hir_id(hir_id))?; + write!(f, "@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))?; } let mut sep = " "; - tcx.with_freevars(hir_id, |freevars| { + cx.tcx.with_freevars(hir_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 = ", "; } @@ -1369,21 +1353,21 @@ 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| { + ty::LazyConst::Evaluated(c) => { match c.val { - ConstValue::Infer(..) => write!(f, "_"), + ConstValue::Infer(..) => write!(f, "_")?, ConstValue::Param(ParamConst { name, .. }) => - write!(f, "{}", name), - _ => write!(f, "{}", c.unwrap_usize(tcx)), + write!(f, "{}", name)?, + _ => write!(f, "{}", c.unwrap_usize(cx.tcx))?, } - })?, + } } write!(f, "]") } @@ -1510,9 +1494,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)) } } @@ -1540,15 +1523,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 01fa283d6feac5838317d0b16e4dda8dff3e4826 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 19:14:30 +0200 Subject: [PATCH 09/70] 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 a3e8598194e..ea1c9d81416 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 c7674ae7a28..0dd076481c8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -854,10 +854,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() { @@ -1686,10 +1687,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 3a31801b3be..b245d903799 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 39728cc8cd5..20acbb5b9c7 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -84,7 +84,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, +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable)] pub enum TyKind<'tcx> { /// The primitive boolean type. Written as `bool`. @@ -383,9 +383,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 ff66df4e4a3..7f41947fbb9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1124,9 +1124,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()), @@ -1376,16 +1376,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 3268af396a2..12edb3a0907 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -513,8 +513,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()), @@ -528,7 +527,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; } } @@ -1473,8 +1472,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!(); } }; @@ -1488,7 +1487,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]); } } @@ -1573,8 +1572,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!(); } }; @@ -1588,7 +1587,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]); } } @@ -1954,10 +1953,10 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo } } -// 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 349c9132842..2bb68dc687c 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: Vec<_> = (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 7c5e615f224..fe00276a55a 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 fe07cc0698a..aa3750946d3 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -1799,7 +1799,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 7749b3a5ca4..c8c6d73d453 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -955,7 +955,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_type(expr.hir_id).sty { + let ty = cx.tables().node_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) => { @@ -968,7 +969,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 67d40197290..8aa4fdedc18 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -529,11 +529,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), } } @@ -554,7 +554,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), } } @@ -608,7 +608,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); @@ -744,7 +744,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 4618cd42686..c9dae699079 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_type(hir_id).sty { + let ty = self.tables().node_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 73c73cc23dc..7543dd678d0 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 b3b9c742d6c..944e393d296 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -336,7 +336,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> let layout = val.layout; let val = val.to_scalar()?; - 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 4df274bc9df..755bbd96b02 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -354,7 +354,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 1e245faddf0..bfdf34f3e37 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -836,7 +836,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 89ec92a6521..fd09ce7f689 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -959,7 +959,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 1a3ade7f8ba..342a214e0cc 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. @@ -894,7 +894,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 28c79ce0c74..c40bdae0762 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3885,7 +3885,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(..) | @@ -5226,8 +5226,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 3e6e6576b63..a76dfdd69ba 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -93,19 +93,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_hir_id, - t + ty ); } }; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index fde940eb2c1..92c44e24998 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -618,7 +618,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 d001545d1d9..4a3d4f31a24 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -472,7 +472,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 3bad9f7b3d09a49277d5861733706f03dde1e7c5 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 20:10:47 +0200 Subject: [PATCH 10/70] 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 7f41947fbb9..6d09f72a76b 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1124,7 +1124,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 61b1a5a850d..41e16684b8a 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -141,7 +141,7 @@ fn write_graph_label<'a, 'gcx, 'tcx, W: Write>(tcx: TyCtxt<'a, 'gcx, 'tcx>, )?; } - 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 52514a3ca97..c7e63a83b15 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -134,7 +134,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 eb525b0916e0b228000a6d3ddfb57979cd5342f6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 7 Dec 2018 17:40:23 +0200 Subject: [PATCH 11/70] 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 | 32 ++++ src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 6 +- src/librustc/util/ppaux.rs | 139 ++++++++---------- src/librustc_codegen_llvm/intrinsic.rs | 4 +- 10 files changed, 115 insertions(+), 94 deletions(-) diff --git a/src/librustc/infer/outlives/free_region_map.rs b/src/librustc/infer/outlives/free_region_map.rs index 78353e52ad4..5349e990a77 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 b04bb5b3d01..bff07de5bcf 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2405,7 +2405,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 e0b7bbc68e2..0a49dea7ec1 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -175,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.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 23fa81f77df..dbccd60f86b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1001,7 +1001,7 @@ impl<'a, 'gcx, 'tcx> Generics { } /// Bounds on generics. -#[derive(Clone, Default, HashStable)] +#[derive(Clone, Default, Debug, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option, pub predicates: Vec<(Predicate<'tcx>, Span)>, @@ -1506,7 +1506,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 fb296519d49..a9fffa2ee87 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 f9eb336a4a3..a19eb1d9545 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -48,7 +48,10 @@ CloneTypeFoldableAndLiftImpls! { // really meant to be folded. In general, we can only fold a fully // general `Region`. crate::ty::BoundRegion, + crate::ty::Placeholder, crate::ty::ClosureKind, + crate::ty::FreeRegion, + crate::ty::InferTy, crate::ty::IntVarValue, crate::ty::ParamConst, crate::ty::ParamTy, @@ -480,6 +483,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>; @@ -494,6 +504,28 @@ BraceStructLiftImpl! { } } +// FIXME(eddyb) this is like what some of the macros above generate, +// except that macros *also* generate a foldable impl, which we don't +// want (with it we'd risk bypassing `fold_region` / `fold_const`). +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()) + } +} + +impl<'a, 'tcx> Lift<'tcx> for ty::LazyConst<'a> { + type Lifted = ty::LazyConst<'tcx>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { + match self { + ty::LazyConst::Evaluated(v) => Some(ty::LazyConst::Evaluated(tcx.lift(v)?)), + ty::LazyConst::Unevaluated(def_id, substs) => { + Some(ty::LazyConst::Unevaluated(*def_id, tcx.lift(substs)?)) + } + } + } +} + 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 20acbb5b9c7..0e4b43155d9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -616,7 +616,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 38be19a71c4..85a05bb9f55 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -140,9 +140,9 @@ 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(lt) => lt.lift_to_tcx(tcx).map(|lt| lt.into()), - UnpackedKind::Type(ty) => ty.lift_to_tcx(tcx).map(|ty| ty.into()), - UnpackedKind::Const(ct) => ct.lift_to_tcx(tcx).map(|ct| ct.into()), + UnpackedKind::Lifetime(lt) => tcx.lift(<).map(|lt| lt.into()), + UnpackedKind::Type(ty) => tcx.lift(&ty).map(|ty| ty.into()), + UnpackedKind::Const(ct) => tcx.lift(&ct).map(|ct| ct.into()), } } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 6d09f72a76b..b56ce0665e9 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -14,6 +14,7 @@ use crate::mir::interpret::ConstValue; 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>], c_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: SubstsRef<'_>, - did: DefId, - projections: &[ty::ProjectionPredicate<'_>]) - -> fmt::Result { + fn parameterized( + &mut self, + f: &mut F, + did: DefId, + substs: SubstsRef<'tcx>, + projections: impl Iterator> + Clone, + ) -> fmt::Result { let key = self.tcx.def_key(did); let verbose = self.is_verbose; @@ -411,7 +415,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 { @@ -428,10 +431,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); + } } } @@ -490,7 +495,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))?; } @@ -530,7 +535,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 { @@ -547,7 +552,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; @@ -562,7 +567,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) => { @@ -604,16 +609,15 @@ impl PrintCx<'a, 'gcx, 'tcx> { } } -pub fn parameterized(f: &mut F, - substs: SubstsRef<'_>, - 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: SubstsRef<'_>) -> 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) } } @@ -628,16 +632,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(cx.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; } @@ -755,15 +756,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) } } } @@ -957,22 +958,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 { @@ -1098,8 +1083,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) } } } @@ -1107,7 +1091,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 @@ -1117,7 +1101,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, ">") } } @@ -1166,11 +1150,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) => { @@ -1192,7 +1174,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() { @@ -1206,7 +1188,9 @@ define_print! { Ok(()) } } - Foreign(def_id) => parameterized(f, subst::InternalSubsts::empty(), def_id, &[]), + Foreign(def_id) => { + cx.parameterized(f, def_id, subst::InternalSubsts::empty(), iter::empty()) + } Projection(ref data) => data.print(f, cx), UnnormalizedProjection(ref data) => { write!(f, "Unnormalized(")?; @@ -1237,8 +1221,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; @@ -1305,8 +1287,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); @@ -1347,8 +1328,8 @@ define_print! { write!( f, " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.closure_kind_ty(did, tcx), - substs.closure_sig_ty(did, tcx), + substs.closure_kind_ty(did, cx.tcx), + substs.closure_sig_ty(did, cx.tcx), )?; } @@ -1435,8 +1416,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)) @@ -1524,7 +1509,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") } } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 12edb3a0907..ceb08f94367 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1903,7 +1903,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#, return_error!( "expected element type `{}` of vector type `{}` \ to be a signed or unsigned integer type", - arg_tys[0].simd_type(tcx).sty, arg_tys[0] + arg_tys[0].simd_type(tcx), arg_tys[0] ); } }; @@ -1955,7 +1955,7 @@ fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, boo // Returns the width of a float Ty // Returns None if the type is not a float -fn float_type_width(ty: Ty) -> Option { +fn float_type_width(ty: Ty<'_>) -> Option { match ty.sty { ty::Float(t) => Some(t.bit_width() as u64), _ => None, From 939c69c71f8583e37f536a0c6da75c31bc878383 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 8 Dec 2018 01:13:23 +0200 Subject: [PATCH 12/70] 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 85a05bb9f55..973f7f15f84 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -13,7 +13,6 @@ use rustc_macros::HashStable; use core::intrinsics; use std::cmp::Ordering; -use std::fmt; use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; @@ -115,26 +114,8 @@ 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), UnpackedKind::Const(ct) => write!(f, "{:?}", ct), - } - } -} - -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), UnpackedKind::Const(ct) => write!(f, "{}", ct), - } - } -} - 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 b56ce0665e9..c2b2cf4e62f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,7 @@ use crate::hir::def_id::DefId; use crate::hir::map::definitions::DefPathData; use crate::middle::region; -use crate::ty::subst::{self, Subst, SubstsRef}; +use crate::ty::subst::{self, Kind, Subst, SubstsRef, UnpackedKind}; use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use crate::ty::{Bool, Char, Adt}; use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; @@ -1535,3 +1535,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 fbbc7e915d362d6e0705197c884fce23246acd1d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 8 Dec 2018 11:26:34 +0200 Subject: [PATCH 13/70] rustc: rewrite PrintCx::parameterized to be much simpler and more general. --- src/librustc/ty/sty.rs | 2 +- src/librustc/ty/subst.rs | 2 - src/librustc/util/ppaux.rs | 331 ++++++++++++++----------------------- 3 files changed, 125 insertions(+), 210 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0e4b43155d9..20acbb5b9c7 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -616,7 +616,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/ty/subst.rs b/src/librustc/ty/subst.rs index 973f7f15f84..8c67cdf62b6 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -114,8 +114,6 @@ impl<'tcx> Kind<'tcx> { } } - UnpackedKind::Const(ct) => write!(f, "{:?}", ct), - UnpackedKind::Const(ct) => write!(f, "{}", ct), 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 c2b2cf4e62f..8dfa924c1df 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,7 +8,7 @@ use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; -use crate::ty::{self, Ty, TypeFoldable, GenericParamCount, GenericParamDefKind, ParamConst}; +use crate::ty::{self, ParamConst, Ty, TypeFoldable}; use crate::ty::print::{PrintCx, Print}; use crate::mir::interpret::ConstValue; @@ -314,225 +314,130 @@ impl PrintCx<'a, 'gcx, 'tcx> { fn parameterized( &mut self, f: &mut F, - did: DefId, + mut def_id: DefId, substs: SubstsRef<'tcx>, - projections: impl Iterator> + Clone, + projections: impl Iterator>, ) -> fmt::Result { - let key = self.tcx.def_key(did); + let mut key = self.tcx.def_key(def_id); + let is_value_ns = match key.disambiguated_data.data { + DefPathData::ValueNs(_) | + DefPathData::EnumVariant(_) => true, - 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::ConstParam(_) | - 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 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; - } + // 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 } - 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)) - } - GenericParamDefKind::Const => None, // FIXME(const_generics:defaults) - }).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; - } - } - } - } - 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); + _ => false, + }; - 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); - } + 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 "))?; } + 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 { "<" }; - 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, "'_")?; - } else { - write!(f, "{}", s)?; + 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) + ) } + ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) } - } - - Ok(()) + }).count() }; - 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 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 { + 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)?; + } + UnpackedKind::Const(ct) => { + start_or_continue(f, start, ", ")?; + ct.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))?; } - // FIXME(const_generics::defaults) - let consts = substs.consts(); - - for ct in consts { - start_or_continue(f, "<", ", ")?; - ct.print_display(f, self)?; - } - - 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 @@ -626,19 +531,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; } @@ -1468,12 +1388,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()) } } } @@ -1542,12 +1457,14 @@ define_print! { match self.unpack() { UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), UnpackedKind::Type(ty) => print!(f, cx, print(ty)), + UnpackedKind::Const(ct) => print!(f, cx, print(ct)), } } debug { match self.unpack() { UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), UnpackedKind::Type(ty) => print!(f, cx, print(ty)), + UnpackedKind::Const(ct) => print!(f, cx, print(ct)), } } } From 1c2a3c5d79b9c6ee2ab4257eda41f1a86b273ef5 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Dec 2018 17:54:18 +0200 Subject: [PATCH 14/70] 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 | 2 +- src/test/ui/issues/issue-22638.rs | 2 +- src/test/ui/issues/issue-22638.stderr | 2 +- 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, 32 insertions(+), 16 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 8dfa924c1df..6667d378733 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 37794c6e077..d628573d517 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 418c2c73ba1..0a273bc98ff 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -1,4 +1,4 @@ -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(); diff --git a/src/test/ui/issues/issue-22638.rs b/src/test/ui/issues/issue-22638.rs index fab24404eba..ff58c7aaced 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 aff968f3618..65483abe5c7 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -1,4 +1,4 @@ -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) { diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr index def373cf2c0..b284c8cf117 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; | ^^^^^^^^ 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 1cd3f84f7a2..8062045a6c0 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 3beb7289788..67f188e0588 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 700dbe36474..ca2f2a5ba28 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 c3ae920238f..b6fd22fa669 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 6471a7914e1..69be9d2cea6 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 926b098040f..6315ec2e512 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:: => {} | ^^^^^^^^^^^^^^^^^^^^^ 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 7505bb6bbb7d66f445d7df7afc7c397dadea26f8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 3 Feb 2019 12:24:29 +0200 Subject: [PATCH 15/70] rustc_codegen_utils: revert some symbol_names refactors (while keeping the functional changes). --- src/librustc_codegen_utils/symbol_names.rs | 135 ++++++++++----------- 1 file changed, 61 insertions(+), 74 deletions(-) diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 91301158abd..70ab185660c 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -380,79 +380,6 @@ impl SymbolPathBuffer { let _ = write!(self.result, "17h{:016x}E", hash); self.result } - - // 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, ., _, $ - // NVPTX assembly has more strict naming rules than gas, so additionally, dots - // are replaced with '$' there. - fn sanitize_and_append(&mut self, s: &str) { - self.temp_buf.clear(); - - for c in s.chars() { - match c { - // Escape these with $ sequences - '@' => self.temp_buf.push_str("$SP$"), - '*' => self.temp_buf.push_str("$BP$"), - '&' => self.temp_buf.push_str("$RF$"), - '<' => self.temp_buf.push_str("$LT$"), - '>' => self.temp_buf.push_str("$GT$"), - '(' => self.temp_buf.push_str("$LP$"), - ')' => self.temp_buf.push_str("$RP$"), - ',' => self.temp_buf.push_str("$C$"), - - '-' | ':' => if self.strict_naming { - // NVPTX doesn't support these characters in symbol names. - self.temp_buf.push('$') - } - else { - // '.' doesn't occur in types and functions, so reuse it - // for ':' and '-' - self.temp_buf.push('.') - }, - - '.' => if self.strict_naming { - self.temp_buf.push('$') - } - else { - self.temp_buf.push('.') - }, - - // These are legal symbols - 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '$' => self.temp_buf.push(c), - - _ => { - self.temp_buf.push('$'); - for c in c.escape_unicode().skip(1) { - match c { - '{' => {} - '}' => self.temp_buf.push('$'), - c => self.temp_buf.push(c), - } - } - } - } - } - - let need_underscore = { - // Underscore-qualify anything that didn't start as an ident. - !self.temp_buf.is_empty() - && self.temp_buf.as_bytes()[0] != '_' as u8 - && !(self.temp_buf.as_bytes()[0] as char).is_xid_start() - }; - - let _ = write!( - self.result, - "{}", - self.temp_buf.len() + (need_underscore as usize) - ); - - if need_underscore { - self.result.push('_'); - } - - self.result.push_str(&self.temp_buf); - } } impl ItemPathBuffer for SymbolPathBuffer { @@ -462,6 +389,66 @@ impl ItemPathBuffer for SymbolPathBuffer { } fn push(&mut self, text: &str) { - self.sanitize_and_append(text); + self.temp_buf.clear(); + let need_underscore = sanitize(&mut self.temp_buf, text, self.strict_naming); + let _ = write!( + self.result, + "{}", + self.temp_buf.len() + (need_underscore as usize) + ); + if need_underscore { + self.result.push('_'); + } + self.result.push_str(&self.temp_buf); } } + +// 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, ., _, $ +// NVPTX assembly has more strict naming rules than gas, so additionally, dots +// are replaced with '$' there. +// +// returns true if an underscore must be added at the start +fn sanitize(result: &mut String, s: &str, strict_naming: bool) -> bool { + for c in s.chars() { + match c { + // Escape these with $ sequences + '@' => result.push_str("$SP$"), + '*' => result.push_str("$BP$"), + '&' => result.push_str("$RF$"), + '<' => result.push_str("$LT$"), + '>' => result.push_str("$GT$"), + '(' => result.push_str("$LP$"), + ')' => result.push_str("$RP$"), + ',' => result.push_str("$C$"), + + '-' | ':' | '.' if strict_naming => { + // NVPTX doesn't support these characters in symbol names. + result.push('$') + } + + // '.' doesn't occur in types and functions, so reuse it + // for ':' and '-' + '-' | ':' => result.push('.'), + + // These are legal symbols + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => result.push(c), + + _ => { + result.push('$'); + for c in c.escape_unicode().skip(1) { + match c { + '{' => {} + '}' => result.push('$'), + c => result.push(c), + } + } + } + } + } + + // 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() +} From 7d211e5b1287f9140418c4e46461c451d1da42e1 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Dec 2018 21:05:22 +0200 Subject: [PATCH 16/70] rustc: rewrite ty::item_path to be more functional than mutation-oriented. --- src/librustc/ty/item_path.rs | 236 ++++++++++++--------- src/librustc_codegen_utils/symbol_names.rs | 65 ++++-- 2 files changed, 172 insertions(+), 129 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 6734e264305..1eb3952032a 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,60 @@ 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 +181,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 +223,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 +280,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. @@ -325,26 +342,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 @@ -356,7 +373,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. @@ -380,13 +397,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 @@ -394,8 +410,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 @@ -403,14 +418,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 | @@ -418,31 +434,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 hir_id = self.hir().as_local_hir_id(impl_def_id).unwrap(); let item = self.hir().expect_item_by_hir_id(hir_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 `DefId` of `def_id`'s parent in the def tree. If @@ -505,12 +521,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 @@ -524,33 +545,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 70ab185660c..13f8e13c328 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::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -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 { - let mut buffer = SymbolPathBuffer::new(tcx); item_path::with_forced_absolute_paths(|| { - tcx.push_item_path(&mut buffer, def_id); - }); - buffer.into_interned() + tcx.push_item_path(&mut SymbolPath::new(tcx), def_id).into_interned() + }) } fn symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance<'tcx>) -> ty::SymbolName { @@ -319,7 +317,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), tcx); + let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id), tcx); if instance.is_vtable_shim() { buf.push("{{vtable-shim}}"); @@ -342,15 +340,15 @@ 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, strict_naming: bool, } -impl SymbolPathBuffer { +impl SymbolPath { fn new(tcx: TyCtxt<'_, '_, '_>) -> Self { - let mut result = SymbolPathBuffer { + let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), strict_naming: tcx.has_strict_asm_symbol_naming(), @@ -360,7 +358,7 @@ impl SymbolPathBuffer { } fn from_interned(symbol: ty::SymbolName, tcx: TyCtxt<'_, '_, '_>) -> Self { - let mut result = SymbolPathBuffer { + let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), strict_naming: tcx.has_strict_asm_symbol_naming(), @@ -375,19 +373,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, self.strict_naming); @@ -401,6 +386,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 387cacf76bdee1af073f53948af382ca78d046e6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Dec 2018 12:59:08 +0200 Subject: [PATCH 17/70] rustc: remove ty::item_path::RootMode by moving local logic into the printer. --- src/librustc/ty/item_path.rs | 565 +++++++++------------ src/librustc/ty/print.rs | 26 +- src/librustc_codegen_utils/symbol_names.rs | 27 +- src/librustdoc/clean/mod.rs | 33 +- 4 files changed, 284 insertions(+), 367 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 1eb3952032a..6f8d0d19103 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -2,11 +2,11 @@ use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; +use ty::print::PrintCx; 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,246 +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) + debug!("absolute_item_path_str: def_id={:?}", def_id); + let mut cx = PrintCx::new(self); + AbsolutePathPrinter::print_item_path(&mut cx, 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 +impl PrintCx<'a, 'gcx, 'tcx> { + pub fn default_print_item_path

(&mut self, def_id: DefId) -> P::Path + where P: ItemPathPrinter { - 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?; - } - } - - pub fn print_item_path

( - self, - printer: &mut P, - def_id: DefId, - ) -> P::Path - where P: ItemPathPrinter + Debug - { - 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. @@ -342,27 +120,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. @@ -373,7 +147,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. @@ -381,27 +155,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)); } } @@ -410,7 +184,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(self, &format!("<{} as {}>", self_ty, trait_ref)); } // Inherent impls. Try to print `Foo::bar` for an inherent @@ -420,13 +194,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(self, &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 | @@ -434,33 +208,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, &self_ty.to_string()) } _ => { - printer.path_impl(&format!("<{}>", self_ty)) + P::path_impl(self, &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 hir_id = self.hir().as_local_hir_id(impl_def_id).unwrap(); - let item = self.hir().expect_item_by_hir_id(hir_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 hir_id = self.tcx.hir().as_local_hir_id(impl_def_id).unwrap(); + let item = self.tcx.hir().expect_item_by_hir_id(hir_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 `DefId` of `def_id`'s parent in the def tree. If /// this returns `None`, then `def_id` represents a crate root or /// inlined root. @@ -519,58 +292,202 @@ 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 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(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, -} - -#[derive(Debug)] -struct LocalPathPrinter { - root_mode: RootMode, -} - -impl LocalPathPrinter { - fn new(root_mode: RootMode) -> LocalPathPrinter { - LocalPathPrinter { - root_mode, - } + fn print_item_path(cx: &mut PrintCx<'_, '_, '_>, def_id: DefId) -> Self::Path { + cx.default_print_item_path::(def_id) } + + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path; + fn path_impl(cx: &mut PrintCx<'_, '_, '_>, text: &str) -> Self::Path; + fn path_append(path: Self::Path, text: &str) -> Self::Path; } -impl ItemPathPrinter for LocalPathPrinter { +struct AbsolutePathPrinter; + +impl ItemPathPrinter for AbsolutePathPrinter { type Path = String; - fn root_mode(&self) -> RootMode { - self.root_mode + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + cx.tcx.original_crate_name(cnum).to_string() } - - fn path_crate(&self, name: Option<&str>) -> Self::Path { - name.unwrap_or("").to_string() - } - fn path_impl(&self, text: &str) -> Self::Path { + fn path_impl(_cx: &mut PrintCx<'_, '_, '_>, 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("::"); + } + 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_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 Some(visible_parent) != actual_parent => { + cx.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()) + } + _ => { + 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 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(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(_cx: &mut PrintCx<'_, '_, '_>, 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("::"); } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index a9fffa2ee87..81101740a4c 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 13f8e13c328..56ef15b12a0 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::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -224,7 +225,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::new(tcx), def_id).into_interned() + let mut cx = PrintCx::new(tcx); + SymbolPathPrinter::print_item_path(&mut cx, def_id).into_interned() }) } @@ -394,29 +396,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 { - let mut path = SymbolPath::new(); - if let Some(name) = name { - path.push(name); - } + fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + let mut path = SymbolPath::new(cx.tcx); + path.push(&cx.tcx.original_crate_name(cnum).as_str()); path } - fn path_impl(&self, text: &str) -> Self::Path { - let mut path = SymbolPath::new(); + fn path_impl(cx: &mut PrintCx<'_, '_, '_>, text: &str) -> Self::Path { + let mut path = SymbolPath::new(cx.tcx); 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 af40e417d61..ed7f1bbe7e6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4225,30 +4225,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 path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { + vec![cx.tcx.original_crate_name(cnum).to_string()] } - - fn push(&mut self, text: &str) { - self.names.push(text.to_owned()); + fn path_impl(_: &mut PrintCx<'_, '_, '_>, 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), hir_id: None, def: None, From 329b8ca8180ef8aa7314bd0bff9d9cd61f8dad40 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Dec 2018 17:36:24 +0200 Subject: [PATCH 18/70] 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 | 129 ++++++++---------- 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, 70 insertions(+), 80 deletions(-) diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index a2924cb993f..69d5492c0f4 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 a19eb1d9545..43ab32237de 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -55,6 +55,7 @@ CloneTypeFoldableAndLiftImpls! { crate::ty::IntVarValue, crate::ty::ParamConst, crate::ty::ParamTy, + crate::ty::RegionVid, crate::ty::UniverseIndex, crate::ty::Variance, ::syntax_pos::Span, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 6667d378733..2a03f32fdcc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -120,17 +120,6 @@ impl RegionHighlightMode { Self::highlighting_region(&ty::ReVar(vid), number, op) } - /// Returns `true` if any placeholders are highlighted, and `false` otherwise. - 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 { Self::get() @@ -163,17 +152,6 @@ impl RegionHighlightMode { ) } - /// Returns `true` if any placeholders are highlighted, and `false` otherwise. - 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)) @@ -421,7 +399,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 @@ -720,19 +698,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 { @@ -757,12 +736,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) } } } @@ -785,7 +762,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, .. }) => { @@ -812,14 +793,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(()), @@ -938,15 +916,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); + } - write!(f, "'_#{}r", self.index()) + 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()) + } } } @@ -954,16 +947,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 { @@ -1061,12 +1053,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) } @@ -1112,7 +1101,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 f185f49b9b9..e3909e0c125 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 8e407070342..46de13dbbbd 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 067bd08220d..7eb4d96fc5f 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) | ^^^^^^^^^^^^^^^^^ 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 5cf37bedb88..f8b6bfa003b 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 671a8b9a935..7e7429405fa 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 732b71a1ba4de6a3ecaae5fe1c4e916a7dae33a0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Dec 2018 09:47:45 +0200 Subject: [PATCH 19/70] 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 81101740a4c..7085a3beb1c 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 2a03f32fdcc..a0feeae0a0c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -396,20 +396,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) => { @@ -727,6 +722,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 { @@ -744,6 +765,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 { @@ -851,6 +890,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 { @@ -943,6 +1025,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 { @@ -1053,9 +1153,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) } @@ -1101,17 +1200,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, subst::InternalSubsts::empty(), iter::empty()) From 08d27441ecc96a56e1b0e72c0accbced2ce6a7d3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 10 Dec 2018 16:10:22 +0200 Subject: [PATCH 20/70] 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 | 662 ++++++++++----------- src/librustc_codegen_utils/lib.rs | 1 + src/librustc_codegen_utils/symbol_names.rs | 19 +- src/librustdoc/clean/mod.rs | 15 +- src/librustdoc/lib.rs | 1 + 9 files changed, 448 insertions(+), 429 deletions(-) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 681dffc0116..53f39d3ac8a 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -31,6 +31,7 @@ #![deny(rust_2018_idioms)] #![allow(explicit_outlives_requirements)] +#![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 bff07de5bcf..7d2050a7c68 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2369,7 +2369,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 { @@ -2380,7 +2380,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 6f8d0d19103..0612401ca25 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. @@ -121,20 +117,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(); @@ -147,7 +141,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. @@ -171,11 +165,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)); } } @@ -184,7 +178,7 @@ impl PrintCx<'a, 'gcx, 'tcx> { if let Some(trait_ref) = impl_trait_ref { // Trait impls. - return P::path_impl(self, &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 @@ -194,13 +188,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(self, &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 | @@ -208,28 +202,26 @@ impl PrintCx<'a, 'gcx, 'tcx> { ty::Uint(_) | ty::Float(_) | ty::Str => { - P::path_impl(self, &self_ty.to_string()) + self.path_impl(&self_ty.to_string()) } _ => { - P::path_impl(self, &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 hir_id = self.tcx.hir().as_local_hir_id(impl_def_id).unwrap(); let item = self.tcx.hir().expect_item_by_hir_id(hir_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)) } } @@ -296,13 +288,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(cx: &mut PrintCx<'_, '_, '_>, 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; @@ -310,13 +306,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(_cx: &mut PrintCx<'_, '_, '_>, 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("::"); } @@ -332,7 +332,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); @@ -343,7 +343,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 @@ -356,7 +356,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, @@ -365,14 +365,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)); } _ => {}, } @@ -382,9 +382,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 . @@ -394,12 +394,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!( @@ -441,7 +441,7 @@ impl LocalPathPrinter { // have access to the re-exported name. DefPathData::Module(actual_name) | DefPathData::TypeNs(actual_name) if Some(visible_parent) != actual_parent => { - cx.tcx.item_children(visible_parent) + self.tcx.item_children(visible_parent) .iter() .find(|child| child.def.def_id() == def_id) .map(|child| child.ident.as_str()) @@ -451,7 +451,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() } @@ -459,21 +459,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(); @@ -481,13 +481,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(_cx: &mut PrintCx<'_, '_, '_>, 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 7085a3beb1c..a1d93bc4140 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 a0feeae0a0c..780ff8a61e4 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -9,7 +9,7 @@ use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use crate::ty::{self, ParamConst, Ty, TypeFoldable}; -use crate::ty::print::{PrintCx, Print}; +use crate::ty::print::{FmtPrinter, PrintCx, Print}; use crate::mir::interpret::ConstValue; use std::cell::Cell; @@ -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>], - c_variadic: bool, - output: Ty<'tcx>) - -> fmt::Result { - write!(f, "(")?; +impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { + fn fn_sig( + &mut self, + inputs: &[Ty<'tcx>], + c_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 c_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: SubstsRef<'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)) } }; @@ -395,42 +388,42 @@ 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)?; } UnpackedKind::Const(ct) => { - start_or_continue(f, start, ", ")?; - ct.print_display(f, self)?; + start_or_continue(self, start, ", ")?; + ct.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 { @@ -450,22 +443,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(_) | @@ -478,18 +471,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 @@ -504,20 +497,21 @@ impl PrintCx<'a, 'gcx, 'tcx> { } pub fn parameterized(f: &mut F, did: DefId, substs: SubstsRef<'_>) -> 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; @@ -530,8 +524,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; } } @@ -542,7 +536,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(), @@ -567,11 +560,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(()) @@ -596,16 +589,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))) }) } } @@ -620,12 +613,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_by_hir_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_by_hir_id(self.var_path.hir_id), + self.closure_expr_id)) + }) } } @@ -637,25 +630,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)) } @@ -663,46 +656,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)); } } @@ -710,13 +703,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")), }; } } @@ -726,7 +719,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; } @@ -749,18 +742,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)) } } } @@ -769,7 +762,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; } @@ -784,15 +777,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 @@ -802,89 +795,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")) } } } @@ -897,7 +889,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; } @@ -934,17 +926,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", @@ -955,21 +947,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.c_variadic, self.output()) + print!(cx, write("fn"))?; + cx.fn_sig(self.inputs(), self.c_variadic, self.output()) } debug { - write!(f, "({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output()) + print!(cx, write("({:?}; c_variadic: {})->{:?}", + self.inputs(), self.c_variadic, self.output())) } } } @@ -999,15 +992,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(()) @@ -1017,10 +1010,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())) } } } @@ -1029,7 +1022,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; } @@ -1097,16 +998,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(()) } } } @@ -1152,7 +1054,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) => { @@ -1175,7 +1082,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); @@ -1190,12 +1103,13 @@ define_print! { Ok(()) } Foreign(def_id) => { - cx.parameterized( + let _ = cx.print_def_path( def_id, - subst::InternalSubsts::empty(), + None, Namespace::TypeNS, iter::empty(), - ) + )?; + Ok(()) } Projection(ref data) => data.print(cx), UnnormalizedProjection(ref data) => { @@ -1215,7 +1129,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))?; @@ -1477,7 +1391,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(()) } } } @@ -1505,16 +1425,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/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index b417091704d..4c7b00ae078 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::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -106,8 +106,9 @@ use syntax_pos::symbol::Symbol; use log::debug; -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 { @@ -225,9 +226,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(tcx)); + let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); + cx.printer.into_interned() }) } @@ -323,7 +324,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), tcx); if instance.is_vtable_shim() { - buf.push("{{vtable-shim}}"); + let _ = buf.write_str("{{vtable-shim}}"); } buf.finish(hash) @@ -347,6 +348,12 @@ struct SymbolPath { result: String, temp_buf: String, strict_naming: bool, + + // 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 { @@ -355,6 +362,7 @@ impl SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), strict_naming: tcx.has_strict_asm_symbol_naming(), + keep_within_component: false, }; result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested result @@ -365,109 +373,139 @@ impl SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), strict_naming: tcx.has_strict_asm_symbol_naming(), + 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, self.strict_naming); - 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 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(self.tcx); - 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(self.tcx); - 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: SubstsRef<'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 } } -// 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, ., _, $ -// NVPTX assembly has more strict naming rules than gas, so additionally, dots -// are replaced with '$' there. -// -// returns true if an underscore must be added at the start -fn sanitize(result: &mut String, s: &str, strict_naming: bool) -> bool { - for c in s.chars() { - match c { - // Escape these with $ sequences - '@' => result.push_str("$SP$"), - '*' => result.push_str("$BP$"), - '&' => result.push_str("$RF$"), - '<' => result.push_str("$LT$"), - '>' => result.push_str("$GT$"), - '(' => result.push_str("$LP$"), - ')' => result.push_str("$RP$"), - ',' => result.push_str("$C$"), +impl PrettyPrinter for SymbolPath {} - '-' | ':' | '.' if strict_naming => { - // NVPTX doesn't support these characters in symbol names. - result.push('$') +impl fmt::Write for SymbolPath { + fn write_str(&mut self, s: &str) -> fmt::Result { + // 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, ., _, $ + // NVPTX assembly has more strict naming rules than gas, so additionally, dots + // are replaced with '$' there. + + for c in s.chars() { + if self.temp_buf.is_empty() { + match c { + 'a'..='z' | 'A'..='Z' | '_' => {} + _ => { + // Underscore-qualify anything that didn't start as an ident. + self.temp_buf.push('_'); + } + } } + match c { + // Escape these with $ sequences + '@' => self.temp_buf.push_str("$SP$"), + '*' => self.temp_buf.push_str("$BP$"), + '&' => self.temp_buf.push_str("$RF$"), + '<' => self.temp_buf.push_str("$LT$"), + '>' => self.temp_buf.push_str("$GT$"), + '(' => self.temp_buf.push_str("$LP$"), + ')' => self.temp_buf.push_str("$RP$"), + ',' => self.temp_buf.push_str("$C$"), - // '.' doesn't occur in types and functions, so reuse it - // for ':' and '-' - '-' | ':' => result.push('.'), + '-' | ':' | '.' if self.strict_naming => { + // NVPTX doesn't support these characters in symbol names. + self.temp_buf.push('$') + } - // These are legal symbols - 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => result.push(c), + // '.' doesn't occur in types and functions, so reuse it + // for ':' and '-' + '-' | ':' => self.temp_buf.push('.'), - _ => { - result.push('$'); - for c in c.escape_unicode().skip(1) { - match c { - '{' => {} - '}' => result.push('$'), - c => result.push(c), + // These are legal symbols + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.temp_buf.push(c), + + _ => { + self.temp_buf.push('$'); + for c in c.escape_unicode().skip(1) { + match c { + '{' => {} + '}' => self.temp_buf.push('$'), + c => self.temp_buf.push(c), + } } } } } - } - // 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() + Ok(()) + } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6cf8a9896d5..f629447fc64 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; @@ -4235,6 +4235,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()] } @@ -4246,10 +4258,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: SubstsRef<'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 58ba827ee05..2ac44d0109f 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(test)] diff --git a/src/test/ui/symbol-names/impl1.rs b/src/test/ui/symbol-names/impl1.rs index 992527017fb..c712137e828 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 d225c53e492..eda8646b5b4 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN15impl1..foo..Foo3bar17hc487d6ec13fe9124E) +error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) --> $DIR/impl1.rs:8:9 | LL | #[rustc_symbol_name] From aec5a484812e2e6d0077a960997f1f51f18c1c8a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 21 Dec 2018 17:31:33 +0200 Subject: [PATCH 30/70] 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 45762460f2d..77fed9cf1d1 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, @@ -291,7 +290,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()) } @@ -367,35 +366,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) } } @@ -587,7 +558,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 { @@ -781,12 +775,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 2c38c437cf6..3c34d254099 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1007,7 +1007,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 4c7b00ae078..0ea141b6574 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -416,16 +416,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 f629447fc64..4cc18125e04 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4239,6 +4239,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 { @@ -4247,9 +4248,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 39fd54a418b08051623505ff5263fe8714f40b4c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 21 Dec 2018 20:08:01 +0200 Subject: [PATCH 31/70] 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 77fed9cf1d1..e0a5a2fcf84 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>, 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] @@ -273,7 +275,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) } _ => { @@ -323,30 +334,24 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { fn default_print_impl_path( &mut self, impl_def_id: DefId, - substs: Option>, + _substs: Option>, 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), @@ -702,7 +707,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` @@ -720,35 +725,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>, - 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 df6650f38cb2bed40fb1b1fe5d6a6e08dab963e2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 06:09:22 +0200 Subject: [PATCH 32/70] 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 e0a5a2fcf84..77768975e25 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, @@ -301,7 +302,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()) } @@ -357,21 +358,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) } } @@ -561,10 +559,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 @@ -774,11 +786,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 3c34d254099..6384a2af8ef 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1007,7 +1007,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 0ea141b6574..c4de355aa44 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -387,7 +387,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(); } @@ -414,6 +414,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, @@ -423,25 +424,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 4cc18125e04..bfc7c7859f5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4237,16 +4237,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 66cc029dd78ba5df23998a1966c7f9222e5c9c1c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 07:00:30 +0200 Subject: [PATCH 33/70] 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 c99ab215b35..04f0710436b 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -58,7 +58,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::error::TypeError; use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TyKind, TypeFoldable}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; -use std::{cmp, fmt}; +use std::{cmp, fmt, iter}; use syntax_pos::{Pos, Span}; mod note; @@ -444,20 +444,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 77768975e25..dca9ddc4a5b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -722,9 +722,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; @@ -742,8 +742,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()); @@ -766,10 +764,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 36f64f15fc0c530493206342d5e4c80f7643fc1d Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 07:27:44 +0200 Subject: [PATCH 34/70] rustc: remove `ty::print::FORCE_ABSOLUTE` altogether. --- src/librustc/infer/error_reporting/mod.rs | 4 +-- src/librustc/ty/print.rs | 39 +--------------------- src/librustc_codegen_utils/symbol_names.rs | 8 ++--- 3 files changed, 6 insertions(+), 45 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 04f0710436b..c27281911aa 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::Namespace; use hir::def_id::CrateNum; use ty::print::{PrintCx, Printer}; - use ty::subst::Substs; + use ty::subst::SubstsRef; struct AbsolutePathPrinter; @@ -481,7 +481,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self: &mut PrintCx<'_, '_, 'tcx, Self>, path: Self::Path, _params: &[ty::GenericParamDef], - _substs: &'tcx Substs<'tcx>, + _substs: SubstsRef<'tcx>, _ns: Namespace, _projections: impl Iterator>, ) -> Self::Path { diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index dca9ddc4a5b..0fda55423aa 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, @@ -223,24 +208,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } /// Returns a string identifying this `DefId`. 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>, - 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 `DefId`. 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); @@ -722,8 +690,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) { @@ -763,9 +729,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 c4de355aa44..8f31e91fa79 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -225,11 +225,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(tcx)); - let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); - cx.printer.into_interned() - }) + let mut cx = PrintCx::new(tcx, SymbolPath::new(tcx)); + 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 27ddf2cec8126fbf1a272cee6ce6cb1c18b97e2a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 28 Dec 2018 10:08:30 +0200 Subject: [PATCH 35/70] rustc: replace node_path_str with uses of def_path_str. --- src/librustc/hir/map/mod.rs | 3 ++- src/librustc/ty/print.rs | 7 ------- 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(+), 23 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 747e65ff4b5..600e7e21e99 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1351,7 +1351,8 @@ fn node_id_to_string(map: &Map<'_>, id: NodeId, include_id: bool) -> String { // the user-friendly path, otherwise fall back to stringifying DefPath. crate::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 0fda55423aa..e9cd09aa539 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -4,7 +4,6 @@ use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; -use syntax::ast; use syntax::symbol::{keywords, Symbol}; use rustc_data_structures::fx::FxHashSet; @@ -217,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 3182b2ce30c..dde88a21240 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -471,7 +471,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 8e68a13e1e1..3fea515ae40 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -429,7 +429,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); @@ -470,7 +471,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, @@ -682,7 +684,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)); @@ -1093,7 +1096,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); @@ -1300,7 +1304,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); @@ -1389,7 +1394,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); @@ -1418,7 +1424,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 97b9db34ed5..7ad5b7ce8c7 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -134,7 +134,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); @@ -184,7 +185,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, @@ -202,7 +204,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); @@ -225,7 +228,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); @@ -247,7 +251,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); @@ -274,7 +279,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() @@ -358,7 +364,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 387ea61ec146722daa9fcf5f2658ea5ee2211f0c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jan 2019 12:13:39 +0200 Subject: [PATCH 36/70] 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 6384a2af8ef..a381f8f4e8a 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 972af5e808eb76b449e7af6ee087bb611c722326 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jan 2019 13:05:05 +0200 Subject: [PATCH 37/70] rustc: rename ppaux' print macro to just p and make its cx input implicit. --- src/librustc/util/ppaux.rs | 366 +++++++++++++++++++------------------ 1 file changed, 193 insertions(+), 173 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a381f8f4e8a..fa0acd1a301 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> { c_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 c_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; @@ -502,7 +521,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_by_hir_id(self.var_path.hir_id), self.closure_expr_id)) @@ -520,15 +540,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("}}")) } } } @@ -536,7 +556,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)) } @@ -562,7 +582,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)) } } } @@ -576,14 +596,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)); } } @@ -591,13 +611,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")), }; } } @@ -638,10 +658,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)) } } } @@ -673,7 +693,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 @@ -683,29 +703,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() @@ -713,58 +733,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")) } } } @@ -817,7 +837,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)) } } } @@ -839,18 +859,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.c_variadic, self.output()) } debug { - print!(cx, write("({:?}; c_variadic: {})->{:?}", + p!(write("({:?}; c_variadic: {})->{:?}", self.inputs(), self.c_variadic, self.output())) } } @@ -889,7 +909,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(()) @@ -899,10 +919,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())) } } } @@ -932,22 +952,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)) } } } @@ -1020,68 +1040,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) => { @@ -1096,12 +1116,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(()) } @@ -1116,30 +1136,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(()); } @@ -1149,7 +1169,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. @@ -1158,36 +1178,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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { - print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; + p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; let mut sep = " "; cx.tcx.with_freevars(hir_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - print!(cx, + p!( write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), @@ -1199,36 +1219,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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { if cx.tcx.sess.opts.debugging_opts.span_free_formats { - print!(cx, write("@{:?}", hir_id))?; + p!(write("@{:?}", hir_id))?; } else { - print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; + p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; } let mut sep = " "; cx.tcx.with_freevars(hir_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { - print!(cx, + p!( write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), @@ -1240,10 +1260,10 @@ 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 = ", "; @@ -1251,34 +1271,34 @@ define_print! { } if cx.is_verbose { - print!(cx, write( + p!(write( " closure_kind_ty={:?} closure_sig_ty={:?}", substs.closure_kind_ty(did, cx.tcx), substs.closure_sig_ty(did, cx.tcx) ))?; } - 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) => { match c.val { - ConstValue::Infer(..) => print!(cx, write("_"))?, + ConstValue::Infer(..) => p!(write("_"))?, ConstValue::Param(ParamConst { name, .. }) => - print!(cx, write("{}", name))?, - _ => print!(cx, write("{}", c.unwrap_usize(cx.tcx)))?, + p!(write("{}", name))?, + _ => 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("]")) } } } @@ -1292,9 +1312,9 @@ define_print! { ('tcx) ConstValue<'tcx>, (self, cx) { display { match self { - ConstValue::Infer(..) => print!(cx, write("_")), - ConstValue::Param(ParamConst { name, .. }) => print!(cx, write("{}", name)), - _ => print!(cx, write("{:?}", self)), + ConstValue::Infer(..) => p!(write("_")), + ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)), + _ => p!(write("{:?}", self)), } } } @@ -1303,7 +1323,7 @@ define_print! { define_print! { ('tcx) ty::Const<'tcx>, (self, cx) { display { - print!(cx, write("{} : {}", self.val, self.ty)) + p!(write("{} : {}", self.val, self.ty)) } } } @@ -1313,8 +1333,8 @@ define_print! { display { match self { // FIXME(const_generics) this should print at least the type. - ty::LazyConst::Unevaluated(..) => print!(cx, write("_ : _")), - ty::LazyConst::Evaluated(c) => print!(cx, write("{}", c)), + ty::LazyConst::Unevaluated(..) => p!(write("_ : _")), + ty::LazyConst::Evaluated(c) => p!(write("{}", c)), } } } @@ -1323,10 +1343,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)) } } } @@ -1334,10 +1354,10 @@ define_print! { define_print! { () ty::ParamConst, (self, cx) { display { - print!(cx, write("{}", self.name)) + p!(write("{}", self.name)) } debug { - print!(cx, write("{}/#{}", self.name, self.index)) + p!(write("{}/#{}", self.name, self.index)) } } } @@ -1350,7 +1370,7 @@ define_print_multi! { ] (self, cx) { display { - print!(cx, print(self.0), write(" : "), print(self.1)) + p!(print(self.0), write(" : "), print(self.1)) } } } @@ -1358,7 +1378,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)) } } } @@ -1366,11 +1386,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)) } } } @@ -1378,7 +1398,7 @@ define_print! { define_print! { ('tcx) ty::ProjectionPredicate<'tcx>, (self, cx) { debug { - print!(cx, + p!( write("ProjectionPredicate("), print(self.projection_ty), write(", "), @@ -1386,7 +1406,7 @@ define_print! { write(")")) } display { - print!(cx, print(self.projection_ty), write(" == "), print(self.ty)) + p!(print(self.projection_ty), write(" == "), print(self.ty)) } } } @@ -1409,9 +1429,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")), } } } @@ -1426,36 +1446,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")) } } } @@ -1468,14 +1488,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)) } } } @@ -1486,16 +1506,16 @@ 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::Const(ct) => print!(cx, print(ct)), + UnpackedKind::Lifetime(lt) => p!(print(lt)), + UnpackedKind::Type(ty) => p!(print(ty)), + UnpackedKind::Const(ct) => p!(print(ct)), } } debug { match self.unpack() { - UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), - UnpackedKind::Type(ty) => print!(cx, print(ty)), - UnpackedKind::Const(ct) => print!(cx, print(ct)), + UnpackedKind::Lifetime(lt) => p!(print(lt)), + UnpackedKind::Type(ty) => p!(print(ty)), + UnpackedKind::Const(ct) => p!(print(ct)), } } } From 5616ca857dd05e5e62b4bfcd11bd1ea0f2e22f5e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 9 Jan 2019 16:30:10 +0200 Subject: [PATCH 38/70] 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 c27281911aa..b777b0dc9f3 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -454,9 +454,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>( @@ -465,15 +470,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) } @@ -484,8 +488,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _substs: SubstsRef<'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 e9cd09aa539..f179619b5f8 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -109,16 +109,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); @@ -128,19 +132,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>, 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, @@ -148,27 +152,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, @@ -176,7 +179,7 @@ pub trait Printer: Sized { substs: SubstsRef<'tcx>, ns: Namespace, projections: impl Iterator>, - ) -> Self::Path; + ) -> Result; } #[must_use] @@ -185,7 +188,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>, 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; @@ -515,7 +524,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( @@ -524,7 +533,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. @@ -582,9 +591,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { substs: SubstsRef<'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 { @@ -671,7 +678,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>, @@ -679,20 +688,20 @@ impl Printer for FmtPrinter { substs: Option>, 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); } } @@ -712,7 +721,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)); } @@ -721,7 +730,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. @@ -742,16 +754,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() { @@ -771,7 +781,7 @@ impl Printer for FmtPrinter { substs: SubstsRef<'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 fa0acd1a301..d0d51e7f38c 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 8f31e91fa79..c73c5950c0d 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -404,9 +404,14 @@ impl SymbolPath { // symbol names should have their own printing machinery. 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 }) } @@ -416,7 +421,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 { @@ -432,14 +437,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); @@ -448,11 +456,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 { @@ -475,7 +481,7 @@ impl Printer for SymbolPath { substs: SubstsRef<'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 bfc7c7859f5..2a8db6455bf 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4230,10 +4230,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>, @@ -4241,7 +4246,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: @@ -4251,15 +4256,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>, @@ -4268,13 +4273,14 @@ where F: Fn(DefId) -> Def { _substs: SubstsRef<'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 2ac44d0109f..fccf5a67ad4 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -18,6 +18,7 @@ #![feature(const_fn)] #![feature(drain_filter)] #![feature(inner_deref)] +#![feature(never_type)] #![recursion_limit="256"] From 37e918526a7107bc3c8de48f9a535b0100da40f5 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 10 Jan 2019 13:26:35 +0200 Subject: [PATCH 39/70] 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 b777b0dc9f3..68b2d201fb0 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -498,8 +498,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 ea3668cec15..7ee8eec11ee 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2369,8 +2369,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 f179619b5f8..d385d183e2b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -60,9 +60,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, @@ -71,6 +69,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> { @@ -80,30 +97,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; } } @@ -116,17 +132,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 } } @@ -613,7 +630,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 d0d51e7f38c..90300ecde2e 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: SubstsRef<'_>, 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( @@ -486,7 +487,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, @@ -500,7 +501,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, @@ -522,7 +523,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, @@ -592,7 +593,7 @@ define_print! { define_print! { () ty::BoundRegion, (self, cx) { display { - if cx.is_verbose { + if cx.config.is_verbose { return self.print_debug(cx); } @@ -630,7 +631,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; } @@ -654,7 +655,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); } @@ -673,7 +674,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; } @@ -689,7 +690,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); } @@ -717,7 +718,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())), @@ -734,7 +735,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) => { @@ -801,7 +802,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; } @@ -822,7 +823,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), @@ -905,7 +906,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); } @@ -934,7 +935,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; } @@ -950,7 +951,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 { @@ -997,7 +998,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"))) } }*/ @@ -1146,7 +1147,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 c73c5950c0d..8f4b1d1638a 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -225,9 +225,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(tcx)); - let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); - cx.printer.into_interned() + PrintCx::with(tcx, SymbolPath::new(tcx), |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 2a8db6455bf..ffdf47db547 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4278,9 +4278,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 ab5d6fb302f0b74e825c6e3e829a9e5ce880b7d0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 10 Jan 2019 14:50:36 +0200 Subject: [PATCH 40/70] rustc: remove the closure from ppaux's p! macro (by making ? implicit). --- src/librustc/ty/print.rs | 8 +- src/librustc/util/ppaux.rs | 248 ++++++++++++++++++------------------- 2 files changed, 122 insertions(+), 134 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index d385d183e2b..005dd18177d 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -611,12 +611,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 90300ecde2e..55e0544d2bb 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 c_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(()) } } } @@ -528,7 +527,8 @@ impl fmt::Debug for ty::UpvarId { p!(write("UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, cx.tcx.hir().name_by_hir_id(self.var_path.hir_id), - self.closure_expr_id)) + self.closure_expr_id)); + Ok(()) }) } } @@ -543,12 +543,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("}}")) @@ -571,13 +571,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)) } } } @@ -599,21 +598,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) => { @@ -621,7 +619,7 @@ define_print! { did.krate, did.index, name)) } BrEnv => p!(write("BrEnv")), - }; + } } } } @@ -661,10 +659,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)) } } } @@ -696,7 +694,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 @@ -707,8 +706,6 @@ define_print! { ty::ReEarlyBound(ref data) => { if data.name != "'_" { p!(write("{}", data.name)) - } else { - Ok(()) } } ty::ReLateBound(_, br) | @@ -742,7 +739,7 @@ define_print! { p!(print_display(region_vid)) } ty::ReScope(_) | - ty::ReErased => Ok(()), + ty::ReErased => {} ty::ReStatic => p!(write("'static")), ty::ReEmpty => p!(write("'")), @@ -853,7 +850,7 @@ define_print! { ty::Contravariant => "-", ty::Invariant => "o", ty::Bivariant => "*", - }) + })? } } } @@ -862,15 +859,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.c_variadic, self.output()) + p!(write("fn")); + cx.fn_sig(self.inputs(), self.c_variadic, self.output())? } debug { p!(write("({:?}; c_variadic: {})->{:?}", @@ -912,20 +909,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())) } } } @@ -1016,7 +1011,7 @@ define_print_multi! { ] (self, cx) { display { - cx.in_binder(self) + cx.in_binder(self)? } } } @@ -1030,11 +1025,9 @@ define_print! { Namespace::TypeNS, iter::empty(), )?; - Ok(()) } debug { let _ = cx.path_qualified(None, self.self_ty(), Some(*self), Namespace::TypeNS)?; - Ok(()) } } } @@ -1052,26 +1045,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)); } } } @@ -1079,7 +1072,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), @@ -1089,7 +1082,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]")), @@ -1114,19 +1107,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( @@ -1135,11 +1125,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(")")) } @@ -1148,21 +1137,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(()); } @@ -1172,7 +1162,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. @@ -1183,30 +1173,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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { - p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; + p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))); let mut sep = " "; cx.tcx.with_freevars(hir_id, |freevars| { for (freevar, upvar_ty) in freevars.iter().zip(upvar_tys) { @@ -1214,7 +1203,7 @@ define_print! { write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty))?; + print(upvar_ty)); sep = ", "; } Ok(()) @@ -1222,12 +1211,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 = ", "; } } @@ -1235,18 +1224,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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { if cx.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", hir_id))?; + p!(write("@{:?}", hir_id)); } else { - p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; + p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))); } let mut sep = " "; cx.tcx.with_freevars(hir_id, |freevars| { @@ -1255,7 +1244,7 @@ define_print! { write("{}{}:", sep, cx.tcx.hir().name(freevar.var_id())), - print(upvar_ty))?; + print(upvar_ty)); sep = ", "; } Ok(()) @@ -1263,38 +1252,38 @@ 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 = ", "; } } - if cx.is_verbose { + if cx.config.is_verbose { p!(write( " closure_kind_ty={:?} closure_sig_ty={:?}", substs.closure_kind_ty(did, cx.tcx), substs.closure_sig_ty(did, cx.tcx) - ))?; + )); } 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) => { match c.val { - ConstValue::Infer(..) => p!(write("_"))?, + ConstValue::Infer(..) => p!(write("_")), ConstValue::Param(ParamConst { name, .. }) => - p!(write("{}", name))?, - _ => p!(write("{}", c.unwrap_usize(cx.tcx)))?, + p!(write("{}", name)), + _ => p!(write("{}", c.unwrap_usize(cx.tcx))), } } } @@ -1306,7 +1295,7 @@ define_print! { } } debug { - self.print_display(cx) + p!(print_display(self)) } } } @@ -1423,7 +1412,6 @@ define_print! { Namespace::TypeNS, iter::empty(), )?; - Ok(()) } } } @@ -1444,14 +1432,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, @@ -1461,7 +1449,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, @@ -1471,7 +1459,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), @@ -1484,12 +1472,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 7c4eecef0b256850166fdb0070568544f2380115 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 10 Jan 2019 13:27:11 +0200 Subject: [PATCH 41/70] 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 | 383 ++++++++++++++------- src/librustc/util/ppaux.rs | 205 ++++++----- src/librustc_codegen_utils/symbol_names.rs | 131 ++++--- src/librustdoc/clean/mod.rs | 54 ++- 6 files changed, 503 insertions(+), 309 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 68b2d201fb0..6b1fea581e6 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -459,37 +459,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: SubstsRef<'tcx>, _ns: Namespace, _projections: impl Iterator>, ) -> Result { - Ok(path) + print_prefix(self) } } @@ -498,7 +513,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 7ee8eec11ee..70ebb7111ef 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2369,7 +2369,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 005dd18177d..986d65b2d9b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -88,7 +88,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; @@ -127,21 +127,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 } @@ -153,7 +161,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>, ns: Namespace, @@ -162,7 +170,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>, ns: Namespace, @@ -173,24 +181,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: SubstsRef<'tcx>, ns: Namespace, @@ -198,13 +218,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>, 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); + 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 = 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)? + // 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, + 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), - _ => { - self.path_append( - path, - &key.disambiguated_data.data.as_interned_str().as_str(), - )? + _ => { + 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>, 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 PrintCx<'a, 'gcx, 'tcx, P> { +impl FmtPrinter { + pub fn new(fmt: F) -> Self { + FmtPrinter { + fmt, + empty: true, + } + } +} + +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); @@ -541,29 +607,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 @@ -578,8 +630,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); } _ => {} @@ -587,28 +638,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(PrettyPath { empty: false }) + + 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(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: SubstsRef<'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 { @@ -652,8 +729,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, @@ -661,12 +738,12 @@ 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)); } UnpackedKind::Const(ct) => { start_or_continue(self, start, ", ")?; @@ -676,20 +753,21 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } 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) } } @@ -697,10 +775,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>, ns: Namespace, @@ -710,15 +788,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); } } @@ -738,9 +821,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), + ); } } @@ -748,7 +833,7 @@ impl Printer for FmtPrinter { } fn path_crate( - self: &mut PrintCx<'_, '_, '_, Self>, + mut self: PrintCx<'_, '_, '_, Self>, cnum: CrateNum, ) -> Result { if cnum == LOCAL_CRATE { @@ -756,51 +841,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)?; + + // 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)?; } - if !path.empty { - write!(self.printer, "::")?; - } - 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: SubstsRef<'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 55e0544d2bb..ff5d9335909 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>], c_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: SubstsRef<'_>, 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(), - )?; + )); } } } @@ -486,8 +504,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, @@ -500,8 +518,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, @@ -522,7 +540,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, @@ -571,9 +589,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)) @@ -599,7 +618,7 @@ define_print! { if let BrNamed(_, name) = *self { if name != "" && name != "'_" { p!(write("{}", name)); - return Ok(()); + return Ok(cx.printer); } } @@ -628,7 +647,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; } @@ -671,7 +690,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; } @@ -695,7 +714,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 @@ -798,7 +817,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; } @@ -867,7 +886,7 @@ define_print! { } p!(write("fn")); - cx.fn_sig(self.inputs(), self.c_variadic, self.output())? + nest!(|cx| cx.fn_sig(self.inputs(), self.c_variadic, self.output())); } debug { p!(write("({:?}; c_variadic: {})->{:?}", @@ -929,7 +948,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; } @@ -1011,7 +1030,7 @@ define_print_multi! { ] (self, cx) { display { - cx.in_binder(self)? + nest!(|cx| cx.in_binder(self)) } } } @@ -1019,15 +1038,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)); } } } @@ -1050,7 +1069,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 })) @@ -1073,12 +1092,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) => { @@ -1101,15 +1120,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("(")); } @@ -1119,18 +1138,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)) @@ -1138,7 +1155,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); @@ -1154,7 +1171,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. @@ -1197,17 +1214,19 @@ define_print! { if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(did) { p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))); let mut sep = " "; - cx.tcx.with_freevars(hir_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. @@ -1224,7 +1243,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); @@ -1238,17 +1257,19 @@ define_print! { p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))); } let mut sep = " "; - cx.tcx.with_freevars(hir_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. @@ -1406,12 +1427,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(), - )?; + )); } } } @@ -1440,32 +1461,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 8f4b1d1638a..2f962733118 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::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -225,9 +225,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(tcx), |mut cx| { - let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()); - cx.printer.into_interned() + PrintCx::with(tcx, SymbolPath::new(tcx), |cx| { + cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()) + .unwrap() + .into_interned() }) } @@ -348,7 +349,7 @@ struct SymbolPath { temp_buf: String, strict_naming: bool, - // 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. @@ -407,18 +408,17 @@ impl 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, @@ -429,64 +429,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 - } - fn path_append( - self: &mut PrintCx<'_, '_, '_, Self>, - mut path: Self::Path, - text: &str, - ) -> Result { - 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)?; + let mut path = self.pretty_path_qualified(self_ty, trait_ref, ns)?; + path.keep_within_component = kept_within_component; Ok(path) } - fn path_generic_args( - self: &mut PrintCx<'_, '_, 'tcx, 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 { + 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<'gcx, 'tcx>( + self: PrintCx<'_, 'gcx, 'tcx, Self>, + print_prefix: impl FnOnce( + PrintCx<'_, 'gcx, 'tcx, Self>, + ) -> Result, + text: &str, + ) -> Result { + 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. + path.write_str("::")?; + } else { + path.finalize_pending_component(); + } + + path.write_str(text)?; + Ok(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: SubstsRef<'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 ffdf47db547..536ee3d58d6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4235,50 +4235,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: SubstsRef<'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 cafd83d1d5f81ac1ed74bf97a950120505009a23 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 11 Jan 2019 13:07:01 +0200 Subject: [PATCH 42/70] rustc: don't keep RegionHighlightMode in a thread-local. --- .../infer/error_reporting/need_type_info.rs | 25 +- .../nice_region_error/placeholder_error.rs | 230 ++++++++++-------- src/librustc/ty/print.rs | 106 ++++++++ src/librustc/util/ppaux.rs | 193 +++------------ .../borrow_check/error_reporting.rs | 72 ++++-- .../error_reporting/region_name.rs | 14 +- 6 files changed, 334 insertions(+), 306 deletions(-) diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index 9e0e48e4741..26deecfdbf0 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 crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::infer::InferCtxt; use crate::infer::type_variable::TypeVariableOrigin; use crate::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 189ecf53e0e..65fcc69a338 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 @@ -5,10 +5,12 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; -use crate::ty; +use crate::ty::{self, TyCtxt}; use crate::ty::error::ExpectedFound; use crate::ty::subst::SubstsRef; -use crate::util::ppaux::RegionHighlightMode; +use crate::ty::print::{Print, RegionHighlightMode, FmtPrinter}; + +use std::fmt::{self, Write}; impl NiceRegionError<'me, 'gcx, 'tcx> { /// When given a `ConcreteFailure` for a function with arguments containing a named region and @@ -309,13 +311,48 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { sup_placeholder: Option>, has_sub: Option, has_sup: Option, - expected_trait_ref: ty::TraitRef<'_>, - actual_trait_ref: ty::TraitRef<'_>, + expected_trait_ref: ty::TraitRef<'tcx>, + actual_trait_ref: ty::TraitRef<'tcx>, vid: Option>, expected_has_vid: Option, actual_has_vid: Option, any_self_ty_has_vid: bool, ) { + // HACK(eddyb) maybe move this in a more central location. + #[derive(Copy, Clone)] + struct Highlighted<'a, 'gcx, 'tcx, T> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + highlight: RegionHighlightMode, + value: T, + } + + impl<'a, 'gcx, 'tcx, T> Highlighted<'a, 'gcx, 'tcx, T> { + fn map(self, f: impl FnOnce(T) -> U) -> Highlighted<'a, 'gcx, 'tcx, U> { + Highlighted { + tcx: self.tcx, + highlight: self.highlight, + value: f(self.value), + } + } + } + + impl<'tcx, T> fmt::Display for Highlighted<'_, '_, 'tcx, T> + where T: for<'a, 'b> Print<'tcx, + FmtPrinter<&'a mut fmt::Formatter<'b>>, + Error = fmt::Error, + >, + { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut printer = ty::print::FmtPrinter::new(f); + printer.region_highlight_mode = self.highlight; + + ty::print::PrintCx::with(self.tcx, printer, |cx| { + self.value.print(cx)?; + Ok(()) + }) + } + } + // The weird thing here with the `maybe_highlighting_region` calls and the // the match inside is meant to be like this: // @@ -331,112 +368,93 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { // None, an then we check again inside the closure, but this // setup sort of minimized the number of calls and so form. - 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)) => { - if any_self_ty_has_vid { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`, \ - for any two lifetimes `'{}` and `'{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - std::cmp::min(n1, n2), - std::cmp::max(n1, n2), - )); - } else { - 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), - )); - } + let highlight_trait_ref = |trait_ref| Highlighted { + tcx: self.tcx(), + highlight: RegionHighlightMode::default(), + value: trait_ref, + }; + + let mut expected_trait_ref = highlight_trait_ref(expected_trait_ref); + expected_trait_ref.highlight.maybe_highlighting_region(sub_placeholder, has_sub); + expected_trait_ref.highlight.maybe_highlighting_region(sup_placeholder, has_sup); + err.note(&{ + let passive_voice = match (has_sub, has_sup) { + (Some(_), _) | (_, Some(_)) => any_self_ty_has_vid, + (None, None) => { + expected_trait_ref.highlight.maybe_highlighting_region(vid, expected_has_vid); + match expected_has_vid { + Some(_) => true, + None => any_self_ty_has_vid, } - (Some(n), _) | (_, Some(n)) => { - if any_self_ty_has_vid { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`, \ - for any lifetime `'{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - n, - )); - } else { - err.note(&format!( - "`{}` must implement `{}`, for any lifetime `'{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - n, - )); - } - } - (None, None) => RegionHighlightMode::maybe_highlighting_region( - vid, - expected_has_vid, - || { - if let Some(n) = expected_has_vid { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`, \ - for some specific lifetime `'{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - n, - )); - } else { - if any_self_ty_has_vid { - err.note(&format!( - "`{}` would have to be implemented for the type `{}`", - expected_trait_ref, - expected_trait_ref.self_ty(), - )); - } else { - err.note(&format!( - "`{}` must implement `{}`", - expected_trait_ref.self_ty(), - expected_trait_ref, - )); - } - } - }, - ), } - }) + }; + + let mut note = if passive_voice { + format!( + "`{}` would have to be implemented for the type `{}`", + expected_trait_ref, + expected_trait_ref.map(|tr| tr.self_ty()), + ) + } else { + format!( + "`{}` must implement `{}`", + expected_trait_ref.map(|tr| tr.self_ty()), + expected_trait_ref, + ) + }; + + 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) => if let Some(n) = expected_has_vid { + let _ = write!(note, + ", for some specific lifetime `'{}`", + n, + ); + }, + } + + note }); - RegionHighlightMode::maybe_highlighting_region( - vid, - actual_has_vid, - || match actual_has_vid { - Some(n) => { - if any_self_ty_has_vid { - err.note(&format!( - "but `{}` is actually implemented for the type `{}`, \ - for some specific lifetime `'{}`", - actual_trait_ref, - actual_trait_ref.self_ty(), - n - )); - } else { - err.note(&format!( - "but `{}` actually implements `{}`, for some specific lifetime `'{}`", - actual_trait_ref.self_ty(), - actual_trait_ref, - n - )); - } - } + let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); + actual_trait_ref.highlight.maybe_highlighting_region(vid, actual_has_vid); + err.note(&{ + let passive_voice = match actual_has_vid { + Some(_) => any_self_ty_has_vid, + None => true, + }; - _ => { - err.note(&format!( - "but `{}` is actually implemented for the type `{}`", - actual_trait_ref, - actual_trait_ref.self_ty(), - )); - } - }, - ); + let mut note = if passive_voice { + format!( + "but `{}` is actually implemented for the type `{}`", + actual_trait_ref, + actual_trait_ref.map(|tr| tr.self_ty()), + ) + } else { + format!( + "but `{}` actually implements `{}`", + actual_trait_ref.map(|tr| tr.self_ty()), + actual_trait_ref, + ) + }; + + if let Some(n) = actual_has_vid { + let _ = write!(note, ", for some specific lifetime `'{}`", n); + } + + note + }); } } diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 986d65b2d9b..28e21b28f7e 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -47,6 +47,102 @@ 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`, invokes + /// `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); + } + } + } + + /// Highlights 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 { @@ -237,6 +333,10 @@ pub trait PrettyPrinter: Printer + fmt::Write { config: self.config, }) } + + fn region_highlight_mode(&self) -> RegionHighlightMode { + RegionHighlightMode::default() + } } macro_rules! nest { @@ -450,6 +550,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 +558,7 @@ impl FmtPrinter { FmtPrinter { fmt, empty: true, + region_highlight_mode: RegionHighlightMode::default(), } } } @@ -920,4 +1022,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 ff5d9335909..d4111e0375f 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -12,7 +12,6 @@ use crate::ty::{self, ParamConst, Ty, TypeFoldable}; use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use crate::mir::interpret::ConstValue; -use std::cell::Cell; use std::fmt::{self, Write as _}; use std::iter; use std::usize; @@ -22,142 +21,6 @@ use syntax::ast::CRATE_NODE_ID; use syntax::symbol::{Symbol, InternedString}; use crate::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 { - /// Reads and returns the current region highlight settings (accesses thread-local state). - 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`, invokes - /// `highlighting_region`; otherwise, just invokes `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`, highlights the region inference - /// variable `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 { @@ -622,7 +485,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)); @@ -647,7 +510,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; } @@ -658,7 +523,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; @@ -676,7 +541,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 { @@ -690,12 +555,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; } @@ -712,8 +579,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); } @@ -780,12 +647,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)) @@ -794,11 +661,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")), @@ -817,12 +684,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; } @@ -926,17 +795,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())); } @@ -948,12 +817,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; } @@ -1165,9 +1036,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 aa3750946d3..9a80415827e 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; @@ -831,7 +831,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, @@ -1875,7 +1875,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); @@ -2099,7 +2099,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_hir_id = self.infcx.tcx.hir().as_local_hir_id(did)?; @@ -2245,7 +2245,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, @@ -2253,10 +2257,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, @@ -2264,10 +2268,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, @@ -2286,7 +2290,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, @@ -2294,7 +2298,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)); } @@ -2314,10 +2318,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`. @@ -2327,28 +2336,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 } /// Returns 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 fdede054e15..362214d3257 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::{SubstsRef, 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; 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={:?}", @@ -680,9 +680,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 fc914aa88a525eb6d78d0331fc59fa2d0a60b3b6 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 16:26:03 +0200 Subject: [PATCH 43/70] rustc: centralize region printing in ty::RegionKind's Print impl. --- src/librustc/infer/error_reporting/mod.rs | 7 +- src/librustc/ty/error.rs | 17 +- src/librustc/ty/print.rs | 5 - src/librustc/util/ppaux.rs | 224 ++++++---------------- 4 files changed, 73 insertions(+), 180 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 6b1fea581e6..974b9c59ea4 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -223,7 +223,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.hir().span_by_hir_id(node), ), _ => ( - format!("the lifetime {} as defined on", fr.bound_region), + format!("the lifetime {} as defined on", region), cm.def_span(self.hir().span_by_hir_id(node)), ), }, @@ -1497,7 +1497,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/error.rs b/src/librustc/ty/error.rs index 342a6204d7f..4a3e814cf47 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -71,6 +71,13 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { } } + let br_string = |br: ty::BoundRegion| { + match br { + ty::BrNamed(_, name) => format!(" {}", name), + _ => String::new(), + } + }; + match *self { CyclicTy(_) => write!(f, "cyclic type of infinite size"), Mismatch => write!(f, "types differ"), @@ -105,15 +112,13 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { } RegionsInsufficientlyPolymorphic(br, _) => { write!(f, - "expected bound lifetime parameter{}{}, found concrete lifetime", - if br.is_named() { " " } else { "" }, - br) + "expected bound lifetime parameter{}, found concrete lifetime", + br_string(br)) } RegionsOverlyPolymorphic(br, _) => { write!(f, - "expected concrete lifetime, found bound lifetime parameter{}{}", - if br.is_named() { " " } else { "" }, - br) + "expected concrete lifetime, found bound lifetime parameter{}", + br_string(br)) } RegionsPlaceholderMismatch => { write!(f, "one type is more general than the other") diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 28e21b28f7e..4e1fdf657bd 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -136,11 +136,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 d4111e0375f..1ac6f3fea4c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -2,7 +2,6 @@ use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::middle::region; use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; -use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use crate::ty::{Bool, Char, Adt}; use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; @@ -471,119 +470,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)); - } +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"), } - 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; - } - } - - false - } -} - -define_print! { - () ty::PlaceholderRegion, (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.placeholder_highlight(*self) { - p!(write("'{}", counter)); - } else { - p!(print_display(self.name)); - } - } - } -} - -// 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) { + 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 @@ -595,11 +509,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 { @@ -619,11 +542,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")), @@ -642,14 +563,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)), @@ -661,11 +579,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")), @@ -687,11 +605,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; } @@ -701,17 +620,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, @@ -788,48 +717,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 88d96b269c77a0de2c143c797aeb61e928f32e03 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 17:55:57 +0200 Subject: [PATCH 44/70] 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 974b9c59ea4..768839bf60f 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -457,6 +457,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 4e1fdf657bd..cf47840b022 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -1,6 +1,7 @@ use crate::hir::def::Namespace; use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::middle::region; use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; @@ -67,7 +68,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 { @@ -114,7 +115,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() @@ -250,6 +251,7 @@ pub trait Printer: Sized { type Error; type Path; + type Region; fn print_def_path( self: PrintCx<'_, '_, 'tcx, Self>, @@ -271,6 +273,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, @@ -310,7 +317,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>( @@ -329,9 +336,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 { @@ -795,10 +819,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, } }); @@ -827,7 +854,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, @@ -873,6 +900,7 @@ impl Printer for FmtPrinter { type Error = fmt::Error; type Path = Self; + type Region = Self; fn print_def_path( mut self: PrintCx<'_, '_, 'tcx, Self>, @@ -929,6 +957,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, @@ -1018,7 +1120,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 1ac6f3fea4c..e14741f55ef 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,6 +1,5 @@ use crate::hir::def::Namespace; use crate::hir::def_id::DefId; -use crate::middle::region; use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::ty::{Bool, Char, Adt}; use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; @@ -487,72 +486,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 { @@ -594,63 +528,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 { @@ -830,7 +707,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 })) @@ -889,7 +766,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 2f962733118..912f8149513 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -409,6 +409,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>, @@ -511,7 +519,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 + } +} impl fmt::Write for SymbolPath { fn write_str(&mut self, s: &str) -> fmt::Result { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 536ee3d58d6..bceae24b1b4 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4233,6 +4233,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 35e5123f5168102eed3b3c8e1d7ab36e6f90d53b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 19:56:46 +0200 Subject: [PATCH 45/70] rustc: support overriding type printing in ty::print::Printer. --- src/librustc/infer/error_reporting/mod.rs | 8 + src/librustc/ty/print.rs | 28 +- src/librustc/util/ppaux.rs | 523 +++++++++++---------- src/librustc_codegen_utils/symbol_names.rs | 8 + src/librustdoc/clean/mod.rs | 8 + 5 files changed, 315 insertions(+), 260 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 768839bf60f..863e10846f4 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -458,6 +458,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Path = Vec; type Region = !; + type Type = !; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -466,6 +467,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 cf47840b022..f2f6f2e30fc 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -252,6 +252,7 @@ pub trait Printer: Sized { type Path; type Region; + type Type; fn print_def_path( self: PrintCx<'_, '_, 'tcx, Self>, @@ -278,6 +279,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, @@ -317,7 +323,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>( @@ -870,8 +884,8 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { nest!(self, |cx| ty.print_display(cx)); } UnpackedKind::Const(ct) => { - start_or_continue(self, start, ", ")?; - ct.print_display(self)?; + start_or_continue(&mut self, start, ", ")?; + nest!(self, |cx| ct.print_display(cx)); } } } @@ -901,6 +915,7 @@ impl Printer for FmtPrinter { type Path = Self; type Region = Self; + type Type = Self; fn print_def_path( mut self: PrintCx<'_, '_, 'tcx, Self>, @@ -1031,6 +1046,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 e14741f55ef..f42865f55ec 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,11 +1,6 @@ use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; -use crate::ty::{Bool, Char, Adt}; -use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; -use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; -use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; -use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use crate::ty::{self, ParamConst, Ty, TypeFoldable}; use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use crate::mir::interpret::ConstValue; @@ -689,269 +684,283 @@ 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 })) - } - Never => p!(write("!")), - Tuple(ref tys) => { - p!(write("(")); - let mut tys = tys.iter(); + 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!(print(ty), write(",")); - if let Some(&ty) = tys.next() { - p!(write(" "), print(ty)); - for &ty in tys { - p!(write(", "), print(ty)); - } + p!(write(" "), print(ty)); + for &ty in tys { + p!(write(", "), print(ty)); } } - p!(write(")")) } - 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("}}")) - } - FnPtr(ref bare_fn) => { - p!(print(bare_fn)) - } - 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)), - } - } - 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(")")); - } - } - 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(")")) - } - Placeholder(placeholder) => { - p!(write("Placeholder({:?})", placeholder)) - } - 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; - } - } - if !is_sized { - p!(write("{}?Sized", if first { " " } else { "+" })); - } else if first { - p!(write(" Sized")); - } - } - 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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { - p!(write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_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 = ", "; - } - } 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("]")) - }, - 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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { - if cx.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", hir_id)); + 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("@{:?}", cx.tcx.hir().span_by_hir_id(hir_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 = ", "; - } - } 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("^{}_{}", debruijn.index(), bound_ty.var.index())) } } - if cx.config.is_verbose { - p!(write( - " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.closure_kind_ty(did, cx.tcx), - substs.closure_sig_ty(did, cx.tcx) - )); - } - - p!(write("]")) - }, - Array(ty, sz) => { - p!(write("["), print(ty), write("; ")); - match sz { - ty::LazyConst::Unevaluated(_def_id, _substs) => { - p!(write("_")); - } - ty::LazyConst::Evaluated(c) => { - match c.val { - ConstValue::Infer(..) => p!(write("_")), - ConstValue::Param(ParamConst { name, .. }) => - p!(write("{}", name)), - _ => p!(write("{}", c.unwrap_usize(cx.tcx))), - } - } - } - p!(write("]")) - } - Slice(ty) => { - p!(write("["), print(ty), write("]")) + ty::BoundTyKind::Param(p) => p!(write("{}", p)), } } + 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("(")); + } + 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); + } + + 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(hir_id) = self.tcx.hir().as_local_hir_id(did) { + p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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(hir_id) = self.tcx.hir().as_local_hir_id(did) { + if self.tcx.sess.opts.debugging_opts.span_free_formats { + p!(write("@{:?}", hir_id)); + } else { + p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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 = ", "; + } + } + + if self.config.is_verbose { + p!(write( + " closure_kind_ty={:?} closure_sig_ty={:?}", + substs.closure_kind_ty(did, self.tcx), + substs.closure_sig_ty(did, self.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) => { + match c.val { + ConstValue::Infer(..) => p!(write("_")), + ConstValue::Param(ParamConst { name, .. }) => + p!(write("{}", name)), + _ => 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 { + 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 912f8149513..f3af2425820 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -410,6 +410,7 @@ impl Printer for SymbolPath { type Path = Self; type Region = Self; + type Type = Self; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -418,6 +419,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 bceae24b1b4..13db78cc803 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4234,6 +4234,7 @@ where F: Fn(DefId) -> Def { type Path = Vec; type Region = (); + type Type = (); fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -4242,6 +4243,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 ab26b26d3471e5a26e38d9100a272b1c9d013112 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 22:07:38 +0200 Subject: [PATCH 46/70] rustc: introduce a ty::print::PrettyPrinter helper for printing "<...>". --- src/librustc/ty/print.rs | 183 +++++++++++++-------- src/librustc_codegen_utils/symbol_names.rs | 68 +++----- 2 files changed, 133 insertions(+), 118 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index f2f6f2e30fc..447f02f42d2 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -336,7 +336,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, @@ -350,6 +350,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( @@ -746,7 +757,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, @@ -772,20 +783,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( @@ -796,17 +806,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( @@ -821,18 +832,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() { @@ -861,45 +860,75 @@ 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; - } - 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)); - } + 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, ", ") } - UnpackedKind::Type(ty) => { - start_or_continue(&mut self, start, ", ")?; - nest!(self, |cx| ty.print_display(cx)); - } - UnpackedKind::Const(ct) => { - start_or_continue(&mut self, start, ", ")?; - nest!(self, |cx| ct.print_display(cx)); + }; + + 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)); + } + UnpackedKind::Const(ct) => { + nest!(cx, |cx| ct.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) + }) } } @@ -1087,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>, @@ -1126,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 f3af2425820..40dc2230966 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -434,28 +434,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>( @@ -466,18 +450,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>, @@ -486,11 +463,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 { @@ -510,20 +485,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) } } @@ -534,6 +496,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) + } } impl fmt::Write for SymbolPath { From 5211e37b1dd6b7fc26d919941e958bce8f5815a0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 14 Jan 2019 23:40:53 +0200 Subject: [PATCH 47/70] 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 | 5 +- .../nice_region_error/placeholder_error.rs | 3 +- 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 863e10846f4..ad24e15b45a 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -444,7 +444,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::SubstsRef; @@ -484,7 +483,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) } @@ -517,7 +515,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) -> Result, _params: &[ty::GenericParamDef], _substs: SubstsRef<'tcx>, - _ns: Namespace, _projections: impl Iterator>, ) -> Result { print_prefix(self) @@ -530,7 +527,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 26deecfdbf0..2fabbbeadbd 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -1,9 +1,10 @@ +use crate::hir::def::Namespace; use crate::hir::{self, Local, Pat, Body, HirId}; use crate::hir::intravisit::{self, Visitor, NestedVisitorMap}; use crate::infer::InferCtxt; use crate::infer::type_variable::TypeVariableOrigin; use crate::ty::{self, Ty, Infer, TyVar}; -use ty::print::Print; +use crate::ty::print::Print; use syntax::source_map::CompilerDesugaringKind; use syntax_pos::Span; use errors::DiagnosticBuilder; @@ -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 65fcc69a338..39ab244dae1 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,4 +1,5 @@ use errors::DiagnosticBuilder; +use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; @@ -343,7 +344,7 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { >, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut printer = ty::print::FmtPrinter::new(f); + let mut printer = ty::print::FmtPrinter::new(f, Namespace::TypeNS); printer.region_highlight_mode = self.highlight; ty::print::PrintCx::with(self.tcx, printer, |cx| { diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 70ebb7111ef..c2cafac2d55 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2369,7 +2369,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 447f02f42d2..a94ae0123d8 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -258,20 +258,18 @@ pub trait Printer: Sized { self: PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, substs: Option>, - 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>, - 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( @@ -292,7 +290,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>( @@ -317,7 +314,6 @@ pub trait Printer: Sized { ) -> Result, params: &[ty::GenericParamDef], substs: SubstsRef<'tcx>, - ns: Namespace, projections: impl Iterator>, ) -> Result; } @@ -350,16 +346,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>, + ) -> 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<'_, '_, '_>`. @@ -414,8 +414,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 } @@ -426,10 +426,9 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self, def_id: DefId, substs: Option>, - 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); @@ -449,7 +448,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) } _ => { @@ -467,12 +466,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>| { @@ -492,7 +491,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) } @@ -504,7 +503,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { self, impl_def_id: DefId, _substs: Option>, - ns: Namespace, self_ty: Ty<'tcx>, impl_trait_ref: Option>, ) -> Result { @@ -531,14 +529,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) } } } @@ -594,14 +592,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(), } } @@ -645,7 +645,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)); @@ -760,20 +760,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); @@ -787,12 +780,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) }) @@ -827,7 +815,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { ) -> Result, params: &[ty::GenericParamDef], substs: SubstsRef<'tcx>, - ns: Namespace, projections: impl Iterator>, ) -> Result { nest!(self, |cx| print_prefix(cx)); @@ -878,11 +865,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>, - 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: SubstsRef<'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>, + ) -> 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 f42865f55ec..204a9574a64 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -17,7 +17,7 @@ use crate::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(()) }) @@ -262,9 +262,9 @@ pub fn parameterized( substs: SubstsRef<'_>, 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(()) }) } @@ -284,12 +284,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; } @@ -303,7 +298,6 @@ define_print! { nest!(|cx| cx.print_def_path( principal.def_id, Some(principal.substs), - Namespace::TypeNS, self.projection_bounds(), )); } @@ -332,12 +326,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())); } } } @@ -360,13 +349,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(()) }) } @@ -374,13 +358,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(()) }) } @@ -396,7 +375,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, @@ -671,15 +650,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))); } } } @@ -730,12 +704,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) => { @@ -758,12 +727,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); @@ -776,12 +740,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) => { @@ -1074,12 +1033,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())); } } } @@ -1108,32 +1062,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 40dc2230966..3c8bd0dd01b 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; @@ -226,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 { PrintCx::with(tcx, SymbolPath::new(tcx), |cx| { - cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty()) + cx.print_def_path(def_id, None, iter::empty()) .unwrap() .into_interned() }) @@ -437,9 +436,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>( @@ -482,10 +480,9 @@ impl Printer for SymbolPath { ) -> Result, params: &[ty::GenericParamDef], substs: SubstsRef<'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 9a80415827e..7a92a507ec1 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -3,6 +3,7 @@ use crate::borrow_check::nll::region_infer::{RegionName, RegionNameSource}; use crate::borrow_check::prefixes::IsPrefixOf; use crate::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::{ @@ -2325,7 +2326,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 @@ -2350,7 +2351,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 13db78cc803..02b8291369d 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::{InternalSubsts, SubstsRef}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; @@ -4260,7 +4260,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 { @@ -4307,7 +4306,6 @@ where F: Fn(DefId) -> Def { ) -> Result, _params: &[ty::GenericParamDef], _substs: SubstsRef<'tcx>, - _ns: Namespace, _projections: impl Iterator>, ) -> Result { print_prefix(self) @@ -4315,7 +4313,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 6d67d6846c9d25b1cffdafd8c330e6374532b5d8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 15 Jan 2019 00:41:14 +0200 Subject: [PATCH 48/70] 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 3c8bd0dd01b..a17a554480e 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -422,7 +422,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( @@ -437,7 +448,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 26f180705a993816dd6e16dd7f19775e4325c709 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 19:18:47 +0200 Subject: [PATCH 49/70] 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 55871aad9a9c621e245c2b238f04f9fab55da759 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 21:33:31 +0200 Subject: [PATCH 50/70] 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 | 1305 +++++++++++++++++++++++++++++++ src/librustc/util/ppaux.rs | 386 +-------- 4 files changed, 1324 insertions(+), 1275 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 c2cafac2d55..0165bba5ed7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2370,7 +2370,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 { @@ -2381,7 +2381,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 a94ae0123d8..9d93d1a34a1 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,144 +1,21 @@ -use crate::hir::def::Namespace; use crate::hir::map::DefPathData; -use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use crate::middle::region; +use crate::hir::def_id::{CrateNum, DefId}; use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; -use crate::middle::cstore::{ExternCrate, ExternCrateSource}; -use syntax::symbol::{keywords, Symbol}; +use crate::ty::subst::{Subst, SubstsRef}; 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 - }) -} - -/// Adds 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`, invokes - /// `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); - } - } - } - - /// Highlights 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 { @@ -156,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(), @@ -205,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()); @@ -318,109 +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>, - ) -> 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::ConstParam(..) | - DefPathData::ClosureExpr | - DefPathData::StructCtor => Namespace::ValueNS, - - DefPathData::MacroDef(..) => Namespace::MacroNS, - - _ => Namespace::TypeNS, - } - } - - /// Returns a string identifying this `DefId`. 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, @@ -588,661 +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 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()) - } - _ => { - 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: SubstsRef<'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) - ) - } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) - } - }).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)); - } - UnpackedKind::Const(ct) => { - nest!(cx, |cx| ct.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>, - 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: SubstsRef<'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>, - ) -> 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 00000000000..caa4090625d --- /dev/null +++ b/src/librustc/ty/print/pretty.rs @@ -0,0 +1,1305 @@ +use crate::hir; +use crate::hir::def::Namespace; +use crate::hir::map::DefPathData; +use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::middle::cstore::{ExternCrate, ExternCrateSource}; +use crate::middle::region; +use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; +use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; +use crate::mir::interpret::ConstValue; +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 + }) +} + +/// Adds 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`, invokes + /// `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); + } + } + } + + /// Highlights 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>, + ) -> 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::ConstParam(..) | + DefPathData::ClosureExpr | + DefPathData::StructCtor => Namespace::ValueNS, + + DefPathData::MacroDef(..) => Namespace::MacroNS, + + _ => Namespace::TypeNS, + } + } + + /// Returns a string identifying this `DefId. 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 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()) + } + _ => { + 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: SubstsRef<'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) + ) + } + ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) + } + }).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>, + 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: SubstsRef<'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>, + ) -> 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(hir_id) = self.tcx.hir().as_local_hir_id(did) { + p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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(hir_id) = self.tcx.hir().as_local_hir_id(did) { + if self.tcx.sess.opts.debugging_opts.span_free_formats { + p!(write("@{:?}", hir_id)); + } else { + p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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 = ", "; + } + } + + if self.config.is_verbose { + p!(write( + " closure_kind_ty={:?} closure_sig_ty={:?}", + substs.closure_kind_ty(did, self.tcx), + substs.closure_sig_ty(did, self.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) => { + match c.val { + ConstValue::Infer(..) => p!(write("_")), + ConstValue::Param(ParamConst { name, .. }) => + p!(write("{}", name)), + _ => 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>], + c_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 c_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 204a9574a64..059a3614704 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,18 +1,15 @@ +use crate::hir; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; -use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; -use crate::ty::{self, ParamConst, Ty, TypeFoldable}; +use crate::ty::subst::{Kind, SubstsRef, UnpackedKind}; +use crate::ty::{self, ParamConst, Ty}; use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use crate::mir::interpret::ConstValue; 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 crate::hir; macro_rules! gen_display_debug_body { ( $with:path ) => { @@ -145,117 +142,6 @@ macro_rules! define_scoped_cx { }; } -impl PrintCx<'a, 'gcx, 'tcx, P> { - fn fn_sig( - mut self, - inputs: &[Ty<'tcx>], - c_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 c_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, @@ -285,7 +171,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; } } @@ -535,7 +421,7 @@ define_print! { } p!(write("fn")); - nest!(|cx| cx.fn_sig(self.inputs(), self.c_variadic, self.output())); + nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); } debug { p!(write("({:?}; c_variadic: {})->{:?}", @@ -624,7 +510,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"))) } }*/ @@ -642,7 +528,7 @@ define_print_multi! { ] (self, cx) { display { - nest!(|cx| cx.in_binder(self)) + nest!(|cx| cx.pretty_in_binder(self)) } } } @@ -658,264 +544,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(hir_id) = self.tcx.hir().as_local_hir_id(did) { - p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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(hir_id) = self.tcx.hir().as_local_hir_id(did) { - if self.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", hir_id)); - } else { - p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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 = ", "; - } - } - - if self.config.is_verbose { - p!(write( - " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.closure_kind_ty(did, self.tcx), - substs.closure_sig_ty(did, self.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) => { - match c.val { - ConstValue::Infer(..) => p!(write("_")), - ConstValue::Param(ParamConst { name, .. }) => - p!(write("{}", name)), - _ => 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 800ddb367e4a56a77ab940ce95023e82b64f3bd2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 21:45:13 +0200 Subject: [PATCH 51/70] 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 0165bba5ed7..c0f0df004c6 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2369,20 +2369,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 9d93d1a34a1..ccd2a702c9f 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 caa4090625d..325897dc042 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -515,7 +515,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| { @@ -818,10 +818,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 != "'_" @@ -846,7 +848,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(_) | @@ -874,10 +876,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 @@ -904,7 +908,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())), @@ -921,7 +925,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(_) => {} @@ -1029,7 +1033,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 059a3614704..20df306dd2a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -166,7 +166,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()) { @@ -463,7 +463,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 d0a1bf5c88a31942dc3e3e1fdd991c4fae5fded9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 18 Jan 2019 22:14:01 +0200 Subject: [PATCH 52/70] 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/ty/print/pretty.rs | 2 +- src/librustc/util/ppaux.rs | 16 +--------------- src/librustc_mir/monomorphize/item.rs | 5 ++--- 8 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index ad24e15b45a..73a8721bdeb 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -768,7 +768,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 53f39d3ac8a..9150417a85d 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -135,7 +135,7 @@ pub mod ty; pub mod util { pub mod captures; pub mod common; - pub mod ppaux; + mod ppaux; pub mod nodemap; pub mod profiling; pub mod bug; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index c0f0df004c6..5e2851e08ec 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -34,7 +34,7 @@ use crate::ty::{ self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; -use crate::util::ppaux; +use crate::ty::print::{FmtPrinter, Printer, PrintCx}; pub use crate::mir::interpret::AssertMessage; @@ -2406,7 +2406,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 b5be1777fa0..f3a800bf46d 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 crate::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 fd0b97e98a3..b137d5f69c6 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -2,10 +2,10 @@ use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; +use crate::ty::print::{FmtPrinter, Printer, PrintCx}; use crate::traits; use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; -use crate::util::ppaux; use std::fmt; use std::iter; @@ -176,7 +176,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/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 325897dc042..a2e8954cf92 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1163,7 +1163,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - if self.config.is_verbose { + if self.tcx.sess.verbose() { p!(write( " closure_kind_ty={:?} closure_sig_ty={:?}", substs.closure_kind_ty(did, self.tcx), diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 20df306dd2a..cb2c8acba82 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,6 @@ use crate::hir; use crate::hir::def::Namespace; -use crate::hir::def_id::DefId; -use crate::ty::subst::{Kind, SubstsRef, UnpackedKind}; +use crate::ty::subst::{Kind, UnpackedKind}; use crate::ty::{self, ParamConst, Ty}; use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use crate::mir::interpret::ConstValue; @@ -142,19 +141,6 @@ macro_rules! define_scoped_cx { }; } -pub fn parameterized( - f: &mut F, - did: DefId, - substs: SubstsRef<'_>, - 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 211f9ad1735..68d13bf2dcb 100644 --- a/src/librustc_mir/monomorphize/item.rs +++ b/src/librustc_mir/monomorphize/item.rs @@ -216,9 +216,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 9c424850e8b342eb348c4a8cbb95704f51aedac3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 19 Jan 2019 03:25:51 +0200 Subject: [PATCH 53/70] 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 | 301 ++++++++++++++------------------ 3 files changed, 146 insertions(+), 215 deletions(-) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index ccd2a702c9f..8c590bd7833 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 a2e8954cf92..6a7c48ee879 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -451,7 +451,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); } _ => {} @@ -461,9 +461,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) }) @@ -484,9 +484,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) }) @@ -578,14 +578,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) @@ -877,7 +877,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; @@ -965,7 +966,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 })) } @@ -1019,7 +1020,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) => { @@ -1033,6 +1034,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); @@ -1045,9 +1047,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(">")); } @@ -1209,9 +1211,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 c_variadic { p!(write(", ...")); @@ -1219,7 +1221,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) @@ -1290,7 +1292,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 cb2c8acba82..4c9d26c8481 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,108 +10,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 { - 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) - } - } - }; - ( () $target:ty, ($self:ident, $cx:ident) $disp:block $dbg:block ) => { +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) } } + + 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 } + + (@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 display $disp:block } ) => { - gen_print_impl! { $generic $target, $vars yes $disp yes $dbg } + + ([$($target:ty),+] $vars:tt $def:tt) => { + $(define_print!($target, $vars $def);)+ }; - ( $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 { + display $disp:block + debug $dbg:block + }) => { + define_print!(@display $target, $vars $disp); + define_print!(@debug $target, $vars $dbg); }; - ( $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)? - } } - }; -} -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)? @@ -142,7 +98,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; @@ -266,7 +222,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(); @@ -282,7 +238,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 { "" }), @@ -292,26 +248,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) } } @@ -330,7 +287,7 @@ impl fmt::Debug for ty::BoundRegion { } define_print! { - () ty::RegionKind, (self, cx) { + ty::RegionKind, (self, cx) { display { return cx.print_region(self); } @@ -350,7 +307,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)) @@ -374,29 +331,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) + } +} + +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! { - () ty::Variance, (self, cx) { - debug { - cx.printer.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 ")); @@ -447,10 +400,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("_")), @@ -501,16 +455,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 { @@ -520,29 +474,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! { - ('tcx) ConstValue<'tcx>, (self, cx) { + ConstValue<'tcx>, (self, cx) { display { match self { ConstValue::Infer(..) => p!(write("_")), @@ -554,7 +514,7 @@ define_print! { } define_print! { - ('tcx) ty::Const<'tcx>, (self, cx) { + ty::Const<'tcx>, (self, cx) { display { p!(write("{} : {}", self.val, self.ty)) } @@ -562,7 +522,7 @@ define_print! { } define_print! { - ('tcx) ty::LazyConst<'tcx>, (self, cx) { + ty::LazyConst<'tcx>, (self, cx) { display { match self { // FIXME(const_generics) this should print at least the type. @@ -574,7 +534,7 @@ define_print! { } define_print! { - () ty::ParamTy, (self, cx) { + ty::ParamTy, (self, cx) { display { p!(write("{}", self.name)) } @@ -585,7 +545,7 @@ define_print! { } define_print! { - () ty::ParamConst, (self, cx) { + ty::ParamConst, (self, cx) { display { p!(write("{}", self.name)) } @@ -596,10 +556,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 { @@ -609,7 +569,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)) } @@ -617,35 +577,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())); } @@ -653,7 +608,7 @@ define_print! { } define_print! { - () ty::ClosureKind, (self, cx) { + ty::ClosureKind, (self, cx) { display { match *self { ty::ClosureKind::Fn => p!(write("Fn")), @@ -665,7 +620,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)), @@ -693,12 +648,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)) } @@ -715,7 +670,7 @@ define_print! { } define_print! { - ('tcx) Kind<'tcx>, (self, cx) { + Kind<'tcx>, (self, cx) { display { match self.unpack() { UnpackedKind::Lifetime(lt) => p!(print(lt)), @@ -725,9 +680,9 @@ define_print! { } debug { match self.unpack() { - UnpackedKind::Lifetime(lt) => p!(print(lt)), - UnpackedKind::Type(ty) => p!(print(ty)), - UnpackedKind::Const(ct) => p!(print(ct)), + UnpackedKind::Lifetime(lt) => p!(write("{:?}", lt)), + UnpackedKind::Type(ty) => p!(write("{:?}", ty)), + UnpackedKind::Const(ct) => p!(write("{:?}", ct)), } } } From fb53bb9e2b67887916a9815428ff5b8bac4c1ebf Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 19 Jan 2019 06:33:44 +0200 Subject: [PATCH 54/70] rustc: move Debug impls from ppaux to ty::structural_impls. --- src/librustc/ty/structural_impls.rs | 270 +++++++++++++++++++++++++ src/librustc/ty/subst.rs | 11 ++ src/librustc/util/ppaux.rs | 294 +--------------------------- 3 files changed, 288 insertions(+), 287 deletions(-) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 43ab32237de..45db95e2b0f 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -3,17 +3,287 @@ //! hand, though we've recently added some macros (e.g., //! `BraceStructLiftImpl!`) to help with the tedium. +use crate::hir::def::Namespace; use crate::mir::ProjectionKind; use crate::mir::interpret::ConstValue; use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use crate::ty::print::{FmtPrinter, PrintCx, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use smallvec::SmallVec; use crate::mir::interpret; +use std::fmt; +use std::iter; use std::marker::PhantomData; 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", + ty::GenericParamDefKind::Const => "Const", + }; + 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_by_hir_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, "({:?}; c_variadic: {})->{:?}", + self.inputs(), self.c_variadic, self.output()) + } +} + +impl fmt::Debug for ty::TyVid { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}t", self.index) + } +} + +impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "_#{}c", 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::ParamConst { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}/#{}", self.name, self.index) + } +} + +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 8c67cdf62b6..84642865614 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -12,6 +12,7 @@ use smallvec::SmallVec; use rustc_macros::HashStable; use core::intrinsics; +use std::fmt; use std::cmp::Ordering; use std::marker::PhantomData; use std::mem; @@ -69,6 +70,16 @@ 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), + UnpackedKind::Const(ct) => ct.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 4c9d26c8481..2e11a374136 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -2,16 +2,20 @@ use crate::hir; use crate::hir::def::Namespace; use crate::ty::subst::{Kind, UnpackedKind}; use crate::ty::{self, ParamConst, Ty}; -use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; +use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; use crate::mir::interpret::ConstValue; -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; @@ -34,38 +38,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 { @@ -160,67 +132,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", - ty::GenericParamDefKind::Const => "Const", - }; - 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_by_hir_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 { @@ -260,91 +171,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 => "*", - }) } } @@ -362,40 +193,6 @@ define_print! { p!(write("fn")); nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); } - debug { - p!(write("({:?}; c_variadic: {})->{:?}", - self.inputs(), self.c_variadic, self.output())) - } - } -} - -impl fmt::Debug for ty::TyVid { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}t", self.index) - } -} - -impl<'tcx> fmt::Debug for ty::ConstVid<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "_#{}f", 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()) } } @@ -415,31 +212,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) } } @@ -478,12 +250,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)) - } } } @@ -495,12 +261,6 @@ define_print! { } } -impl fmt::Debug for Ty<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Display::fmt(self, f) - } -} - define_print! { ConstValue<'tcx>, (self, cx) { display { @@ -538,9 +298,6 @@ define_print! { display { p!(write("{}", self.name)) } - debug { - p!(write("{}/#{}", self.name, self.idx)) - } } } @@ -549,9 +306,6 @@ define_print! { display { p!(write("{}", self.name)) } - debug { - p!(write("{}/#{}", self.name, self.index)) - } } } @@ -581,10 +335,6 @@ define_print! { display { p!(print(self.trait_ref.self_ty()), write(": "), print(self.trait_ref)) } - debug { - p!(write("TraitPredicate({:?})", - self.trait_ref)) - } } } @@ -593,9 +343,6 @@ define_print! { display { p!(print(self.projection_ty), write(" == "), print(self.ty)) } - debug { - p!(write("ProjectionPredicate({:?}, {:?})", self.projection_ty, self.ty)) - } } } @@ -646,26 +393,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)) - } - } - } } } @@ -678,12 +405,5 @@ define_print! { UnpackedKind::Const(ct) => p!(print(ct)), } } - debug { - match self.unpack() { - UnpackedKind::Lifetime(lt) => p!(write("{:?}", lt)), - UnpackedKind::Type(ty) => p!(write("{:?}", ty)), - UnpackedKind::Const(ct) => p!(write("{:?}", ct)), - } - } } } From 030cdc972930aa864fe89dd4c5125ba26ebd05ac Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 20 Jan 2019 04:56:48 +0200 Subject: [PATCH 55/70] 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 | 22 ----- src/librustc/util/ppaux.rs | 121 +++++++++++++++------------- 4 files changed, 142 insertions(+), 104 deletions(-) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 8c590bd7833..d1632e1e9bb 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,6 +1,6 @@ use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId}; -use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::ty::subst::{Subst, SubstsRef}; 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 6a7c48ee879..7488b074471 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -205,6 +205,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>, @@ -784,6 +793,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, @@ -1125,7 +1143,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); @@ -1257,9 +1275,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; @@ -1302,6 +1317,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), @@ -1309,3 +1347,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 45db95e2b0f..dfb7e64d98b 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -775,28 +775,6 @@ BraceStructLiftImpl! { } } -// FIXME(eddyb) this is like what some of the macros above generate, -// except that macros *also* generate a foldable impl, which we don't -// want (with it we'd risk bypassing `fold_region` / `fold_const`). -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()) - } -} - -impl<'a, 'tcx> Lift<'tcx> for ty::LazyConst<'a> { - type Lifted = ty::LazyConst<'tcx>; - fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option { - match self { - ty::LazyConst::Evaluated(v) => Some(ty::LazyConst::Evaluated(tcx.lift(v)?)), - ty::LazyConst::Unevaluated(def_id, substs) => { - Some(ty::LazyConst::Unevaluated(*def_id, tcx.lift(substs)?)) - } - } - } -} - 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 2e11a374136..f8d0c8f661c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,7 +1,7 @@ use crate::hir; use crate::hir::def::Namespace; use crate::ty::subst::{Kind, UnpackedKind}; -use crate::ty::{self, ParamConst, Ty}; +use crate::ty::{self, ParamConst, Ty, TyCtxt}; use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; use crate::mir::interpret::ConstValue; @@ -10,13 +10,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 { @@ -29,14 +76,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 }); }; } @@ -172,11 +220,7 @@ define_print! { } define_print! { - ty::RegionKind, (self, cx) { - display { - return cx.print_region(self); - } - } + ty::RegionKind } define_print! { @@ -215,34 +259,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! { @@ -254,11 +272,7 @@ define_print! { } define_print! { - Ty<'tcx>, (self, cx) { - display { - return cx.print_type(self); - } - } + Ty<'tcx> } define_print! { @@ -309,13 +323,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 1a0f3a285697b6238793ce3c1353f0d2f0c28938 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 20 Jan 2019 14:00:39 +0200 Subject: [PATCH 56/70] 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 | 300 +++++++++++++++++++++++ src/librustc/util/ppaux.rs | 418 -------------------------------- 4 files changed, 303 insertions(+), 425 deletions(-) delete mode 100644 src/librustc/util/ppaux.rs diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 9150417a85d..b6677326227 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -135,7 +135,6 @@ pub mod ty; pub mod util { pub mod captures; pub mod common; - mod ppaux; pub mod nodemap; pub mod profiling; pub mod bug; diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index d1632e1e9bb..85786818a53 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 7488b074471..f1ab58bc2e2 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -9,6 +9,7 @@ use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::mir::interpret::ConstValue; use syntax::symbol::{keywords, Symbol}; +use rustc_target::spec::abi::Abi; use syntax::symbol::InternedString; use std::cell::Cell; @@ -1357,3 +1358,302 @@ 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.c_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())); + } + + ConstValue<'tcx> { + match self { + ConstValue::Infer(..) => p!(write("_")), + ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)), + _ => p!(write("{:?}", self)), + } + } + + ty::Const<'tcx> { + p!(write("{} : {}", self.val, self.ty)) + } + + ty::LazyConst<'tcx> { + match self { + // FIXME(const_generics) this should print at least the type. + ty::LazyConst::Unevaluated(..) => p!(write("_ : _")), + ty::LazyConst::Evaluated(c) => p!(write("{}", c)), + } + } + + ty::ParamTy { + p!(write("{}", self.name)) + } + + ty::ParamConst { + 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)), + UnpackedKind::Const(ct) => p!(print(ct)), + } + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs deleted file mode 100644 index f8d0c8f661c..00000000000 --- a/src/librustc/util/ppaux.rs +++ /dev/null @@ -1,418 +0,0 @@ -use crate::hir; -use crate::hir::def::Namespace; -use crate::ty::subst::{Kind, UnpackedKind}; -use crate::ty::{self, ParamConst, Ty, TyCtxt}; -use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; -use crate::mir::interpret::ConstValue; - -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.c_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! { - ConstValue<'tcx>, (self, cx) { - display { - match self { - ConstValue::Infer(..) => p!(write("_")), - ConstValue::Param(ParamConst { name, .. }) => p!(write("{}", name)), - _ => p!(write("{:?}", self)), - } - } - } -} - -define_print! { - ty::Const<'tcx>, (self, cx) { - display { - p!(write("{} : {}", self.val, self.ty)) - } - } -} - -define_print! { - ty::LazyConst<'tcx>, (self, cx) { - display { - match self { - // FIXME(const_generics) this should print at least the type. - ty::LazyConst::Unevaluated(..) => p!(write("_ : _")), - ty::LazyConst::Evaluated(c) => p!(write("{}", c)), - } - } - } -} - -define_print! { - ty::ParamTy, (self, cx) { - display { - p!(write("{}", self.name)) - } - } -} - -define_print! { - ty::ParamConst, (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)), - UnpackedKind::Const(ct) => p!(print(ct)), - } - } - } -} From 381fa7aa18d0440d122c476bdbd074281a93b6a9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 20 Jan 2019 19:46:47 +0200 Subject: [PATCH 57/70] 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 | 6 +- 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, 185 insertions(+), 190 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 73a8721bdeb..a7ce53e9876 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -526,9 +526,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 2fabbbeadbd..f649309004b 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 39ab244dae1..fd01ed85ef7 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 @@ -347,10 +347,8 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { let mut printer = ty::print::FmtPrinter::new(f, Namespace::TypeNS); printer.region_highlight_mode = self.highlight; - ty::print::PrintCx::with(self.tcx, printer, |cx| { - self.value.print(cx)?; - Ok(()) - }) + self.value.print(ty::print::PrintCx::new(self.tcx, printer))?; + Ok(()) } } diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 85786818a53..aac76025951 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -4,52 +4,50 @@ use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::ty::subst::{Subst, SubstsRef}; 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(printer: P, f: impl FnOnce(PrintCx<'_, '_, '_, P>) -> R) -> R { - ty::tls::with(|tcx| PrintCx::with(tcx, printer, f)) + 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()) } } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index f1ab58bc2e2..1f609dbc6e5 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)) @@ -185,16 +186,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. @@ -243,6 +235,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!( @@ -445,7 +424,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( @@ -475,7 +454,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() }) } @@ -498,7 +477,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(print(self_ty)); - Ok(cx.printer) + cx.ok() }) } @@ -556,7 +535,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| { @@ -568,7 +547,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { empty = false; Ok(()) } else { - write!(cx.printer, ", ") + write!(cx, ", ") } }; @@ -598,11 +577,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(); @@ -629,17 +651,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() }; } } @@ -693,14 +715,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>, @@ -719,15 +740,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>( @@ -737,18 +758,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>, @@ -768,18 +789,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( @@ -787,11 +801,11 @@ impl PrettyPrinter for FmtPrinter { def_id: DefId, substs: Option>, ) -> 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( @@ -807,18 +821,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( @@ -832,7 +846,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; } @@ -889,15 +903,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; @@ -918,7 +932,7 @@ impl FmtPrinter { if let ty::BrNamed(_, name) = br { if name != "" && name != "'_" { p!(write("{}", name)); - return Ok(self.printer); + return self.ok(); } } @@ -958,7 +972,7 @@ impl FmtPrinter { ty::ReClosureBound(vid) => p!(write("{:?}", vid)), } - Ok(self.printer) + self.ok() } } @@ -1056,7 +1070,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); @@ -1072,7 +1086,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. @@ -1216,7 +1230,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } } - Ok(self.printer) + self.ok() } pub fn pretty_fn_sig( @@ -1243,11 +1257,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 { @@ -1262,13 +1283,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 { @@ -1278,13 +1299,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(_) | @@ -1293,11 +1314,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) } }; @@ -1305,25 +1326,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)) => { @@ -1335,17 +1351,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; } } @@ -1377,10 +1386,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(()) } } @@ -1391,10 +1400,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(()) } } @@ -1427,7 +1434,7 @@ macro_rules! define_print_and_forward_display { define_scoped_cx!($cx); let _: () = $print; #[allow(unreachable_code)] - Ok($cx.printer) + $cx.ok() } } @@ -1555,7 +1562,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 a17a554480e..b7e69f64f5a 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -224,11 +224,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(tcx), |cx| { - cx.print_def_path(def_id, None, iter::empty()) - .unwrap() - .into_interned() - }) + PrintCx::new(tcx, SymbolPath::new(tcx)) + .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 { @@ -415,7 +414,7 @@ impl Printer for SymbolPath { self: PrintCx<'_, '_, '_, Self>, _region: ty::Region<'_>, ) -> Result { - Ok(self.printer) + self.ok() } fn print_type( @@ -440,8 +439,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>, @@ -524,10 +523,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 7a92a507ec1..d7dd0313e94 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -2341,9 +2341,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 } @@ -2368,9 +2366,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 02b8291369d..c486628a4f5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4312,9 +4312,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 72690d24f02543f5a3c77a8506da48bb32fdc466 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 23 Jan 2019 18:39:05 +0200 Subject: [PATCH 58/70] rustc: always hide defaulted generic args, even in verbose mode. --- src/librustc/ty/print/mod.rs | 31 +++++++++++++++++++++---- src/librustc/ty/print/pretty.rs | 22 +----------------- 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 aac76025951..af6f8ba72f0 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,7 +1,7 @@ use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; -use crate::ty::subst::{Subst, SubstsRef}; +use crate::ty::subst::{Kind, Subst, SubstsRef}; 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,30 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } } + pub fn generic_params_to_print( + &self, + generics: &'a ty::Generics, + substs: SubstsRef<'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) + ) + } + ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) + } + }).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 1f609dbc6e5..7358dd1932f 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -502,25 +502,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) - ) - } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) - } - }).count() - }; - - let params = ¶ms[..params.len() - num_supplied_defaults]; let mut args = params.iter().map(|param| { substs[param.index as usize] }).filter(|arg| { @@ -657,8 +638,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() diff --git a/src/test/ui/substs-ppaux.rs b/src/test/ui/substs-ppaux.rs index 7ad7ccb5444..129ebd43594 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 9d8a555dffe..86936475f8c 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 4deaa69b429442c0e25a7828cfd63d7be78772d8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 23 Jan 2019 19:36:39 +0200 Subject: [PATCH 59/70] 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 | 56 +++++++++---------- 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, 41 insertions(+), 39 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index a7ce53e9876..14d9f9deb50 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -826,11 +826,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 69d5492c0f4..c576586fcad 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 4a3e814cf47..fa3c76a817a 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -190,7 +190,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 7358dd1932f..d4a539e3eed 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -222,14 +222,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; @@ -497,7 +493,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, } @@ -535,19 +531,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)); } @@ -822,7 +805,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 { @@ -902,8 +885,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) | @@ -919,6 +903,7 @@ impl FmtPrinter { if let Some((region, counter)) = highlight.highlight_bound_region { if br == region { p!(write("'{}", counter)); + return self.ok(); } } } @@ -938,20 +923,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() } } @@ -978,7 +976,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 })) @@ -1027,7 +1025,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 b7e69f64f5a..1edb5dfe2b8 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -512,7 +512,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 b2a05551837..e20869a6f3a 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 01b2631a537..ac5e5e9aabc 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; | ^^^^^^^^^^^^^^ | -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 9cf0b0ffabd..be441bc4808 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; | ^^^^^^ | -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; From ffa00d4628aac6503d7ef04b9f37a52ed6104dfc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 24 Jan 2019 19:52:43 +0200 Subject: [PATCH 60/70] 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 14d9f9deb50..06495510ede 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -446,7 +446,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { use hir::def_id::CrateNum; use ty::print::{PrintCx, Printer}; - use ty::subst::SubstsRef; + use ty::subst::Kind; struct AbsolutePathPrinter; @@ -513,8 +513,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - _params: &[ty::GenericParamDef], - _substs: SubstsRef<'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 af6f8ba72f0..d89bd84a349 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: SubstsRef<'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: SubstsRef<'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..]; @@ -227,7 +226,9 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) } }).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 d4a539e3eed..a1e157685c9 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -207,21 +207,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. @@ -482,66 +491,25 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, P>, ) -> Result, - params: &[ty::GenericParamDef], - substs: SubstsRef<'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, ", ") }) } } @@ -621,8 +589,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() }; @@ -739,11 +707,23 @@ impl Printer for FmtPrinter { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - params: &[ty::GenericParamDef], - substs: SubstsRef<'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) } } @@ -798,13 +778,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<'_>, @@ -1498,6 +1471,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 1edb5dfe2b8..93e7e495d4e 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::SubstsRef; +use rustc::ty::subst::{Kind, SubstsRef, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc::util::common::record_time; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -503,11 +503,16 @@ impl Printer for SymbolPath { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - params: &[ty::GenericParamDef], - substs: SubstsRef<'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 c486628a4f5..94c954b01b1 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::{InternalSubsts, SubstsRef}; +use rustc::ty::subst::{Kind, InternalSubsts, SubstsRef}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; use rustc::ty::layout::VariantIdx; @@ -4304,8 +4304,7 @@ where F: Fn(DefId) -> Def { print_prefix: impl FnOnce( PrintCx<'_, 'gcx, 'tcx, Self>, ) -> Result, - _params: &[ty::GenericParamDef], - _substs: SubstsRef<'tcx>, + _args: impl Iterator> + Clone, _projections: impl Iterator>, ) -> Result { print_prefix(self) From c0c485c3ad7017c99137d8c9bc9afc729e7db534 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 24 Jan 2019 20:47:02 +0200 Subject: [PATCH 61/70] 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 06495510ede..10c34aaf5b7 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -58,7 +58,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode}; use crate::ty::error::TypeError; use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TyKind, TypeFoldable}; use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString}; -use std::{cmp, fmt, iter}; +use std::{cmp, fmt}; use syntax_pos::{Pos, Span}; mod note; @@ -458,6 +458,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { type Path = Vec; type Region = !; type Type = !; + type DynExistential = !; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -473,6 +474,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, @@ -513,8 +521,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) } @@ -526,7 +533,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 5e2851e08ec..d1574bb322d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2409,7 +2409,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 b137d5f69c6..66c99a7c4fc 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -178,7 +178,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 d89bd84a349..4e81533589e 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -5,7 +5,6 @@ use crate::ty::subst::{Kind, Subst, SubstsRef}; 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>, - 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>, - 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: SubstsRef<'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, .. } => { @@ -226,9 +231,8 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) } }).count(); - params[..params.len() - num_supplied_defaults].iter().map(move |param| { - substs[param.index as usize] - }) + + &substs[own_params] } fn default_print_impl_path( @@ -261,7 +265,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, ) @@ -344,3 +348,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 a1e157685c9..d27e64b27a2 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. @@ -177,6 +176,7 @@ pub trait PrettyPrinter: Path = Self, Region = Self, Type = Self, + DynExistential = Self, > + fmt::Write { @@ -195,7 +195,7 @@ pub trait PrettyPrinter: def_id: DefId, substs: Option>, ) -> Result { - self.print_def_path(def_id, substs, iter::empty()) + self.print_def_path(def_id, substs) } fn in_binder( @@ -211,14 +211,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)); @@ -485,33 +484,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. @@ -570,12 +542,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>, - projections: impl Iterator>, ) -> Result { // FIXME(eddyb) avoid querying `tcx.generics_of` and `tcx.def_key` // both here and in `default_print_def_path`. @@ -590,7 +562,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() }; @@ -615,13 +587,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( @@ -638,6 +610,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, @@ -703,27 +682,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() + } } } @@ -745,7 +730,7 @@ impl PrettyPrinter for FmtPrinter { substs: Option>, ) -> 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) @@ -995,7 +980,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); @@ -1008,7 +993,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) => { @@ -1184,6 +1169,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>], @@ -1399,6 +1483,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! { @@ -1412,70 +1497,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(); @@ -1494,14 +1515,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 ")); @@ -1531,7 +1565,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))); } ConstValue<'tcx> { @@ -1575,7 +1609,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 { @@ -1596,7 +1630,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 dfb7e64d98b..32a39c2eb88 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -14,7 +14,6 @@ use smallvec::SmallVec; use crate::mir::interpret; use std::fmt; -use std::iter; use std::marker::PhantomData; use std::rc::Rc; @@ -36,7 +35,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(()) }) } @@ -45,7 +44,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 93e7e495d4e..9620c3efda0 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, SubstsRef, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -106,7 +106,6 @@ use syntax_pos::symbol::Symbol; use log::debug; use std::fmt::{self, Write}; -use std::iter; use std::mem::{self, discriminant}; pub fn provide(providers: &mut Providers<'_>) { @@ -225,7 +224,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(tcx)) - .print_def_path(def_id, None, iter::empty()) + .print_def_path(def_id, None) .unwrap() .into_interned() } @@ -409,6 +408,7 @@ impl Printer for SymbolPath { type Path = Self; type Region = Self; type Type = Self; + type DynExistential = Self; fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -429,12 +429,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, @@ -499,20 +514,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() + } } } @@ -523,6 +544,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 94c954b01b1..6822de2bceb 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; @@ -4235,6 +4235,7 @@ where F: Fn(DefId) -> Def { type Path = Vec; type Region = (); type Type = (); + type DynExistential = (); fn print_region( self: PrintCx<'_, '_, '_, Self>, @@ -4250,6 +4251,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, @@ -4304,15 +4312,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 2a656828acc6fa619e2e83f928ca21f2281c911b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 02:34:19 +0200 Subject: [PATCH 62/70] rustc: remove the ability for pretty-printers to override nesting. --- src/librustc/ty/print/pretty.rs | 121 ++++++++++----------- src/librustc_codegen_utils/symbol_names.rs | 8 +- 2 files changed, 59 insertions(+), 70 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index d27e64b27a2..da01fd11a3f 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 { @@ -180,15 +180,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>, @@ -214,11 +205,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) }); @@ -470,7 +463,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); @@ -492,7 +485,7 @@ pub struct FmtPrinter(Box>); pub struct FmtPrinterData { fmt: F, - empty: bool, + empty_path: bool, in_value: bool, used_region_names: FxHashSet, @@ -519,7 +512,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, @@ -531,7 +524,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) } } @@ -549,16 +541,18 @@ impl Printer for FmtPrinter { def_id: DefId, substs: Option>, ) -> 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); @@ -621,15 +615,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() } @@ -638,7 +635,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>( @@ -649,17 +648,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>, @@ -673,10 +671,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) @@ -688,7 +687,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| { @@ -705,6 +706,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() @@ -713,17 +717,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, @@ -749,11 +742,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)?; @@ -957,7 +946,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) => { @@ -980,7 +969,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); @@ -993,7 +982,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) => { @@ -1094,7 +1083,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); @@ -1179,7 +1168,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; @@ -1189,7 +1178,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; } } @@ -1228,8 +1217,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, ", ")?; } @@ -1262,7 +1251,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() @@ -1531,7 +1520,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)) } } } @@ -1546,7 +1535,7 @@ define_print_and_forward_display! { } p!(write("fn")); - nest!(|cx| cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); + nest!(cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); } ty::InferTy { @@ -1565,7 +1554,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))); } ConstValue<'tcx> { @@ -1609,7 +1598,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 { @@ -1630,17 +1619,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 9620c3efda0..084b86b1eb4 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -445,7 +445,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() } @@ -520,7 +520,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() { @@ -551,10 +551,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 52b4f2daa0e1a9c4aea4b729c0bcd46b5991f8a3 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 12:11:50 +0200 Subject: [PATCH 63/70] 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 | 10 +- 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 | 1256 ++++++++--------- src/librustc/ty/structural_impls.rs | 30 +- src/librustc_codegen_utils/symbol_names.rs | 175 +-- .../borrow_check/error_reporting.rs | 8 +- src/librustdoc/clean/mod.rs | 57 +- 11 files changed, 849 insertions(+), 906 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 10c34aaf5b7..52b42881038 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -445,14 +445,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; @@ -460,67 +462,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) @@ -532,7 +532,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 f649309004b..0a83b839201 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 fd01ed85ef7..e708454b5b6 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 @@ -337,17 +337,17 @@ impl NiceRegionError<'me, 'gcx, 'tcx> { } } - impl<'tcx, T> fmt::Display for Highlighted<'_, '_, 'tcx, T> - where T: for<'a, 'b> Print<'tcx, - FmtPrinter<&'a mut fmt::Formatter<'b>>, + impl<'a, 'gcx, 'tcx, T> fmt::Display for Highlighted<'a, 'gcx, 'tcx, T> + where T: for<'b, 'c> Print<'gcx, 'tcx, + FmtPrinter<'a, 'gcx, 'tcx, &'b mut fmt::Formatter<'c>>, Error = fmt::Error, >, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut printer = ty::print::FmtPrinter::new(f, Namespace::TypeNS); + let mut printer = ty::print::FmtPrinter::new(self.tcx, f, Namespace::TypeNS); printer.region_highlight_mode = self.highlight; - self.value.print(ty::print::PrintCx::new(self.tcx, printer))?; + self.value.print(printer)?; Ok(()) } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d1574bb322d..3218f8ea5de 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -34,7 +34,7 @@ use crate::ty::{ self, AdtDef, CanonicalUserTypeAnnotations, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt, UserTypeAnnotationIndex, }; -use crate::ty::print::{FmtPrinter, Printer, PrintCx}; +use crate::ty::print::{FmtPrinter, Printer}; pub use crate::mir::interpret::AssertMessage; @@ -2407,9 +2407,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 66c99a7c4fc..89d956c8bfa 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -2,7 +2,7 @@ use crate::hir::Unsafety; use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; -use crate::ty::print::{FmtPrinter, Printer, PrintCx}; +use crate::ty::print::{FmtPrinter, Printer}; use crate::traits; use rustc_target::spec::abi::Abi; use rustc_macros::HashStable; @@ -176,9 +176,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 4e81533589e..ad17a8114ca 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -5,59 +5,18 @@ use crate::ty::subst::{Kind, Subst, SubstsRef}; 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>, ) -> Result { self.default_print_def_path(def_id, substs) } fn print_impl_path( - self: PrintCx<'_, '_, 'tcx, Self>, + self, impl_def_id: DefId, substs: Option>, 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>, - ) -> 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: SubstsRef<'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) ) } ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) @@ -241,7 +196,7 @@ impl PrintCx<'_, 'gcx, 'tcx, P> { _substs: Option>, 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); @@ -250,14 +205,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 { @@ -325,34 +280,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 da01fd11a3f..fff4ca822d2 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 { @@ -170,8 +165,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, @@ -182,7 +177,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>, ) -> Result { @@ -190,93 +185,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) - } -} + // Defaults (should not be overriden): -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::ConstParam(..) | - DefPathData::ClosureExpr | - DefPathData::StructCtor => Namespace::ValueNS, - - DefPathData::MacroDef(..) => Namespace::MacroNS, - - _ => Namespace::TypeNS, - } - } - - /// Returns a string identifying this `DefId. 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 - } -} - -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 +256,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 +278,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 +293,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)), + None => return Ok((self, 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)); - }; - 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, @@ -403,7 +354,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { // 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) + self.tcx().item_children(visible_parent) .iter() .find(|child| child.def.def_id() == def_id) .map(|child| child.ident.as_str()) @@ -413,7 +364,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() } @@ -421,14 +372,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 @@ -451,19 +402,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); @@ -474,15 +423,398 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> { } p!(print(self_ty)); - cx.ok() + Ok(cx) }) } + + 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(" {{")); + self = 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) => { + self = self.print_def_path(def.did, Some(substs))?; + } + ty::Dynamic(data, r) => { + let print_r = self.region_should_not_be_omitted(r); + if print_r { + p!(write("(")); + } + p!(write("dyn "), print(data)); + if print_r { + p!(write(" + "), print(r), write(")")); + } + } + ty::Foreign(def_id) => { + self = self.print_def_path(def_id, None)?; + } + 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) => { + // FIXME(eddyb) print this with `print_def_path`. + if self.tcx().sess.verbose() { + p!(write("Opaque({:?}, {:?})", def_id, substs)); + return Ok(self); + } + + 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(first)); + for subst in substs { + p!(write(", "), print(subst)); + } + p!(write(">")); + } + 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 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(hir_id) = self.tcx().hir().as_local_hir_id(did) { + p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_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) => { + self = self.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(hir_id) = self.tcx().hir().as_local_hir_id(did) { + if self.tcx().sess.opts.debugging_opts.span_free_formats { + p!(write("@{:?}", hir_id)); + } else { + p!(write("@{:?}", self.tcx().hir().span_by_hir_id(hir_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 = ", "; + } + } + + if self.tcx().sess.verbose() { + p!(write( + " closure_kind_ty={:?} closure_sig_ty={:?}", + substs.closure_kind_ty(did, self.tcx()), + substs.closure_sig_ty(did, self.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) => { + match c.val { + ConstValue::Infer(..) => p!(write("_")), + ConstValue::Param(ParamConst { name, .. }) => + p!(write("{}", name)), + _ => p!(write("{}", c.unwrap_usize(self.tcx()))), + } + } + } + p!(write("]")) + } + ty::Slice(ty) => { + p!(write("["), print(ty), write("]")) + } + } + + Ok(self) + } + + 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() { + 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() { + 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)?; + 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); + + 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; + } + + // 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; + + self = self.print_def_path(def_id, None)?; + } + + Ok(self) + } + + fn pretty_fn_sig( + mut self, + inputs: &[Ty<'tcx>], + c_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(ty)); + for &ty in inputs { + p!(write(", "), print(ty)); + } + if c_variadic { + p!(write(", ...")); + } + } + p!(write(")")); + if !output.is_unit() { + p!(write(" -> "), print(output)); + } + + Ok(self) + } } // HACK(eddyb) boxed to avoid moving around a large struct by-value. -pub struct FmtPrinter(Box>); +pub struct FmtPrinter<'a, 'gcx, 'tcx, F>(Box>); -pub struct FmtPrinterData { +pub struct FmtPrinterData<'a, 'gcx, 'tcx, F> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, fmt: F, empty_path: bool, @@ -495,22 +827,23 @@ pub struct FmtPrinterData { pub region_highlight_mode: RegionHighlightMode, } -impl Deref for FmtPrinter { - type Target = FmtPrinterData; +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 { +impl DerefMut for FmtPrinter<'_, '_, '_, F> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } -impl FmtPrinter { - pub fn new(fmt: F, ns: Namespace) -> Self { +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, @@ -522,13 +855,44 @@ impl FmtPrinter { } } -impl fmt::Write for FmtPrinter { +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::ConstParam(..) | + DefPathData::ClosureExpr | + DefPathData::StructCtor => Namespace::ValueNS, + + DefPathData::MacroDef(..) => Namespace::MacroNS, + + _ => Namespace::TypeNS, + } + } + + /// Returns a string identifying this `DefId`. 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 for FmtPrinter { +impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { type Error = fmt::Error; type Path = Self; @@ -536,8 +900,12 @@ impl Printer for FmtPrinter { type Type = Self; type DynExistential = Self; + fn tcx(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> { + self.tcx + } + fn print_def_path( - mut self: PrintCx<'_, '_, 'tcx, Self>, + mut self, def_id: DefId, substs: Option>, ) -> Result { @@ -547,19 +915,14 @@ 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() { - 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) + 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 { - self.ok() - }; + Ok(cx) + }, + (cx, false) => self = cx, } } @@ -591,28 +954,28 @@ impl Printer for FmtPrinter { } fn print_region( - self: PrintCx<'_, '_, '_, Self>, + self, region: ty::Region<'_>, ) -> Result { self.pretty_print_region(region) } fn print_type( - self: PrintCx<'_, '_, 'tcx, Self>, + self, ty: Ty<'tcx>, ) -> Result { self.pretty_print_type(ty) } fn print_dyn_existential( - self: PrintCx<'_, '_, 'tcx, Self>, + self, predicates: &'tcx ty::List>, ) -> Result { self.pretty_print_dyn_existential(predicates) } fn path_crate( - mut self: PrintCx<'_, '_, '_, Self>, + mut self, cnum: CrateNum, ) -> Result { self.empty_path = true; @@ -628,68 +991,60 @@ impl Printer for FmtPrinter { write!(self, "{}", self.tcx.crate_name(cnum))?; self.empty_path = false; } - self.ok() + Ok(self) } fn path_qualified( - self: PrintCx<'_, '_, 'tcx, Self>, + mut 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) + self = self.pretty_path_qualified(self_ty, trait_ref)?; + self.empty_path = false; + Ok(self) } - fn path_append_impl<'gcx, 'tcx>( - self: PrintCx<'_, 'gcx, 'tcx, Self>, - print_prefix: impl FnOnce( - PrintCx<'_, 'gcx, 'tcx, Self>, - ) -> Result, + fn path_append_impl( + mut self, + print_prefix: impl FnOnce(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, "::")?; + self = self.pretty_path_append_impl(|mut cx| { + cx = print_prefix(cx)?; + if !cx.empty_path { + write!(cx, "::")?; } - Ok(path) + Ok(cx) }, self_ty, trait_ref)?; - path.empty_path = false; - Ok(path) + self.empty_path = false; + Ok(self) } - 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)?; // 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, "::")?; + if !self.empty_path { + write!(self, "::")?; } - write!(path, "{}", text)?; - path.empty_path = false; + write!(self, "{}", text)?; + self.empty_path = false; } - Ok(path) + 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 { - define_scoped_cx!(self); - - nest!(print_prefix(self)); + self = print_prefix(self)?; // Don't print `'_` if there's no unerased regions. let print_regions = args.iter().any(|arg| { @@ -711,36 +1066,36 @@ impl Printer for FmtPrinter { } self.generic_delimiters(|cx| cx.comma_sep(args)) } else { - self.ok() + Ok(self) } } } -impl PrettyPrinter for FmtPrinter { +impl PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { fn print_value_path( - mut self: PrintCx<'_, '_, 'tcx, Self>, + mut self, def_id: DefId, substs: Option>, ) -> 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; + self = self.print_def_path(def_id, substs)?; + self.in_value = was_in_value; - Ok(path) + Ok(self) } 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> { self.pretty_in_binder(value) } - 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, "<")?; @@ -753,7 +1108,7 @@ impl PrettyPrinter for FmtPrinter { } fn region_should_not_be_omitted( - self: &PrintCx<'_, '_, '_, Self>, + &self, region: ty::Region<'_>, ) -> bool { let highlight = self.region_highlight_mode; @@ -805,9 +1160,9 @@ impl PrettyPrinter for FmtPrinter { } // HACK(eddyb) limited to `FmtPrinter` because of `region_highlight_mode`. -impl FmtPrinter { +impl FmtPrinter<'_, '_, '_, F> { pub fn pretty_print_region( - mut self: PrintCx<'_, '_, '_, Self>, + mut self, region: ty::Region<'_>, ) -> Result { define_scoped_cx!(self); @@ -816,12 +1171,12 @@ impl FmtPrinter { let highlight = self.region_highlight_mode; if let Some(n) = highlight.region_highlighted(region) { p!(write("'{}", n)); - return self.ok(); + return Ok(self); } if self.tcx.sess.verbose() { p!(write("{:?}", region)); - return self.ok(); + return Ok(self); } let identify_regions = self.tcx.sess.opts.debugging_opts.identify_regions; @@ -834,7 +1189,7 @@ impl FmtPrinter { ty::ReEarlyBound(ref data) => { if data.name != "" { p!(write("{}", data.name)); - return self.ok(); + return Ok(self); } } ty::ReLateBound(_, br) | @@ -843,14 +1198,14 @@ impl FmtPrinter { if let ty::BrNamed(_, name) = br { if name != "" && name != "'_" { p!(write("{}", name)); - return self.ok(); + return Ok(self); } } if let Some((region, counter)) = highlight.highlight_bound_region { if br == region { p!(write("'{}", counter)); - return self.ok(); + return Ok(self); } } } @@ -870,429 +1225,45 @@ impl FmtPrinter { first_statement_index.index() )), } - return self.ok(); + return Ok(self); } ty::ReVar(region_vid) if identify_regions => { p!(write("{:?}", region_vid)); - return self.ok(); + return Ok(self); } ty::ReVar(_) => {} ty::ReScope(_) | ty::ReErased => {} ty::ReStatic => { p!(write("'static")); - return self.ok(); + return Ok(self); } ty::ReEmpty => { p!(write("'")); - return self.ok(); + return Ok(self); } // The user should never encounter these in unsubstituted form. ty::ReClosureBound(vid) => { p!(write("{:?}", vid)); - return self.ok(); + return Ok(self); } } 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::Dynamic(data, r) => { - let print_r = self.region_should_not_be_omitted(r); - if print_r { - p!(write("(")); - } - p!(write("dyn "), print(data)); - if print_r { - p!(write(" + "), print(r), write(")")); - } - } - ty::Foreign(def_id) => { - nest!(self.print_def_path(def_id, None)); - } - 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) => { - // FIXME(eddyb) print this with `print_def_path`. - if self.tcx.sess.verbose() { - p!(write("Opaque({:?}, {:?})", def_id, substs)); - return self.ok(); - } - - 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(first)); - for subst in substs { - p!(write(", "), print(subst)); - } - p!(write(">")); - } - return self.ok(); - } - // 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(hir_id) = self.tcx.hir().as_local_hir_id(did) { - p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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!(self.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(hir_id) = self.tcx.hir().as_local_hir_id(did) { - if self.tcx.sess.opts.debugging_opts.span_free_formats { - p!(write("@{:?}", hir_id)); - } else { - p!(write("@{:?}", self.tcx.hir().span_by_hir_id(hir_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 = ", "; - } - } - - if self.tcx.sess.verbose() { - p!(write( - " closure_kind_ty={:?} closure_sig_ty={:?}", - substs.closure_kind_ty(did, self.tcx), - substs.closure_sig_ty(did, self.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) => { - match c.val { - ConstValue::Infer(..) => p!(write("_")), - ConstValue::Param(ParamConst { name, .. }) => - p!(write("{}", name)), - _ => p!(write("{}", c.unwrap_usize(self.tcx))), - } - } - } - p!(write("]")) - } - ty::Slice(ty) => { - p!(write("["), print(ty), write("]")) - } - } - - 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!(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() { - 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)); - 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!(self.generic_delimiters(|mut cx| { - cx = PrintCx::new(cx.tcx, 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!(self.print_def_path(def_id, None)); - } - - self.ok() - } - - pub fn pretty_fn_sig( - mut self, - inputs: &[Ty<'tcx>], - c_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(ty)); - for &ty in inputs { - p!(write(", "), print(ty)); - } - if c_variadic { - p!(write(", ...")); - } - } - p!(write(")")); - if !output.is_unit() { - 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 { +impl FmtPrinter<'_, 'gcx, 'tcx, F> { pub fn pretty_in_binder( - mut self: PrintCx<'_, '_, 'tcx, Self>, + mut self, value: &ty::Binder, ) -> Result - where T: Print<'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx> + where T: Print<'gcx, 'tcx, Self, Output = Self, Error = fmt::Error> + TypeFoldable<'tcx> { fn name_by_region_index(index: usize) -> InternedString { match index { @@ -1382,107 +1353,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): @@ -1505,13 +1463,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)) } @@ -1520,7 +1478,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)?; } } } @@ -1535,13 +1493,13 @@ define_print_and_forward_display! { } p!(write("fn")); - nest!(cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); + cx = cx.pretty_fn_sig(self.inputs(), self.c_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("_")), @@ -1554,7 +1512,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))?; } ConstValue<'tcx> { @@ -1569,7 +1527,7 @@ define_print_and_forward_display! { p!(write("{} : {}", self.val, self.ty)) } - ty::LazyConst<'tcx> { + &'tcx ty::LazyConst<'tcx> { match self { // FIXME(const_generics) this should print at least the type. ty::LazyConst::Unevaluated(..) => p!(write("_ : _")), @@ -1598,7 +1556,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 { @@ -1619,17 +1577,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 32a39c2eb88..4cbb315cefa 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -8,7 +8,7 @@ use crate::mir::ProjectionKind; use crate::mir::interpret::ConstValue; use crate::ty::{self, Lift, Ty, TyCtxt, ConstVid, InferConst}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use crate::ty::print::{FmtPrinter, PrintCx, Printer}; +use crate::ty::print::{FmtPrinter, Printer}; use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use smallvec::SmallVec; use crate::mir::interpret; @@ -34,8 +34,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(()) }) } @@ -43,8 +44,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(()) }) } @@ -333,6 +335,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 { @@ -429,6 +432,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 084b86b1eb4..d1fcc88e599 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, SubstsRef, UnpackedKind}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -223,10 +223,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(tcx)) - .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 { @@ -318,13 +319,17 @@ 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 = SymbolPath::from_interned(tcx.def_symbol_name(def_id), tcx); + let mut printer = SymbolPrinter { + tcx, + path: SymbolPath::from_interned(tcx.def_symbol_name(def_id)), + keep_within_component: false, + }; if instance.is_vtable_shim() { - let _ = buf.write_str("{{vtable-shim}}"); + let _ = printer.write_str("{{vtable-shim}}"); } - buf.finish(hash) + printer.path.finish(hash) } // Follow C++ namespace-mangling style, see @@ -344,33 +349,22 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance struct SymbolPath { result: String, temp_buf: String, - strict_naming: bool, - - // 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 { - fn new(tcx: TyCtxt<'_, '_, '_>) -> Self { + fn new() -> Self { let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), - strict_naming: tcx.has_strict_asm_symbol_naming(), - keep_within_component: false, }; result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested result } - fn from_interned(symbol: ty::SymbolName, tcx: TyCtxt<'_, '_, '_>) -> Self { + fn from_interned(symbol: ty::SymbolName) -> Self { let mut result = SymbolPath { result: String::with_capacity(64), temp_buf: String::with_capacity(16), - strict_naming: tcx.has_strict_asm_symbol_naming(), - keep_within_component: false, }; result.result.push_str(&symbol.as_str()); result @@ -398,11 +392,22 @@ 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 Printer for SymbolPath { +impl Printer<'tcx, 'tcx> for SymbolPrinter<'_, 'tcx> { type Error = fmt::Error; type Path = Self; @@ -410,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 { @@ -436,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; @@ -445,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 { @@ -480,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 { @@ -494,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() { @@ -532,52 +535,52 @@ 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) } } -impl fmt::Write for SymbolPath { +impl fmt::Write for SymbolPrinter<'_, '_> { fn write_str(&mut self, s: &str) -> fmt::Result { // Name sanitation. LLVM will happily accept identifiers with weird names, but // gas doesn't! @@ -586,45 +589,45 @@ impl fmt::Write for SymbolPath { // are replaced with '$' there. for c in s.chars() { - if self.temp_buf.is_empty() { + if self.path.temp_buf.is_empty() { match c { 'a'..='z' | 'A'..='Z' | '_' => {} _ => { // Underscore-qualify anything that didn't start as an ident. - self.temp_buf.push('_'); + self.path.temp_buf.push('_'); } } } match c { // Escape these with $ sequences - '@' => self.temp_buf.push_str("$SP$"), - '*' => self.temp_buf.push_str("$BP$"), - '&' => self.temp_buf.push_str("$RF$"), - '<' => self.temp_buf.push_str("$LT$"), - '>' => self.temp_buf.push_str("$GT$"), - '(' => self.temp_buf.push_str("$LP$"), - ')' => self.temp_buf.push_str("$RP$"), - ',' => self.temp_buf.push_str("$C$"), + '@' => self.path.temp_buf.push_str("$SP$"), + '*' => self.path.temp_buf.push_str("$BP$"), + '&' => self.path.temp_buf.push_str("$RF$"), + '<' => self.path.temp_buf.push_str("$LT$"), + '>' => self.path.temp_buf.push_str("$GT$"), + '(' => self.path.temp_buf.push_str("$LP$"), + ')' => self.path.temp_buf.push_str("$RP$"), + ',' => self.path.temp_buf.push_str("$C$"), - '-' | ':' | '.' if self.strict_naming => { + '-' | ':' | '.' if self.tcx.has_strict_asm_symbol_naming() => { // NVPTX doesn't support these characters in symbol names. - self.temp_buf.push('$') + self.path.temp_buf.push('$') } // '.' doesn't occur in types and functions, so reuse it // for ':' and '-' - '-' | ':' => self.temp_buf.push('.'), + '-' | ':' => self.path.temp_buf.push('.'), // These are legal symbols - 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.temp_buf.push(c), + 'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.path.temp_buf.push(c), _ => { - self.temp_buf.push('$'); + self.path.temp_buf.push('$'); for c in c.escape_unicode().skip(1) { match c { '{' => {} - '}' => self.temp_buf.push('$'), - c => self.temp_buf.push(c), + '}' => self.path.temp_buf.push('$'), + c => self.path.temp_buf.push(c), } } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index d7dd0313e94..86134647324 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -2326,7 +2326,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 @@ -2341,7 +2341,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 } @@ -2349,7 +2349,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, _, _) => { @@ -2366,7 +2366,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 6822de2bceb..53087eb1b1a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4223,13 +4223,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; @@ -4237,35 +4242,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 { @@ -4276,11 +4285,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 { @@ -4296,29 +4303,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 9df7c3f48fd4bb20da04624d19c8c1465d1117dc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 25 Jan 2019 12:28:43 +0200 Subject: [PATCH 64/70] 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 fff4ca822d2..bc98aee233a 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) => { @@ -470,9 +469,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)) @@ -494,7 +492,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); @@ -507,7 +505,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) => { @@ -608,7 +606,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()); @@ -693,7 +691,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; @@ -703,7 +701,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; } } @@ -742,13 +740,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; @@ -776,7 +774,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) @@ -1478,7 +1476,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)); } } } @@ -1492,8 +1490,7 @@ define_print_and_forward_display! { p!(write("extern {} ", self.abi)); } - p!(write("fn")); - cx = cx.pretty_fn_sig(self.inputs(), self.c_variadic, self.output())?; + p!(write("fn"), pretty_fn_sig(self.inputs(), self.c_variadic, self.output())); } ty::InferTy { @@ -1512,7 +1509,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))); } ConstValue<'tcx> { @@ -1556,7 +1553,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 { @@ -1576,19 +1573,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 8619edede1496a8d9c4131f9cb2079e71dccd5fb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Jan 2019 07:21:11 +0200 Subject: [PATCH 65/70] rustc: slice substs in ty::print instead of passing the full ones. --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/print/mod.rs | 92 +++++++++++----------- src/librustc/ty/print/pretty.rs | 49 +++++------- src/librustc/ty/structural_impls.rs | 4 +- src/librustc_codegen_utils/symbol_names.rs | 4 +- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/test/ui/namespace/namespace-mix.stderr | 4 +- 10 files changed, 77 insertions(+), 86 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 52b42881038..5026074f5e8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -533,7 +533,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/mir/mod.rs b/src/librustc/mir/mod.rs index 3218f8ea5de..718b506d051 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2410,7 +2410,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 89d956c8bfa..995e85fc5f4 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -179,7 +179,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 ad17a8114ca..c3f4a26a57e 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,7 +1,7 @@ use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; -use crate::ty::subst::{Kind, Subst, SubstsRef}; +use crate::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>, + substs: &'tcx [Kind<'tcx>], ) -> Result { self.default_print_def_path(def_id, substs) } fn print_impl_path( self, impl_def_id: DefId, - substs: Option>, + substs: &'tcx [Kind<'tcx>], self_ty: Ty<'tcx>, trait_ref: Option>, ) -> Result { @@ -90,7 +90,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn default_print_def_path( self, def_id: DefId, - substs: Option>, + 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 +103,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), + // Closures' own generics are only captures, don't print them. + DefPathData::ClosureExpr => {} - _ => { - cx.path_append( - print_parent_path, - &key.disambiguated_data.data.as_interned_str().as_str(), - ) + // 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.data.as_interned_str().as_str(), + ) } } } @@ -165,7 +165,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn generic_args_to_print( &self, generics: &'tcx ty::Generics, - substs: SubstsRef<'tcx>, + substs: &'tcx [Kind<'tcx>], ) -> &'tcx [Kind<'tcx>] { let mut own_params = generics.parent_count..generics.count(); @@ -193,7 +193,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { fn default_print_impl_path( self, impl_def_id: DefId, - _substs: Option>, + _substs: &'tcx [Kind<'tcx>], self_ty: Ty<'tcx>, impl_trait_ref: Option>, ) -> Result { @@ -220,7 +220,7 @@ 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, &[]), self_ty, impl_trait_ref, ) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index bc98aee233a..54ca63b457a 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -5,7 +5,7 @@ use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; use crate::middle::region; use crate::ty::{self, DefIdTree, ParamConst, Ty, TyCtxt, TypeFoldable}; -use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; +use crate::ty::subst::{Kind, Subst, UnpackedKind}; use crate::mir::interpret::ConstValue; 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>, + 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)); @@ -469,8 +469,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 +491,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 +504,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) => { @@ -691,7 +690,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; @@ -774,7 +773,7 @@ pub trait PrettyPrinter<'gcx: 'tcx, 'tcx>: } first = false; - p!(print_def_path(def_id, None)); + p!(print_def_path(def_id, &[])); } Ok(self) @@ -879,7 +878,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 } } @@ -905,21 +904,13 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { fn print_def_path( mut self, def_id: DefId, - substs: Option>, + 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, } } @@ -942,7 +933,7 @@ impl Printer<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> { 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), + |cx| cx.print_def_path(parent_def_id, &[]), &format!("", span), ); } @@ -1073,7 +1064,7 @@ impl PrettyPrinter<'gcx, 'tcx> for FmtPrinter<'_, 'gcx, 'tcx, F> fn print_value_path( mut self, def_id: DefId, - substs: Option>, + 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)?; @@ -1476,7 +1467,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, &[])); } } } @@ -1509,7 +1500,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)); } ConstValue<'tcx> { @@ -1553,7 +1544,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 { @@ -1574,17 +1565,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 4cbb315cefa..6aabdf1e566 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -36,7 +36,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(()) }) } @@ -46,7 +46,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 d1fcc88e599..262ba8a1c74 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -227,7 +227,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), } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 0f0811b562e..c4e371d5afe 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, DefIdTree, TyCtxt}; +use rustc::ty::{self, TyCtxt}; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::bit_set::BitSet; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 53087eb1b1a..da73eb0cda5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4322,7 +4322,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/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index 22c871dd3c0..99fa3b96794 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); - | ^^^^^ 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 a54a41ce47c149fd6587182a4ab87a146844f939 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 3 Feb 2019 12:59:37 +0200 Subject: [PATCH 66/70] rustc: provide DisambiguatedDefPathData in ty::print. --- src/librustc/hir/map/definitions.rs | 6 +- src/librustc/infer/error_reporting/mod.rs | 6 +- src/librustc/ty/print/mod.rs | 12 ++- src/librustc/ty/print/pretty.rs | 88 +++++++++++++------ src/librustc_codegen_utils/symbol_names.rs | 26 +++++- src/librustdoc/clean/mod.rs | 6 +- 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 | 2 +- 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 +- 16 files changed, 127 insertions(+), 71 deletions(-) diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index f454d691d41..dca4ce4aef8 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -679,13 +679,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 5026074f5e8..2810b5a8e6a 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -445,6 +445,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; @@ -504,6 +505,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 { @@ -512,10 +514,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( diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index c3f4a26a57e..99b83deab8b 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -1,4 +1,4 @@ -use crate::hir::map::DefPathData; +use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::hir::def_id::{CrateNum, DefId}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::ty::subst::{Kind, Subst}; @@ -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, @@ -156,7 +157,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { } else { cx.print_def_path(parent_def_id, parent_substs) }, - &key.disambiguated_data.data.as_interned_str().as_str(), + &key.disambiguated_data, ) } } @@ -200,12 +201,14 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { 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), @@ -221,6 +224,7 @@ pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { // the module more clearly. self.path_append_impl( |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 54ca63b457a..258903e1f10 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1,6 +1,6 @@ use crate::hir; use crate::hir::def::Namespace; -use crate::hir::map::DefPathData; +use crate::hir::map::{DefPathData, DisambiguatedDefPathData}; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; use crate::middle::region; @@ -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( @@ -932,10 +935,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, &[]), - &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); } } @@ -995,6 +1006,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 { @@ -1012,17 +1024,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; } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 262ba8a1c74..0fa935199f9 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -90,7 +90,7 @@ 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; @@ -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 da73eb0cda5..c80fd8fcd81 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, InternalSubsts, SubstsRef}; use rustc::ty::{self, DefIdTree, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::fold::TypeFolder; @@ -4288,6 +4289,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 { @@ -4306,10 +4308,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( diff --git a/src/test/mir-opt/retag.rs b/src/test/mir-opt/retag.rs index cdf63556737..3b333b5431c 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@HirId { owner: DefIndex(0:7), local_id: 70 }], _2: &i32) -> &i32 { +// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(0:7), local_id: 70 }], _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 8f8eb38e938..3762f5e3d6a 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 033d6eebbb2..26271395005 100644 --- a/src/test/ui/deprecation/deprecation-lint.rs +++ b/src/test/ui/deprecation/deprecation-lint.rs @@ -314,7 +314,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 50cbe3846bb..ffbcb259754 100644 --- a/src/test/ui/deprecation/deprecation-lint.stderr +++ b/src/test/ui/deprecation/deprecation-lint.stderr @@ -298,7 +298,7 @@ error: use of deprecated item 'this_crate::Trait::trait_deprecated_text': text LL | ::trait_deprecated_text(&foo); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -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:317:13 | LL | bar(); diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index b936fed85f4..4e79dfc3f7c 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 c993588f553..da3e2e763af 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; | ^^^ | = 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 5fa82f8b786..43effc0b3b9 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, | ^^^^^^^^^^^^^ | - = 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, diff --git a/src/test/ui/issues/issue-23302-2.stderr b/src/test/ui/issues/issue-23302-2.stderr index 5b77baed73c..707d4fa7ed3 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, | ^^^^^^^^^^^^^ | - = 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, diff --git a/src/test/ui/issues/issue-36163.stderr b/src/test/ui/issues/issue-36163.stderr index 94de4c76927..4c3f726180d 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, @@ -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, diff --git a/src/test/ui/issues/issue-44415.stderr b/src/test/ui/issues/issue-44415.stderr index 3f377fd27e7..df8e804c87a 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 | From 22d6c55cdf1772b0cfbed371dca16b3f3769117f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Mon, 4 Feb 2019 00:48:16 +0200 Subject: [PATCH 67/70] rustc: print ExistentialProjection with spaces around `=`, e.g. `dyn Foo`. --- src/librustc/ty/print/pretty.rs | 2 +- src/test/ui/associated-types/associated-types-eq-3.stderr | 2 +- .../associated-types-overridden-binding-2.stderr | 2 +- src/test/ui/confuse-field-and-method/issue-2392.stderr | 2 +- src/test/ui/issues/issue-20605.stderr | 4 ++-- src/test/ui/issues/issue-22312.stderr | 2 +- src/test/ui/issues/issue-55796.stderr | 8 ++++---- src/test/ui/retslot-cast.stderr | 6 +++--- .../typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr | 2 +- .../unboxed-closures/unboxed-closure-sugar-default.stderr | 4 ++-- .../unboxed-closures/unboxed-closure-sugar-equiv.stderr | 4 ++-- .../ui/underscore-lifetime/dyn-trait-underscore.stderr | 4 ++-- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 258903e1f10..fa57e0b9674 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -1489,7 +1489,7 @@ 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)) + p!(write("{} = ", name), print(self.ty)) } ty::ExistentialPredicate<'tcx> { diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr index c1a8e2002be..31d2c5f318e 100644 --- a/src/test/ui/associated-types/associated-types-eq-3.stderr +++ b/src/test/ui/associated-types/associated-types-eq-3.stderr @@ -29,7 +29,7 @@ LL | baz(&a); | = note: expected type `usize` found type `Bar` - = note: required for the cast to the object type `dyn Foo` + = note: required for the cast to the object type `dyn Foo` error: aborting due to 3 previous errors diff --git a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr index 8c0e5570d19..ad0b6515490 100644 --- a/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr +++ b/src/test/ui/associated-types/associated-types-overridden-binding-2.stderr @@ -6,7 +6,7 @@ LL | let _: &I32Iterator = &vec![42].into_iter(); | = note: expected type `u32` found type `i32` - = note: required for the cast to the object type `dyn I32Iterator` + = note: required for the cast to the object type `dyn I32Iterator` error: aborting due to previous error diff --git a/src/test/ui/confuse-field-and-method/issue-2392.stderr b/src/test/ui/confuse-field-and-method/issue-2392.stderr index 7cd1941d80e..456a4c18e2b 100644 --- a/src/test/ui/confuse-field-and-method/issue-2392.stderr +++ b/src/test/ui/confuse-field-and-method/issue-2392.stderr @@ -75,7 +75,7 @@ LL | w.wrap.not_closure(); | = help: did you mean to write `w.wrap.not_closure` instead of `w.wrap.not_closure(...)`? -error[E0599]: no method named `closure` found for type `Obj + 'static)>>` in the current scope +error[E0599]: no method named `closure` found for type `Obj + 'static)>>` in the current scope --> $DIR/issue-2392.rs:62:24 | LL | struct Obj where F: FnOnce() -> u32 { diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr index f779fe51bf2..89df58dd2dc 100644 --- a/src/test/ui/issues/issue-20605.stderr +++ b/src/test/ui/issues/issue-20605.stderr @@ -1,10 +1,10 @@ -error[E0277]: the size for values of type `dyn std::iter::Iterator` cannot be known at compilation time +error[E0277]: the size for values of type `dyn std::iter::Iterator` cannot be known at compilation time --> $DIR/issue-20605.rs:2:17 | LL | for item in *things { *item = 0 } | ^^^^^^^ doesn't have a size known at compile-time | - = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator` + = help: the trait `std::marker::Sized` is not implemented for `dyn std::iter::Iterator` = note: to learn more, visit = note: required by `std::iter::IntoIterator::into_iter` diff --git a/src/test/ui/issues/issue-22312.stderr b/src/test/ui/issues/issue-22312.stderr index d8987a37f7e..6a012b214c5 100644 --- a/src/test/ui/issues/issue-22312.stderr +++ b/src/test/ui/issues/issue-22312.stderr @@ -1,4 +1,4 @@ -error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index>::Output>` +error[E0605]: non-primitive cast: `Self` as `&dyn std::ops::Index>::Output>` --> $DIR/issue-22312.rs:11:24 | LL | let indexer = &(*self as &Index>::Output>); diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr index c05f8b85d0e..7cf597d3a98 100644 --- a/src/test/ui/issues/issue-55796.stderr +++ b/src/test/ui/issues/issue-55796.stderr @@ -16,8 +16,8 @@ LL | Box::new(self.out_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: - expected std::boxed::Box<(dyn std::iter::Iterator>::Node> + 'static)> - found std::boxed::Box>::Node>> + expected std::boxed::Box<(dyn std::iter::Iterator>::Node> + 'static)> + found std::boxed::Box>::Node>> error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements --> $DIR/issue-55796.rs:21:9 @@ -37,8 +37,8 @@ LL | Box::new(self.in_edges(u).map(|e| e.target())) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: - expected std::boxed::Box<(dyn std::iter::Iterator>::Node> + 'static)> - found std::boxed::Box>::Node>> + expected std::boxed::Box<(dyn std::iter::Iterator>::Node> + 'static)> + found std::boxed::Box>::Node>> error: aborting due to 2 previous errors diff --git a/src/test/ui/retslot-cast.stderr b/src/test/ui/retslot-cast.stderr index 3c58285bdb3..a1169910ae7 100644 --- a/src/test/ui/retslot-cast.stderr +++ b/src/test/ui/retslot-cast.stderr @@ -2,10 +2,10 @@ error[E0308]: mismatched types --> $DIR/retslot-cast.rs:13:5 | LL | inner(x) - | ^^^^^^^^ expected trait `std::iter::Iterator`, found trait `std::iter::Iterator + std::marker::Send` + | ^^^^^^^^ expected trait `std::iter::Iterator`, found trait `std::iter::Iterator + std::marker::Send` | - = note: expected type `std::option::Option<&dyn std::iter::Iterator>` - found type `std::option::Option<&dyn std::iter::Iterator + std::marker::Send>` + = note: expected type `std::option::Option<&dyn std::iter::Iterator>` + found type `std::option::Option<&dyn std::iter::Iterator + std::marker::Send>` error: aborting due to previous error diff --git a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr index f1118709962..d41086186f8 100644 --- a/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr +++ b/src/test/ui/typeck/issue-57673-ice-on-deref-of-boxed-trait.stderr @@ -7,7 +7,7 @@ LL | *x | ^^ expected (), found trait std::iter::Iterator | = note: expected type `()` - found type `(dyn std::iter::Iterator + 'static)` + found type `(dyn std::iter::Iterator + 'static)` error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr index 508c2f780b9..ce90f5b9d24 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-default.stderr @@ -1,8 +1,8 @@ -error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output=()>: Eq>` is not satisfied +error[E0277]: the trait bound `dyn Foo<(isize,), isize, Output = ()>: Eq>` is not satisfied --> $DIR/unboxed-closure-sugar-default.rs:21:5 | LL | eq::< Foo<(isize,),isize,Output=()>, Foo(isize) >(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq>` is not implemented for `dyn Foo<(isize,), isize, Output=()>` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq>` is not implemented for `dyn Foo<(isize,), isize, Output = ()>` | note: required by `eq` --> $DIR/unboxed-closure-sugar-default.rs:14:1 diff --git a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr index 071ba2792b0..857a32ca69e 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-sugar-equiv.stderr @@ -1,9 +1,9 @@ -error[E0277]: the trait bound `dyn Foo<(char,), Output=()>: Eq>` is not satisfied +error[E0277]: the trait bound `dyn Foo<(char,), Output = ()>: Eq>` is not satisfied --> $DIR/unboxed-closure-sugar-equiv.rs:43:5 | LL | / eq::< Foo<(),Output=()>, LL | | Foo(char) >(); - | |___________________________________________________________________^ the trait `Eq>` is not implemented for `dyn Foo<(char,), Output=()>` + | |___________________________________________________________________^ the trait `Eq>` is not implemented for `dyn Foo<(char,), Output = ()>` | note: required by `eq` --> $DIR/unboxed-closure-sugar-equiv.rs:16:1 diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr index 69a9fd7a60c..d0475bf08c3 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr @@ -19,8 +19,8 @@ LL | Box::new(items.iter()) | ^^^^^ = note: but, the lifetime must be valid for the static lifetime... = note: ...so that the expression is assignable: - expected std::boxed::Box<(dyn std::iter::Iterator + 'static)> - found std::boxed::Box> + expected std::boxed::Box<(dyn std::iter::Iterator + 'static)> + found std::boxed::Box> error: aborting due to previous error From 4653ae1e3e9ce3613844987b43431b35302fb34a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 7 Feb 2019 15:02:14 +0100 Subject: [PATCH 68/70] we can now print on entering/leaving the topmost frame, and make sure it stays that way --- src/librustc_mir/const_eval.rs | 17 +++++++++-------- src/librustc_mir/interpret/eval_context.rs | 12 ++++-------- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index e6005142b85..43f019019f7 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -602,14 +602,15 @@ pub fn const_eval_raw_provider<'a, 'tcx>( other => return other, } } - // the first trace is for replicating an ice - // There's no tracking issue, but the next two lines concatenated link to the discussion on - // zulip. It's not really possible to test this, because it doesn't show up in diagnostics - // or MIR. - // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ - // subject/anon_const_instance_printing/near/135980032 - trace!("const eval: {}", key.value.instance); - trace!("const eval: {:?}", key); + if cfg!(debug_assertions) { + // Make sure we format the instance even if we do not print it. + // This serves as a regression test against an ICE on printing. + // The next two lines concatenated contain some discussion: + // https://rust-lang.zulipchat.com/#narrow/stream/146212-t-compiler.2Fconst-eval/ + // subject/anon_const_instance_printing/near/135980032 + let instance = key.value.instance.to_string(); + trace!("const eval: {:?} ({})", key, instance); + } let cid = key.value; let def_id = cid.instance.def.def_id(); diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index d92ab0c5179..e81d0a56b2b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -450,7 +450,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc return_place: Option>, return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { - if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... + if self.stack.len() > 0 { info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation += 1; @@ -525,9 +525,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc self.frame_mut().locals = locals; } - if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); - } + info!("ENTERING({}) {}", self.cur_frame(), self.frame().instance); if self.stack.len() > self.tcx.sess.const_eval_stack_frame_limit { err!(StackFrameLimitReached) @@ -537,9 +535,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc } pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { - if self.stack.len() > 1 { // FIXME no check should be needed, but some instances ICE - info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); - } + info!("LEAVING({}) {}", self.cur_frame(), self.frame().instance); ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect( "tried to pop a stack frame, but there were none", @@ -591,7 +587,7 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc StackPopCleanup::None { .. } => {} } - if self.stack.len() > 1 { // FIXME should be "> 0", printing topmost frame crashes rustc... + if self.stack.len() > 0 { info!("CONTINUING({}) {}", self.cur_frame(), self.frame().instance); } From 0ee059d5a08662b22250e28dbd5d5a9502303afb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 14 Mar 2019 19:47:24 +0200 Subject: [PATCH 69/70] Fix rebase fallout and address some review comments. --- src/librustc/ty/print/mod.rs | 8 ++++++++ src/librustc/ty/structural_impls.rs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 99b83deab8b..ef30a4032d8 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -16,6 +16,14 @@ pub trait Print<'gcx, 'tcx, P> { fn print(&self, cx: P) -> Result; } +/// Interface for outputting user-facing "type-system entities" +/// (paths, types, lifetimes, constants, etc.) as a side-effect +/// (e.g. formatting, like `PrettyPrinter` implementors do) or by +/// constructing some alternative representation (e.g. an AST), +/// which the associated types allow passing through the methods. +/// +/// For pretty-printing/formatting in particular, see `PrettyPrinter`. +// FIXME(eddyb) find a better name, this is more general than "printing". pub trait Printer<'gcx: 'tcx, 'tcx>: Sized { type Error; diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 6aabdf1e566..ecfb034e4f2 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -225,7 +225,7 @@ impl fmt::Debug for ty::FloatVarValue { 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 + // FIXME(#59188) 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) From dbf19c3975a014861535b775b2fb7cd71e6c5042 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 15 Mar 2019 13:24:34 +0200 Subject: [PATCH 70/70] rustbuild: remove obsolete fulldeps behavior from src/test/pretty tests, and enable them by default. --- src/bootstrap/mk/Makefile.in | 1 - src/bootstrap/test.rs | 12 +++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 1c27cf3909b..07be27c2f5a 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -48,7 +48,6 @@ check: $(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS) check-aux: $(Q)$(BOOTSTRAP) test \ - src/test/pretty \ src/test/run-pass/pretty \ src/test/run-fail/pretty \ src/test/run-pass-valgrind/pretty \ diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index b7323b2eadc..81e09bc878a 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -897,12 +897,10 @@ host_test!(Rustdoc { suite: "rustdoc" }); -test!(Pretty { +host_test!(Pretty { path: "src/test/pretty", mode: "pretty", - suite: "pretty", - default: false, - host: true + suite: "pretty" }); test!(RunPassPretty { path: "src/test/run-pass/pretty", @@ -993,11 +991,7 @@ impl Step for Compiletest { }); } - if suite.ends_with("fulldeps") || - // FIXME: Does pretty need librustc compiled? Note that there are - // fulldeps test suites with mode = pretty as well. - mode == "pretty" - { + if suite.ends_with("fulldeps") { builder.ensure(compile::Rustc { compiler, target }); }

(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool { if cx.is_verbose { return true; } @@ -1044,28 +1037,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)) } } } @@ -1093,7 +1086,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"))) } }*/ @@ -1109,136 +1102,131 @@ 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, subst::InternalSubsts::empty(), iter::empty()) + cx.parameterized(def_id, subst::InternalSubsts::empty(), iter::empty()) } - Projection(ref data) => data.print(f, cx), + 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(()); } @@ -1248,7 +1236,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. @@ -1257,35 +1245,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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { - write!(f, "@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))?; + print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; let mut sep = " "; cx.tcx.with_freevars(hir_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())), @@ -1297,35 +1286,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(hir_id) = cx.tcx.hir().as_local_hir_id(did) { if cx.tcx.sess.opts.debugging_opts.span_free_formats { - write!(f, "@{:?}", hir_id)?; + print!(cx, write("@{:?}", hir_id))?; } else { - write!(f, "@{:?}", cx.tcx.hir().span_by_hir_id(hir_id))?; + print!(cx, write("@{:?}", cx.tcx.hir().span_by_hir_id(hir_id)))?; } let mut sep = " "; cx.tcx.with_freevars(hir_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())), @@ -1337,10 +1327,10 @@ 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 = ", "; @@ -1348,93 +1338,93 @@ define_print! { } if cx.is_verbose { - write!( - f, + print!(cx, write( " closure_kind_ty={:?} closure_sig_ty={:?}", substs.closure_kind_ty(did, cx.tcx), - substs.closure_sig_ty(did, cx.tcx), - )?; + substs.closure_sig_ty(did, cx.tcx) + ))?; } - 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) => { match c.val { - ConstValue::Infer(..) => write!(f, "_")?, + ConstValue::Infer(..) => print!(cx, write("_"))?, ConstValue::Param(ParamConst { name, .. }) => - write!(f, "{}", name)?, - _ => write!(f, "{}", c.unwrap_usize(cx.tcx))?, + print!(cx, write("{}", name))?, + _ => 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! { - ('tcx) ConstValue<'tcx>, (self, f, cx) { + ('tcx) ConstValue<'tcx>, (self, cx) { display { match self { - ConstValue::Infer(..) => write!(f, "_"), - ConstValue::Param(ParamConst { name, .. }) => write!(f, "{}", name), - _ => write!(f, "{:?}", self), + ConstValue::Infer(..) => print!(cx, write("_")), + ConstValue::Param(ParamConst { name, .. }) => print!(cx, write("{}", name)), + _ => print!(cx, write("{:?}", self)), } } } } define_print! { - ('tcx) ty::Const<'tcx>, (self, f, cx) { + ('tcx) ty::Const<'tcx>, (self, cx) { display { - write!(f, "{} : {}", self.val, self.ty) + print!(cx, write("{} : {}", self.val, self.ty)) } } } define_print! { - ('tcx) ty::LazyConst<'tcx>, (self, f, cx) { + ('tcx) ty::LazyConst<'tcx>, (self, cx) { display { match self { - ty::LazyConst::Unevaluated(..) => write!(f, "_ : _"), - ty::LazyConst::Evaluated(c) => write!(f, "{}", c), + // FIXME(const_generics) this should print at least the type. + ty::LazyConst::Unevaluated(..) => print!(cx, write("_ : _")), + ty::LazyConst::Evaluated(c) => print!(cx, write("{}", c)), } } } } 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)) } } } define_print! { - () ty::ParamConst, (self, f, cx) { + () ty::ParamConst, (self, cx) { display { - write!(f, "{}", self.name) + print!(cx, write("{}", self.name)) } debug { - write!(f, "{}/#{}", self.name, self.index) + print!(cx, write("{}/#{}", self.name, self.index)) } } } @@ -1445,37 +1435,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(", "), @@ -1483,71 +1473,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)) } } } @@ -1555,19 +1547,19 @@ 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::Const(ct) => print!(f, cx, print(ct)), + UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), + UnpackedKind::Type(ty) => print!(cx, print(ty)), + UnpackedKind::Const(ct) => print!(cx, print(ct)), } } debug { match self.unpack() { - UnpackedKind::Lifetime(lt) => print!(f, cx, print(lt)), - UnpackedKind::Type(ty) => print!(f, cx, print(ty)), - UnpackedKind::Const(ct) => print!(f, cx, print(ct)), + UnpackedKind::Lifetime(lt) => print!(cx, print(lt)), + UnpackedKind::Type(ty) => print!(cx, print(ty)), + UnpackedKind::Const(ct) => print!(cx, print(ct)), } } } diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs index 2b70141894b..466cf40a157 100644 --- a/src/librustc_codegen_utils/lib.rs +++ b/src/librustc_codegen_utils/lib.rs @@ -4,6 +4,7 @@ #![doc(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 56ef15b12a0..6bd9b159775 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -225,8 +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(|| { - 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() }) } @@ -401,17 +400,21 @@ struct SymbolPathPrinter; impl ItemPathPrinter for SymbolPathPrinter { type Path = SymbolPath; - fn path_crate(cx: &mut PrintCx<'_, '_, '_>, cnum: CrateNum) -> Self::Path { - let mut path = SymbolPath::new(cx.tcx); - path.push(&cx.tcx.original_crate_name(cnum).as_str()); + fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path { + let mut path = SymbolPath::new(self.tcx); + path.push(&self.tcx.original_crate_name(cnum).as_str()); path } - fn path_impl(cx: &mut PrintCx<'_, '_, '_>, text: &str) -> Self::Path { - let mut path = SymbolPath::new(cx.tcx); + fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path { + let mut path = SymbolPath::new(self.tcx); 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 ed7f1bbe7e6..d321697f713 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4233,20 +4233,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(_: &mut PrintCx<'_, '_, '_>, 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 f11e268b909..58ba827ee05 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 238616813974babc53cb85aaa8e102df119d7f0f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Dec 2018 15:12:48 +0200 Subject: [PATCH 21/70] 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 | 79 +++++++++++++++------------ 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, 54 insertions(+), 42 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 7d2050a7c68..ec42809ff65 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 crate::hir::def::CtorKind; +use crate::hir::def::{CtorKind, Namespace}; use crate::hir::def_id::DefId; use crate::hir::{self, HirId, InlineAsm}; use crate::mir::interpret::{ConstValue, EvalErrorKind, Scalar}; @@ -2405,7 +2405,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 0a49dea7ec1..fd0b97e98a3 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,4 +1,5 @@ use crate::hir::Unsafety; +use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::ty::{self, Ty, PolyFnSig, TypeFoldable, SubstsRef, TyCtxt}; use crate::traits; @@ -175,7 +176,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 780ff8a61e4..94560606cad 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,3 +1,4 @@ +use crate::hir::def::Namespace; use crate::hir::def_id::DefId; use crate::hir::map::definitions::DefPathData; use crate::middle::region; @@ -285,26 +286,12 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { fn parameterized( &mut self, - mut def_id: DefId, + def_id: DefId, substs: SubstsRef<'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..]; @@ -496,10 +490,15 @@ impl PrintCx<'a, 'gcx, 'tcx, FmtPrinter> { } } -pub fn parameterized(f: &mut F, did: DefId, substs: SubstsRef<'_>) -> fmt::Result { +pub fn parameterized( + f: &mut F, + did: DefId, + substs: SubstsRef<'_>, + 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()) }) } @@ -538,6 +537,7 @@ define_print! { cx.parameterized( principal.def_id, principal.substs, + Namespace::TypeNS, self.projection_bounds(), )?; } @@ -663,7 +663,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) @@ -1112,12 +1112,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(">") + ) } } } @@ -1163,7 +1167,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) => { @@ -1185,7 +1189,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 { @@ -1199,7 +1205,12 @@ define_print! { Ok(()) } Foreign(def_id) => { - cx.parameterized(def_id, subst::InternalSubsts::empty(), iter::empty()) + cx.parameterized( + def_id, + subst::InternalSubsts::empty(), + Namespace::TypeNS, + iter::empty(), + ) } Projection(ref data) => data.print(cx), UnnormalizedProjection(ref data) => { @@ -1481,7 +1492,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()) } } } @@ -1518,7 +1529,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 1bbbe67a12c..3ce43cc4a22 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 ab6de71d289..9eeef8570a3 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); // _3 = discriminant(_2); // switchInt(move _3) -> [0isize: bb4, 1isize: bb2, otherwise: bb7]; @@ -111,7 +111,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); // _3 = discriminant(_2); // switchInt(move _3) -> [0isize: bb3, 1isize: bb2, otherwise: bb7]; @@ -180,7 +180,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); // _3 = discriminant(_2); // switchInt(move _3) -> [1isize: bb2, otherwise: bb3]; diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index a5d6ced2b17..9a22f57116e 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 ed2be6fa89428b6c0a43e41a8906d29bc78f62d0 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 12 Dec 2018 18:28:29 +0200 Subject: [PATCH 22/70] 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 0612401ca25..87859ac00c3 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. @@ -132,18 +132,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 @@ -210,19 +198,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 hir_id = self.tcx.hir().as_local_hir_id(impl_def_id).unwrap(); - let item = self.tcx.hir().expect_item_by_hir_id(hir_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> { @@ -291,6 +266,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; @@ -470,6 +448,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 3e1cef700753ef4802c244f7e48d59de5d4324dd Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 05:01:06 +0200 Subject: [PATCH 23/70] rustc: pass Option<&Substs> and Namespace around in ty::item_path. --- src/librustc/ty/item_path.rs | 137 +++++++++++++----- src/librustc/util/ppaux.rs | 20 +-- src/librustc_codegen_utils/symbol_names.rs | 5 +- src/librustdoc/clean/mod.rs | 5 +- src/test/pretty/issue-4264.pp | 34 ++--- src/test/ui/bad/bad-sized.stderr | 2 +- ...gate-unleash_the_miri_inside_of_you.stderr | 2 +- src/test/ui/hygiene/impl_items.rs | 2 +- src/test/ui/hygiene/impl_items.stderr | 2 +- src/test/ui/issues/issue-17651.stderr | 2 +- src/test/ui/issues/issue-22638.rs | 2 +- src/test/ui/issues/issue-22638.stderr | 2 +- 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 | 2 +- 26 files changed, 159 insertions(+), 94 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 87859ac00c3..d9a8deb80e4 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -1,8 +1,10 @@ +use crate::hir::def::Namespace; use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; +use crate::ty::print::PrintCx; +use crate::ty::subst::{Subst, Substs}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; -use ty::print::PrintCx; 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 `DefId`. 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. @@ -117,18 +155,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(); @@ -137,13 +180,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), @@ -153,7 +202,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 { @@ -174,15 +223,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(); + crate::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 | @@ -263,11 +311,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; @@ -312,6 +370,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); @@ -343,7 +402,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) }; @@ -376,7 +435,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; @@ -444,11 +503,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() || { @@ -463,12 +532,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 94560606cad..092255129f4 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. - 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)))?; + // 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)))?; - 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(">"))?; - } + // For impls, the above call already prints relevant generics args. + if let DefPathData::Impl = key.disambiguated_data.data { 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 6bd9b159775..a7771f3da18 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; @@ -225,7 +226,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 d321697f713..6714866369e 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::{InternalSubsts, SubstsRef}; use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; @@ -4249,7 +4249,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/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index b529beba783..ad663412e77 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -32,27 +32,27 @@ pub fn bar() ({ (($crate::fmt::format as for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((<$crate::fmt::Arguments>::new_v1 as - fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments<'_>::new_v1})((&([("test" + fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test" + as + &'static str)] as - &'static str)] + [&str; 1]) as - [&str; 1]) - as - &[&str; 1]), - (&(match (() + &[&str; 1]), + (&(match (() + as + ()) + { + () + => + ([] as - ()) - { - () - => - ([] - as - [std::fmt::ArgumentV1<'_>; 0]), - } + [std::fmt::ArgumentV1<'_>; 0]), + } + as + [std::fmt::ArgumentV1<'_>; 0]) as - [std::fmt::ArgumentV1<'_>; 0]) - as - &[std::fmt::ArgumentV1<'_>; 0])) + &[std::fmt::ArgumentV1<'_>; 0])) as std::fmt::Arguments<'_>)) as std::string::String); diff --git a/src/test/ui/bad/bad-sized.stderr b/src/test/ui/bad/bad-sized.stderr index 9565888dcc0..51b84745552 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/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr index 1fe3d33322f..7ede44c65b8 100644 --- a/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr +++ b/src/test/ui/consts/miri_unleashed/feature-gate-unleash_the_miri_inside_of_you.stderr @@ -4,7 +4,7 @@ error[E0493]: destructors cannot be evaluated at compile-time LL | const F: u32 = (U::X, 42).1; | ^^^^^^^^^^ constants cannot evaluate destructors -error: `>::new` is not yet stable as a const fn +error: `std::vec::Vec::::new` is not yet stable as a const fn --> $DIR/feature-gate-unleash_the_miri_inside_of_you.rs:18:25 | LL | const X: Vec = Vec::new(); diff --git a/src/test/ui/hygiene/impl_items.rs b/src/test/ui/hygiene/impl_items.rs index d628573d517..37794c6e077 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 0a273bc98ff..418c2c73ba1 100644 --- a/src/test/ui/hygiene/impl_items.stderr +++ b/src/test/ui/hygiene/impl_items.stderr @@ -1,4 +1,4 @@ -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(); diff --git a/src/test/ui/issues/issue-17651.stderr b/src/test/ui/issues/issue-17651.stderr index 72c40ff4b3a..ce9af1524b0 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 ff58c7aaced..fab24404eba 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 65483abe5c7..aff968f3618 100644 --- a/src/test/ui/issues/issue-22638.stderr +++ b/src/test/ui/issues/issue-22638.stderr @@ -1,4 +1,4 @@ -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) { diff --git a/src/test/ui/issues/issue-24322.stderr b/src/test/ui/issues/issue-24322.stderr index b284c8cf117..def373cf2c0 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; | ^^^^^^^^ 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 8062045a6c0..1cd3f84f7a2 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 67f188e0588..3beb7289788 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 24b31f43a85..c5432190412 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) { diff --git a/src/test/ui/issues/issue-39559-2.stderr b/src/test/ui/issues/issue-39559-2.stderr index ca2f2a5ba28..700dbe36474 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 b6fd22fa669..c3ae920238f 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 69be9d2cea6..6471a7914e1 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 d885407a1cd..39f2e5d4af2 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 f8b757ea098..61cd8476297 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 d98cf5991ef..d9bb421b53f 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 baa98292b67..4d40b6b7cab 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -151,7 +151,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 6315ec2e512..926b098040f 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:: => {} | ^^^^^^^^^^^^^^^^^^^^^ 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 97169c33b8c..69cd49e3951 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 e4fefeb601f..4041eb6b0ba 100644 --- a/src/test/ui/symbol-names/impl1.stderr +++ b/src/test/ui/symbol-names/impl1.stderr @@ -1,4 +1,4 @@ -error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E) +error: symbol-name(_ZN15impl1..foo..Foo3bar17hc487d6ec13fe9124E) --> $DIR/impl1.rs:8:9 | LL | #[rustc_symbol_name] From 6ca6c1a6cc2b097c93eee30f0ba5371423e9966f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 06:39:33 +0200 Subject: [PATCH 24/70] rustc_mir: adjust the type_length_limit diagnostic to be more useful. --- src/librustc/ty/item_path.rs | 16 ++++---- 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.rs | 2 + src/test/ui/type_length_limit.stderr | 8 +++- 6 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index d9a8deb80e4..288894f235b 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -3,7 +3,7 @@ use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::ty::print::PrintCx; -use crate::ty::subst::{Subst, Substs}; +use crate::ty::subst::{Subst, SubstsRef}; use crate::middle::cstore::{ExternCrate, ExternCrateSource}; use syntax::ast; use syntax::symbol::{keywords, Symbol}; @@ -79,7 +79,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn item_path_str_with_substs_and_ns( self, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> String { debug!("item_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); @@ -116,7 +116,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { pub fn default_print_item_path( &mut self, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> P::Path { debug!("default_print_item_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns); @@ -169,7 +169,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { fn default_print_impl_path( &mut self, impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> P::Path { debug!("default_print_impl_path: impl_def_id={:?}", impl_def_id); @@ -314,7 +314,7 @@ pub trait ItemPathPrinter: Sized { fn print_item_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> Self::Path { self.default_print_item_path(def_id, substs, ns) @@ -322,7 +322,7 @@ pub trait ItemPathPrinter: Sized { fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> Self::Path { self.default_print_impl_path(impl_def_id, substs, ns) @@ -506,7 +506,7 @@ impl ItemPathPrinter for LocalPathPrinter { fn print_item_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> Self::Path { self.try_print_visible_item_path(def_id, ns) @@ -515,7 +515,7 @@ impl ItemPathPrinter for LocalPathPrinter { fn print_impl_path( self: &mut PrintCx<'_, '_, 'tcx, Self>, impl_def_id: DefId, - substs: Option<&Substs<'tcx>>, + substs: Option>, ns: Namespace, ) -> Self::Path { // Always use types for non-local impls, where types are always diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index bfdf34f3e37..307cee5d972 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -198,6 +198,8 @@ use crate::monomorphize::item::{MonoItemExt, DefPathBasedNames, InstantiationMod 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, @@ -487,21 +489,33 @@ fn check_type_length_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // We include the const length in the type length, as it's better // to be overly conservative. if type_length + const_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(hir_id) = tcx.hir().as_local_hir_id(instance.def_id()) { - tcx.sess.struct_span_fatal(tcx.hir().span_by_hir_id(hir_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 aff968f3618..b60e1c29ec0 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 c5432190412..aead415d23f 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) { @@ -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.rs b/src/test/ui/type_length_limit.rs index bb54669d37d..cd15f81a615 100644 --- a/src/test/ui/type_length_limit.rs +++ b/src/test/ui/type_length_limit.rs @@ -1,3 +1,5 @@ +// ignore-musl +// ignore-x86 // error-pattern: reached the type-length limit while instantiating // Test that the type length limit can be changed. diff --git a/src/test/ui/type_length_limit.stderr b/src/test/ui/type_length_limit.stderr index 910eca07594..9d07c86356b 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 f1af5a77a00225bec61c0ae7218031123364b619 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 12:20:59 +0200 Subject: [PATCH 25/70] 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 | 2 +- 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, 37 insertions(+), 47 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 6db1bc382af..3ed28a1f988 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 crate::hir; use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::ty::{self, Region, Ty}; +use crate::ty::{self, DefIdTree, Region, Ty}; use crate::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 94de999c25d..3da82d728c0 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -12,7 +12,7 @@ use crate::hir::CodegenFnAttrFlags; use crate::hir::def_id::{DefId, LOCAL_CRATE}; use crate::lint; use crate::middle::privacy; -use crate::ty::{self, TyCtxt}; +use crate::ty::{self, DefIdTree, TyCtxt}; use crate::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 ea1c9d81416..b36d2a57cb3 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -64,7 +64,7 @@ use crate::hir::Node; use crate::infer::InferCtxt; use crate::hir::def::{Def, CtorKind}; use crate::ty::adjustment; -use crate::ty::{self, Ty, TyCtxt}; +use crate::ty::{self, DefIdTree, Ty, TyCtxt}; use crate::ty::fold::TypeFoldable; use crate::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 42e253273ab..2b380238810 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -17,7 +17,7 @@ use rustc_macros::HashStable; use syntax::source_map; use syntax::ast; use syntax_pos::{Span, DUMMY_SP}; -use crate::ty::TyCtxt; +use crate::ty::{DefIdTree, TyCtxt}; use crate::ty::query::Providers; use crate::hir; @@ -650,7 +650,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_hir_id(param_owner).unwrap(); let scope = tcx.hir().maybe_body_owned_by_by_hir_id(param_owner_id).map(|body_id| { @@ -679,7 +679,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 ecf1d8a980a..1942f98abff 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -26,7 +26,7 @@ use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; use crate::traits; use crate::traits::{Clause, Clauses, GoalKind, Goal, Goals}; -use crate::ty::{self, Ty, TypeAndMut}; +use crate::ty::{self, DefIdTree, Ty, TypeAndMut}; use crate::ty::{TyS, TyKind, List}; use crate::ty::{AdtKind, AdtDef, ClosureSubsts, GeneratorSubsts, Region, Const, LazyConst}; use crate::ty::{PolyFnSig, InferTy, ParamTy, ProjectionTy, ExistentialPredicate, Predicate}; @@ -1594,7 +1594,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 288894f235b..5a15efc2f11 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -154,13 +154,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) } } @@ -173,7 +173,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 @@ -186,7 +186,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); @@ -195,7 +195,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 { @@ -248,16 +248,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - /// Returns the `DefId` 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 @@ -531,7 +521,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 dbccd60f86b..ddb3911daeb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2893,14 +2893,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 20acbb5b9c7..dfe87242c71 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -9,7 +9,7 @@ use polonius_engine::Atom; use rustc_data_structures::indexed_vec::Idx; use rustc_macros::HashStable; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef, Kind, UnpackedKind}; -use crate::ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; +use crate::ty::{self, AdtDef, DefIdTree, TypeFlags, Ty, TyCtxt, TypeFoldable}; use crate::ty::{List, TyS, ParamEnvAnd, ParamEnv}; use crate::util::captures::Captures; use crate::mir::interpret::{Scalar, Pointer}; @@ -1591,7 +1591,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 422f97b2996..65918a90821 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -7,7 +7,7 @@ use crate::hir::{self, Node}; use crate::mir::interpret::{sign_extend, truncate}; use crate::ich::NodeIdHashingMode; use crate::traits::{self, ObligationCause}; -use crate::ty::{self, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; +use crate::ty::{self, DefIdTree, Ty, TyCtxt, GenericParamDefKind, TypeFoldable}; use crate::ty::subst::{Subst, InternalSubsts, SubstsRef, UnpackedKind}; use crate::ty::query::TyCtxtAt; use crate::ty::TyKind::*; @@ -563,7 +563,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 0bdf44c2ae0..62cfa184430 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; diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 8aa4fdedc18..f1a3c682b53 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -13,7 +13,7 @@ use crate::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::{SubstsRef, Kind}; use rustc::ty::layout::VariantIdx; @@ -735,7 +735,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 b82aee7c96a..8e68a13e1e1 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -17,7 +17,7 @@ use rustc::hir::def::Def as HirDef; use rustc::hir::def_id::DefId; use rustc::session::config::Input; use rustc::span_bug; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use std::path::Path; @@ -1201,7 +1201,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 { @@ -1350,7 +1350,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 d80f3e5ce75..2aa44a9242e 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -20,7 +20,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::{bug, span_bug}; use rustc_typeck::hir_ty_to_ty; use rustc_codegen_utils::link::{filename_for_metadata, out_filename}; @@ -763,7 +763,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 fd09ce7f689..4e952f972e4 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -12,7 +12,7 @@ use crate::middle::resolve_lifetime as rl; use crate::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, InternalSubsts, SubstsRef}; use rustc::ty::wf::object_region_bounds; @@ -1452,7 +1452,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)); @@ -1621,7 +1621,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 6714866369e..e2e2d552ff1 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::{InternalSubsts, SubstsRef}; -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}; @@ -3971,7 +3971,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 e0c75ff40def45bbf39bfed5766a1a8a56f2409f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 12:31:35 +0200 Subject: [PATCH 26/70] 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 | 4 +- 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, 174 insertions(+), 174 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 41a4a803100..eb75e624d34 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -724,7 +724,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) } } @@ -736,7 +736,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 ed1c15a73c2..397843fd75a 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 ebed768fa54..2a638853992 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -448,10 +448,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 { @@ -658,7 +658,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(()); @@ -757,8 +757,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. @@ -1013,7 +1013,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 506388c268b..189ecf53e0e 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 @@ -193,7 +193,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), ), ); @@ -201,7 +201,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 1677384059e..0a2a375e1b2 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -593,7 +593,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { .map_or(false, |parent_depr| parent_depr.same_origin(&depr_entry)); 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, @@ -620,7 +620,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { if let Some(id) = id { if let Some(stability) = stability { if let Some(depr) = &stability.rustc_depr { - let path = self.item_path_str(def_id); + let path = self.def_path_str(def_id); if deprecation_in_effect(&depr.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 ec42809ff65..ea3668cec15 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2062,7 +2062,7 @@ impl<'tcx> Debug for Place<'tcx> { Base(PlaceBase::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 ), Base(PlaceBase::Promoted(ref promoted)) => write!( @@ -2731,7 +2731,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 { @@ -2756,8 +2756,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 0dd076481c8..6c8fe0875b6 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -1285,11 +1285,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 } @@ -1299,7 +1299,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, @@ -1524,7 +1524,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 df127b934b0..78c80b48ee8 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -650,7 +650,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, @@ -665,7 +665,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 @@ -692,13 +692,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 e7a5138e689..1c8ea5c7b9c 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { hir::CRATE_HIR_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 c86fd0d52b9..fc0058a1df5 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 197bea1c311..ab6acc66213 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1549,7 +1549,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 f58e5e4fb69..342a6204d7f 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -125,9 +125,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 `{:?}`", @@ -146,8 +146,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 {}", @@ -169,8 +169,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(), @@ -199,7 +199,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 5a15efc2f11..9f34f475eff 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 `DefId`. 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>, 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>, 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()); @@ -155,13 +155,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) } } } @@ -202,7 +202,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 { @@ -224,13 +224,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(); crate::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 | @@ -301,13 +301,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>, 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>, @@ -357,12 +357,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. @@ -390,9 +390,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) }; @@ -412,7 +412,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 { @@ -425,12 +425,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, ); @@ -485,7 +485,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)) } } @@ -493,14 +493,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>, 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>, @@ -522,7 +522,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 ddb3911daeb..4f933bf0d53 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2056,7 +2056,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 6488c0db42b..395b288df14 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -71,7 +71,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() @@ -301,7 +301,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() } } @@ -322,7 +322,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() } } @@ -359,7 +359,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() } } @@ -394,7 +394,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() } @@ -415,7 +415,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] @@ -513,7 +513,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] @@ -532,21 +532,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() } @@ -565,19 +565,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() } } @@ -883,7 +883,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() } } @@ -927,7 +927,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, SubstsRef<'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() } } @@ -945,7 +945,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 092255129f4..cf92ab2f2ff 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 { @@ -515,7 +515,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; } @@ -538,7 +538,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 @@ -582,7 +582,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))) }) } } @@ -590,7 +590,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))) }) } } @@ -1513,11 +1513,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 da065f9e05d..01bfe5d5af7 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1406,7 +1406,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(')'); } @@ -1443,7 +1443,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(')'); } @@ -1523,7 +1523,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) }; @@ -1558,7 +1558,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 a7771f3da18..1417cbf1265 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -227,7 +227,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 c4952681546..6a2b6f1321b 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; @@ -10,7 +10,7 @@ use rustc::ty::TyCtxt; 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 @@ -41,9 +41,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 1f69d617c83..9fe9a60b9aa 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 2794b6c556f..633e61a0034 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -463,7 +463,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 86b8b276eaf..7d61547527f 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -182,7 +182,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 62cfa184430..0f0811b562e 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 17f8c23f4fd..dfa5af444d3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -93,7 +93,7 @@ impl BorrowExplanation { // 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)), + format!("type `{}`", tcx.def_path_str(adt.did)), ), // Otherwise, just report the whole type (and use diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 365cb508b09..e6005142b85 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -142,7 +142,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 41babc1ad12..49967df0889 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -319,7 +319,7 @@ fn check_for_bindings_named_same_as_variants(cx: &MatchVisitor<'_, '_>, pat: &Pa 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 f1a3c682b53..ad7b45d8945 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -969,8 +969,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 8a32c3b636c..d92ab0c5179 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -283,7 +283,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 97d566e586e..001a61959c2 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1253,7 +1253,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { if !self.span.allows_unstable(&feature.as_str()) { 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 f078316b97c..f9f8abbe6c0 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -29,10 +29,10 @@ impl MirPass for SanityCheck { let def_id = src.def_id(); let id = tcx.hir().as_local_hir_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 41e16684b8a..69a2adcfce0 100644 --- a/src/librustc_mir/util/graphviz.rs +++ b/src/librustc_mir/util/graphviz.rs @@ -127,7 +127,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, result); } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index c3fbee3a2a6..12d4e90c7c0 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -80,7 +80,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, @@ -105,7 +105,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| { @@ -115,7 +115,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>( @@ -614,7 +614,7 @@ fn write_mir_sig( 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())) })?; if src.promoted.is_none() && is_function { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index c7e63a83b15..5065c1de97b 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -816,7 +816,7 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { let def_id = self.tcx.adjust_ident(ident, def.did, current_hir).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 2aa44a9242e..97b9db34ed5 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -411,7 +411,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) @@ -451,7 +451,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 4e952f972e4..9ca75566b42 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -922,7 +922,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(); @@ -1071,7 +1071,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!( @@ -1459,7 +1459,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 342a214e0cc..c6b66393dd2 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -1001,13 +1001,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 f79bf4e999d..e6e5c46c473 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -719,7 +719,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 32ca854b277..3a7308d0917 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -130,7 +130,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 efae870c3c3..1f0ab3abb28 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1195,7 +1195,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() { @@ -1203,7 +1203,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 4bf6471a629..f784a720b19 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -102,7 +102,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)) } }; @@ -135,16 +135,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() { @@ -516,7 +516,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 ) }); @@ -530,14 +530,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)) ) ); } @@ -638,7 +638,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 c40bdae0762..1383bf28113 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1328,7 +1328,7 @@ pub fn check_item_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, it: &'tcx hir::Ite debug!( "check_item_type(it.hir_id={}, it.name={})", it.hir_id, - tcx.item_path_str(tcx.hir().local_def_id_from_hir_id(it.hir_id)) + tcx.def_path_str(tcx.hir().local_def_id_from_hir_id(it.hir_id)) ); let _indenter = indenter(); match it.node { @@ -3534,7 +3534,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 92c44e24998..1f7e05de18b 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -68,7 +68,7 @@ pub fn check_item_well_formed<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: Def debug!("check_item_well_formed(it.hir_id={:?}, it.name={})", item.hir_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 @@ -976,7 +976,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 5d86bc54095..a2b01e3843f 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 39a2f5d37bd..a5452b4db2a 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -28,7 +28,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). @@ -204,10 +204,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 c875b856f3a..7e1c38e0515 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 49d11150689..c18f9fd102f 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 e2e2d552ff1..08d165b82b1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4250,7 +4250,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 279e2089f5d..b2982629fe6 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1042,7 +1042,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 9db25b15f68..5a461d61482 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 2a051a5e144..086b903b973 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 e23a326d5f8..6ddd93d632e 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: item-path(main) +error: def-path(main) --> $DIR/basic.rs:4:1 | -LL | #[rustc_item_path] - | ^^^^^^^^^^^^^^^^^^ +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ 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 69cd49e3951..992527017fb 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 4041eb6b0ba..d225c53e492 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: item-path(foo::Foo::bar) +error: def-path(foo::Foo::bar) --> $DIR/impl1.rs:9:9 | -LL | #[rustc_item_path] - | ^^^^^^^^^^^^^^^^^^ +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ 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: item-path(bar::::baz) +error: def-path(bar::::baz) --> $DIR/impl1.rs:19:9 | -LL | #[rustc_item_path] - | ^^^^^^^^^^^^^^^^^^ +LL | #[rustc_def_path] + | ^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors From 9f8aaa04e02c74209e3ea355d8888cbc59a8fb64 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 13:25:31 +0200 Subject: [PATCH 27/70] rustc: move the contents of ty::item_path to ty::print. --- src/librustc/ty/item_path.rs | 560 ------------------ src/librustc/ty/mod.rs | 1 - src/librustc/ty/print.rs | 560 +++++++++++++++++- 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, 573 insertions(+), 580 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 9f34f475eff..00000000000 --- a/src/librustc/ty/item_path.rs +++ /dev/null @@ -1,560 +0,0 @@ -use crate::hir::def::Namespace; -use crate::hir::map::DefPathData; -use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use crate::ty::{self, DefIdTree, Ty, TyCtxt}; -use crate::ty::print::PrintCx; -use crate::ty::subst::{Subst, SubstsRef}; -use crate::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 - }) -} - -/// Adds 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 `DefId`. 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>, - 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>, - 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::ConstParam(..) | - 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>, - 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(); - crate::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 `DefId`" 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>, - 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>, - 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 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()) - } - _ => { - 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>, - 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>, - 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 4f933bf0d53..882e2dc62b1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -95,7 +95,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 a1d93bc4140..053a7531cad 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -1,11 +1,64 @@ -use crate::ty::{self, TyCtxt, TypeFoldable}; +use crate::hir::def::Namespace; +use crate::hir::map::DefPathData; +use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use crate::ty::subst::{Subst, SubstsRef}; +use crate::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 + }) +} + +/// Adds 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,511 @@ 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>, + 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>, + 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 `DefId`. 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>, + 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 `DefId`. 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 `DefId`. 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>, + 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::ConstParam(..) | + 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>, + 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(); + crate::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 `DefId`" 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 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()) + } + _ => { + 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>, + 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>, + 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 e3276ba0bea..cff99f23d0e 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -4,11 +4,10 @@ use crate::dep_graph::{DepNodeIndex, DepNode, DepKind, SerializedDepNodeIndex}; use crate::ty::tls; -use crate::ty::{TyCtxt}; +use crate::ty::{self, TyCtxt}; use crate::ty::query::Query; use crate::ty::query::config::{QueryConfig, QueryDescription}; use crate::ty::query::job::{QueryJob, QueryResult, QueryInfo}; -use crate::ty::item_path; use crate::util::common::{profq_msg, ProfileQueriesMsg, QueryMsg}; @@ -299,7 +298,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 1417cbf1265..b417091704d 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::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; @@ -225,7 +224,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() @@ -400,7 +399,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 c0e2186d9f3..4a2c05b2013 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -104,7 +104,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 200089530c1..cbdd50cf405 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -29,7 +29,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; @@ -265,7 +265,7 @@ pub fn dump_mir<'a, 'tcx>( 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 12d4e90c7c0..a76d26a6831 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -2,7 +2,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; @@ -78,7 +77,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()) }); @@ -103,7 +102,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()) }); @@ -612,7 +611,7 @@ fn write_mir_sig( _ => bug!("Unexpected def description {:?}", descr), } - 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 f784a720b19..b4a1a2d76c2 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -15,7 +15,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 syntax_pos::{Span, FileName}; use syntax::ast; use syntax::util::lev_distance::find_best_match_for_name; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 08d165b82b1..6cf8a9896d5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -4225,12 +4225,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 b0fbca953fbdcef5e561a97e5936db0dd13c41d2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 19 Dec 2018 14:49:32 +0200 Subject: [PATCH 28/70] rustc: integrate LocalPathPrinter's behavior into FmtPrinter. --- src/librustc/ty/print.rs | 67 ++++++++++++++++++++++++++++---------- src/librustc/util/ppaux.rs | 35 ++++++++------------ 2 files changed, 63 insertions(+), 39 deletions(-) diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 053a7531cad..de0c3ee7fff 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 } } @@ -442,10 +458,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`. @@ -582,8 +595,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>, @@ -612,7 +631,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); @@ -627,26 +645,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 cf92ab2f2ff..39e26f13233 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -10,11 +10,11 @@ use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use crate::ty::{self, ParamConst, Ty, TypeFoldable}; -use crate::ty::print::{FmtPrinter, PrintCx, Print}; +use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; use crate::mir::interpret::ConstValue; 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>], @@ -409,7 +409,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 { @@ -494,13 +494,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 { @@ -581,7 +574,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))) }) } @@ -589,7 +582,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))) }) } @@ -605,7 +598,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_by_hir_id(self.var_path.hir_id), @@ -928,7 +921,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 a15bfc6f483c552f793932f7ac7fcbb69d187681 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Fri, 21 Dec 2018 17:10:21 +0200 Subject: [PATCH 29/70] rustc: merge PrintCx::parameterized and def_path printing. --- src/librustc/infer/error_reporting/mod.rs | 7 +- src/librustc/ty/print.rs | 327 +++++++++++++++------ src/librustc/util/ppaux.rs | 257 ++++++---------- src/librustc_codegen_utils/symbol_names.rs | 176 ++++++----- 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 | 2 +- 8 files changed, 469 insertions(+), 329 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 2a638853992..c99ab215b35 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -450,8 +450,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 de0c3ee7fff..45762460f2d 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -2,7 +2,7 @@ use crate::hir::def::Namespace; use crate::hir::map::DefPathData; use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; -use crate::ty::subst::{Subst, SubstsRef}; +use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::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! { @@ -151,8 +152,9 @@ pub trait Printer: Sized { def_id: DefId, substs: Option>, 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( @@ -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: SubstsRef<'tcx>, + ns: Namespace, + projections: impl Iterator>, + ) -> Self::Path; } #[must_use] @@ -193,6 +210,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { DefPathData::EnumVariant(..) | DefPathData::Field(..) | DefPathData::AnonConst | + DefPathData::ConstParam(..) | DefPathData::ClosureExpr | DefPathData::StructCtor => Namespace::ValueNS, @@ -212,14 +230,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 `DefId`. This string is @@ -227,7 +241,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,14 +253,6 @@ 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 `DefId`. 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> { @@ -251,10 +261,12 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { def_id: DefId, substs: Option>, 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,36 +277,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::ConstParam(..) | - 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()) - }, + _ => { + 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); - 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) + // 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 + } } } } @@ -335,7 +357,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 { @@ -348,7 +370,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 @@ -356,14 +378,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(); - crate::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 | @@ -375,7 +393,7 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { } _ => { - self.path_impl(&format!("<{}>", self_ty)) + self.path_qualified(self_ty, None) } } } @@ -429,44 +447,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 @@ -497,7 +486,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) }; @@ -530,7 +519,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; @@ -593,6 +582,114 @@ 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: SubstsRef<'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) + ) + } + ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) + } + }).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)?; + } + UnpackedKind::Const(ct) => { + start_or_continue(self, start, ", ")?; + ct.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,9 +706,27 @@ impl Printer for FmtPrinter { def_id: DefId, substs: Option>, 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>, @@ -621,7 +736,9 @@ impl Printer for FmtPrinter { ) -> 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 @@ -632,7 +749,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)); } @@ -641,6 +758,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. @@ -655,6 +777,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 }) @@ -678,6 +807,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: SubstsRef<'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 39e26f13233..2c38c437cf6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -1,8 +1,7 @@ use crate::hir::def::Namespace; use crate::hir::def_id::DefId; -use crate::hir::map::definitions::DefPathData; use crate::middle::region; -use crate::ty::subst::{self, Kind, Subst, SubstsRef, UnpackedKind}; +use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind}; use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed}; use crate::ty::{Bool, Char, Adt}; use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr}; @@ -10,7 +9,7 @@ use crate::ty::{Param, Bound, RawPtr, Ref, Never, Tuple}; use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque}; use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer}; use crate::ty::{self, ParamConst, Ty, TypeFoldable}; -use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print}; +use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer}; use crate::mir::interpret::ConstValue; use std::cell::Cell; @@ -284,130 +283,6 @@ impl PrintCx<'a, 'gcx, 'tcx, P> { Ok(()) } - fn parameterized( - &mut self, - def_id: DefId, - substs: SubstsRef<'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) - ) - } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) - } - }).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)?; - } - UnpackedKind::Const(ct) => { - start_or_continue(self, start, ", ")?; - ct.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> { @@ -490,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(()) }) } @@ -508,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; } @@ -519,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(), )?; @@ -530,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 @@ -543,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(()) @@ -575,7 +463,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(()) }) } } @@ -583,7 +477,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(()) }) } } @@ -645,10 +545,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) @@ -874,7 +774,8 @@ define_print! { // // NB: this must be kept in sync with the printing logic above. impl ty::RegionKind { - fn display_outputs_anything