rustc: pass ty::print::PrintCx by value.

This commit is contained in:
Eduard-Mihai Burtescu 2019-01-10 13:27:11 +02:00
parent ab5d6fb302
commit 7c4eecef0b
6 changed files with 503 additions and 309 deletions

View File

@ -459,37 +459,52 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
type Path = Vec<String>;
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
}
fn path_qualified<'tcx>(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
_impl_prefix: Option<Self::Path>,
self: PrintCx<'_, '_, 'tcx, Self>,
_self_ty: Ty<'tcx>,
_trait_ref: Option<ty::TraitRef<'tcx>>,
_ns: Namespace,
) -> Result<Self::Path, Self::Error> {
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::Path, Self::Error>,
_self_ty: Ty<'tcx>,
_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
Err(NonTrivialPath)
}
fn path_append<'gcx, 'tcx>(
self: PrintCx<'_, 'gcx, 'tcx, Self>,
print_prefix: impl FnOnce(
PrintCx<'_, 'gcx, 'tcx, Self>,
) -> Result<Self::Path, Self::Error>,
text: &str,
) -> Result<Self::Path, Self::Error> {
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<Self::Path, Self::Error>,
_params: &[ty::GenericParamDef],
_substs: SubstsRef<'tcx>,
_ns: Namespace,
_projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Result<Self::Path, Self::Error> {
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())
})
};

View File

@ -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 {

View File

@ -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<Self>`, e.g. to
// HACK(eddyb) this is solely for `self: PrintCx<Self>`, e.g. to
// implement traits on the printer and call the methods on the context.
impl<P> 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<Self::Output, Self::Error>;
fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error>;
fn print_display(
&self,
cx: &mut PrintCx<'_, '_, 'tcx, P>,
cx: PrintCx<'_, '_, 'tcx, P>,
) -> Result<Self::Output, Self::Error> {
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<Self::Output, Self::Error> {
fn print_debug(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
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<SubstsRef<'tcx>>,
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<SubstsRef<'tcx>>,
ns: Namespace,
@ -173,24 +181,36 @@ pub trait Printer: Sized {
}
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error>;
fn path_qualified(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
impl_prefix: Option<Self::Path>,
self: PrintCx<'_, '_, 'tcx, Self>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> Result<Self::Path, Self::Error>;
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::Path, Self::Error>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error>;
fn path_append<'gcx, 'tcx>(
self: PrintCx<'_, 'gcx, 'tcx, Self>,
print_prefix: impl FnOnce(
PrintCx<'_, 'gcx, 'tcx, Self>,
) -> Result<Self::Path, Self::Error>,
text: &str,
) -> Result<Self::Path, Self::Error>;
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<Self::Path, Self::Error>,
params: &[ty::GenericParamDef],
substs: SubstsRef<'tcx>,
ns: Namespace,
@ -198,13 +218,32 @@ pub trait Printer: Sized {
) -> Result<Self::Path, Self::Error>;
}
#[must_use]
pub struct PrettyPath {
pub empty: bool,
/// Trait for printers that pretty-print using `fmt::Write` to the printer.
pub trait PrettyPrinter: Printer<Error = fmt::Error, Path = 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 for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result<Self, E>,
) -> Result<PrintCx<'a, 'gcx, 'tcx, Self>, 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<Error = fmt::Error, Path = PrettyPath> + 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<P: Printer> PrintCx<'a, 'gcx, 'tcx, P> {
pub fn default_print_def_path(
&mut self,
self,
def_id: DefId,
substs: Option<SubstsRef<'tcx>>,
ns: Namespace,
@ -273,48 +312,52 @@ impl<P: Printer> 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 {
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_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);
self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns)?
cx.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns)
} else {
self.print_def_path(parent_def_id, substs, ns, iter::empty())?
cx.print_def_path(parent_def_id, substs, ns, iter::empty())
}
} else {
self.print_def_path(parent_def_id, None, ns, iter::empty())?
cx.print_def_path(parent_def_id, None, ns, iter::empty())
}
};
let path = match key.disambiguated_data.data {
let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| {
match key.disambiguated_data.data {
// Skip `::{{constructor}}` on tuple/unit structs.
DefPathData::StructCtor => path,
DefPathData::StructCtor => print_parent_path(cx),
_ => {
self.path_append(
path,
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<SubstsRef<'tcx>>,
ns: Namespace,
@ -339,18 +382,20 @@ impl<P: Printer> 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<DefId> {
}
pub struct FmtPrinter<F: fmt::Write> {
pub fmt: F,
pub(crate) fmt: F,
empty: bool,
}
impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
impl<F: fmt::Write> FmtPrinter<F> {
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<Option<P::Path>, 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<P: PrettyPrinter> 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<P: PrettyPrinter> 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<P: PrettyPrinter> 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<P: PrettyPrinter> 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<P::Path>,
mut self,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> Result<P::Path, P::Error> {
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, "<impl ")?;
if let Some(trait_ref) = trait_ref {
trait_ref.print_display(self)?;
write!(self.printer, " for ")?;
}
self_ty.print_display(self)?;
write!(self.printer, ">")?;
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 `<Foo>::bar` if self-type is
@ -578,8 +630,7 @@ impl<P: PrettyPrinter> 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<P: PrettyPrinter> 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<P::Path, P::Error>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<P::Path, P::Error> {
// 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, "<impl "));
if let Some(trait_ref) = trait_ref {
nest!(self, |cx| trait_ref.print_display(cx));
write!(self.printer, " for ")?;
}
nest!(self, |cx| self_ty.print_display(cx));
write!(self.printer, ">")?;
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<P::Path, P::Error>,
params: &[ty::GenericParamDef],
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Result<P::Path, P::Error> {
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<P: PrettyPrinter> 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<P: PrettyPrinter> 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<P: PrettyPrinter> 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<F: fmt::Write> fmt::Write for FmtPrinter<F> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.empty &= s.is_empty();
self.fmt.write_str(s)
}
}
@ -697,10 +775,10 @@ impl<F: fmt::Write> fmt::Write for FmtPrinter<F> {
impl<F: fmt::Write> Printer for FmtPrinter<F> {
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<SubstsRef<'tcx>>,
ns: Namespace,
@ -710,15 +788,20 @@ impl<F: fmt::Write> Printer for FmtPrinter<F> {
// 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<F: fmt::Write> Printer for FmtPrinter<F> {
// 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!("<impl at {:?}>", span));
return self.path_append(
|cx| cx.print_def_path(parent_def_id, None, ns, iter::empty()),
&format!("<impl at {:?}>", span),
);
}
}
@ -748,7 +833,7 @@ impl<F: fmt::Write> Printer for FmtPrinter<F> {
}
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
mut self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
if cnum == LOCAL_CRATE {
@ -756,51 +841,83 @@ impl<F: fmt::Write> Printer for FmtPrinter<F> {
// 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::Path>,
self: PrintCx<'_, '_, 'tcx, Self>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
ns: Namespace,
) -> Result<Self::Path, Self::Error> {
self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns)
}
fn path_append(
self: &mut PrintCx<'_, '_, '_, Self>,
path: Self::Path,
text: &str,
) -> Result<Self::Path, Self::Error> {
// FIXME(eddyb) this shouldn't happen, but is currently
// the case for `extern { ... }` "foreign modules".
if text.is_empty() {
return Ok(path);
self.pretty_path_qualified(self_ty, trait_ref, ns)
}
if !path.empty {
write!(self.printer, "::")?;
fn path_append_impl<'gcx, 'tcx>(
self: PrintCx<'_, 'gcx, 'tcx, Self>,
print_prefix: impl FnOnce(
PrintCx<'_, 'gcx, 'tcx, Self>,
) -> Result<Self::Path, Self::Error>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
self.pretty_path_append_impl(print_prefix, self_ty, trait_ref)
}
write!(self.printer, "{}", text)?;
Ok(PrettyPath { empty: false })
fn path_append<'gcx, 'tcx>(
self: PrintCx<'_, 'gcx, 'tcx, Self>,
print_prefix: impl FnOnce(
PrintCx<'_, 'gcx, 'tcx, Self>,
) -> Result<Self::Path, Self::Error>,
text: &str,
) -> Result<Self::Path, Self::Error> {
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, "::")?;
}
fn path_generic_args(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
path: Self::Path,
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<Self::Path, Self::Error>,
params: &[ty::GenericParamDef],
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Result<Self::Path, Self::Error> {
self.pretty_path_generic_args(path, params, substs, ns, projections)
self.pretty_path_generic_args(print_prefix, params, substs, ns, projections)
}
}
impl<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {}
impl<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {
fn nest<'a, 'gcx, 'tcx, E>(
mut self: PrintCx<'a, 'gcx, 'tcx, Self>,
f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result<Self, E>,
) -> Result<PrintCx<'a, 'gcx, 'tcx, Self>, 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,
})
}
}

View File

@ -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<Self::Output, Self::Error> {
#[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<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<Self::Output, Self::Error> {
#[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<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
fn fn_sig(
&mut self,
mut self,
inputs: &[Ty<'tcx>],
c_variadic: bool,
output: Ty<'tcx>,
) -> fmt::Result {
) -> Result<P, fmt::Error> {
define_scoped_cx!(self);
p!(write("("));
@ -300,11 +314,11 @@ impl<P: PrettyPrinter> PrintCx<'a, 'gcx, 'tcx, P> {
p!(write(" -> "), print_display(output));
}
Ok(())
Ok(self.printer)
}
fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> Result<T::Output, fmt::Error>
where T: Print<'tcx, P, Error = fmt::Error> + TypeFoldable<'tcx>
fn in_binder<T>(mut self, value: &ty::Binder<T>) -> Result<P, fmt::Error>
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<P: PrettyPrinter> 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<P: PrettyPrinter> 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<F: fmt::Write>(
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<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
fn display_outputs_anything<P>(&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<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
fn display_outputs_anything<P>(&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<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
pub(crate) fn display_outputs_anything<P>(&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<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
fn display_outputs_anything<P>(&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,8 +1214,12 @@ 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) {
for (freevar, upvar_ty) in cx.tcx.freevars(did)
.as_ref()
.map_or(&[][..], |fv| &fv[..])
.iter()
.zip(upvar_tys)
{
p!(
write("{}{}:",
sep,
@ -1206,8 +1227,6 @@ define_print! {
print(upvar_ty));
sep = ", ";
}
Ok(())
})?
} 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,8 +1257,12 @@ 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) {
for (freevar, upvar_ty) in cx.tcx.freevars(did)
.as_ref()
.map_or(&[][..], |fv| &fv[..])
.iter()
.zip(upvar_tys)
{
p!(
write("{}{}:",
sep,
@ -1247,8 +1270,6 @@ define_print! {
print(upvar_ty));
sep = ", ";
}
Ok(())
})?
} 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"))
}
}

View File

@ -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::Path, Self::Error> {
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<Self::Path>,
mut self: PrintCx<'_, '_, 'tcx, Self>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
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<Self::Path, Self::Error> {
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::Path, Self::Error>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
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<Self::Path, Self::Error>,
text: &str,
) -> Result<Self::Path, Self::Error> {
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<Self::Path, Self::Error>,
params: &[ty::GenericParamDef],
substs: SubstsRef<'tcx>,
ns: Namespace,
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Result<Self::Path, Self::Error> {
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)
}
}

View File

@ -4235,50 +4235,70 @@ where F: Fn(DefId) -> Def {
type Path = Vec<String>;
fn path_crate(
self: &mut PrintCx<'_, '_, '_, Self>,
self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
Ok(vec![self.tcx.original_crate_name(cnum).to_string()])
}
fn path_qualified(
self: &mut PrintCx<'_, '_, 'tcx, Self>,
impl_prefix: Option<Self::Path>,
self: PrintCx<'_, '_, 'tcx, Self>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
_ns: Namespace,
) -> Result<Self::Path, Self::Error> {
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::Path, Self::Error>,
self_ty: Ty<'tcx>,
trait_ref: Option<ty::TraitRef<'tcx>>,
) -> Result<Self::Path, Self::Error> {
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!("<impl {} for {}>", trait_ref, self_ty)
}
None => format!("<impl {}>", 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<Self::Path, Self::Error>,
text: &str,
) -> Result<Self::Path, Self::Error> {
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<Self::Path, Self::Error>,
_params: &[ty::GenericParamDef],
_substs: SubstsRef<'tcx>,
_ns: Namespace,
_projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
) -> Result<Self::Path, Self::Error> {
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()
});