diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 053a7531cadd..de0c3ee7fff8 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 cf92ab2f2ff4..39e26f13233b 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",