use syntax::symbol::InternedString;
use std::cell::Cell;
-use std::fmt;
+use std::fmt::{self, Write as _};
use std::ops::Deref;
thread_local! {
pub trait Printer: Sized {
type Path;
+ #[must_use]
fn print_def_path(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
def_id: DefId,
) -> 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,
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,
) -> 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<Path = Result<PrettyPath, fmt::Error>> + 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?)
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
}
}
pub fmt: F,
}
-// FIXME(eddyb) integrate into `FmtPrinter`.
-struct LocalPathPrinter;
-
-impl LocalPathPrinter {
+impl<F: fmt::Write> FmtPrinter<F> {
/// 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`.
}
}
-impl Printer for LocalPathPrinter {
- type Path = String;
+impl<F: fmt::Write> fmt::Write for FmtPrinter<F> {
+ fn write_str(&mut self, s: &str) -> fmt::Result {
+ self.fmt.write_str(s)
+ }
+}
+
+impl<F: fmt::Write> Printer for FmtPrinter<F> {
+ type Path = Result<PrettyPath, fmt::Error>;
fn print_def_path(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
// 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);
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<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {}
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;
}
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<F>> for $target {
+ impl<$($x)+, P: PrettyPrinter> Print<'tcx, P> for $target {
type Output = fmt::Result;
- fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter<F>>) -> 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<F: fmt::Write> Print<'tcx, FmtPrinter<F>> for $target {
+ impl<P: PrettyPrinter> Print<'tcx, P> for $target {
type Output = fmt::Result;
- fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, FmtPrinter<F>>) -> fmt::Result {
+ fn print(&$self, $cx: &mut PrintCx<'_, '_, 'tcx, P>) -> fmt::Result {
if $cx.is_debug $dbg
else $disp
}
( $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)
} }
};
}
}
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)
};
}
-impl<F: fmt::Write> PrintCx<'a, 'gcx, 'tcx, FmtPrinter<F>> {
+impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
fn fn_sig(
&mut self,
inputs: &[Ty<'tcx>],
}
fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> fmt::Result
- where T: Print<'tcx, FmtPrinter<F>, 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 {
})
}
-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<ty::ExistentialPredicate<'tcx>>, (self, cx) {
display {
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)))
})
}
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)))
})
}
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),
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",