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)
}
}
// 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())
})
};
};
// 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 {
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;
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
}
type Path;
fn print_def_path(
- self: &mut PrintCx<'_, '_, 'tcx, Self>,
+ self: PrintCx<'_, '_, 'tcx, Self>,
def_id: DefId,
substs: Option<SubstsRef<'tcx>>,
ns: Namespace,
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,
}
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,
) -> 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
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
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,
let generics = substs.map(|_| self.tcx.generics_of(def_id));
let generics_parent = generics.as_ref().and_then(|g| g.parent);
let parent_def_id = DefId { index: key.parent.unwrap(), ..def_id };
- let path = if let Some(generics_parent_def_id) = generics_parent {
- assert_eq!(parent_def_id, generics_parent_def_id);
-
- // FIXME(eddyb) try to move this into the parent's printing
- // logic, instead of doing it when printing the child.
- let parent_generics = self.tcx.generics_of(parent_def_id);
- let parent_has_own_self =
- parent_generics.has_self && parent_generics.parent_count == 0;
- if let (Some(substs), true) = (substs, parent_has_own_self) {
- let trait_ref = ty::TraitRef::new(parent_def_id, substs);
- self.path_qualified(None, trait_ref.self_ty(), Some(trait_ref), ns)?
+ let print_parent_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| {
+ if let Some(generics_parent_def_id) = generics_parent {
+ assert_eq!(parent_def_id, generics_parent_def_id);
+
+ // FIXME(eddyb) try to move this into the parent's printing
+ // logic, instead of doing it when printing the child.
+ let parent_generics = cx.tcx.generics_of(parent_def_id);
+ let parent_has_own_self =
+ parent_generics.has_self && parent_generics.parent_count == 0;
+ if let (Some(substs), true) = (substs, parent_has_own_self) {
+ let trait_ref = ty::TraitRef::new(parent_def_id, substs);
+ cx.path_qualified(trait_ref.self_ty(), Some(trait_ref), ns)
+ } else {
+ cx.print_def_path(parent_def_id, substs, ns, iter::empty())
+ }
} else {
- self.print_def_path(parent_def_id, substs, ns, iter::empty())?
+ cx.print_def_path(parent_def_id, None, ns, iter::empty())
}
- } else {
- self.print_def_path(parent_def_id, None, ns, iter::empty())?
};
- let path = match key.disambiguated_data.data {
- // Skip `::{{constructor}}` on tuple/unit structs.
- DefPathData::StructCtor => path,
-
- _ => {
- self.path_append(
- path,
- &key.disambiguated_data.data.as_interned_str().as_str(),
- )?
+ let print_path = |cx: PrintCx<'_, 'gcx, 'tcx, P>| {
+ match key.disambiguated_data.data {
+ // Skip `::{{constructor}}` on tuple/unit structs.
+ DefPathData::StructCtor => print_parent_path(cx),
+
+ _ => {
+ cx.path_append(
+ print_parent_path,
+ &key.disambiguated_data.data.as_interned_str().as_str(),
+ )
+ }
}
};
if let (Some(generics), Some(substs)) = (generics, substs) {
let has_own_self = generics.has_self && generics.parent_count == 0;
let params = &generics.params[has_own_self as usize..];
- self.path_generic_args(path, params, substs, ns, projections)
+ self.path_generic_args(print_path, params, substs, ns, projections)
} else {
- Ok(path)
+ print_path(self)
}
}
}
}
fn default_print_impl_path(
- &mut self,
+ self,
impl_def_id: DefId,
_substs: Option<SubstsRef<'tcx>>,
ns: Namespace,
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)
+ }
}
}
}
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
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
..
}) => {
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);
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);
},
};
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
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);
}
_ => {}
}
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 {
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,
// 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, ", ")?;
}
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)
}
}
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,
// 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);
}
}
// 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),
+ );
}
}
}
fn path_crate(
- self: &mut PrintCx<'_, '_, '_, Self>,
+ mut self: PrintCx<'_, '_, '_, Self>,
cnum: CrateNum,
) -> Result<Self::Path, Self::Error> {
if cnum == LOCAL_CRATE {
// 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)
+ 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::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)
+ }
+ 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> {
- // FIXME(eddyb) this shouldn't happen, but is currently
- // the case for `extern { ... }` "foreign modules".
- if text.is_empty() {
- return Ok(path);
- }
+ let mut printer = print_prefix(self)?;
- if !path.empty {
- write!(self.printer, "::")?;
+ // FIXME(eddyb) `text` should never be empty, but it
+ // currently is for `extern { ... }` "foreign modules".
+ if !text.is_empty() {
+ if !printer.empty {
+ write!(printer, "::")?;
+ }
+ write!(printer, "{}", text)?;
}
- write!(self.printer, "{}", text)?;
- Ok(PrettyPath { empty: false })
+
+ Ok(printer)
}
- fn path_generic_args(
- self: &mut PrintCx<'_, '_, 'tcx, Self>,
- path: Self::Path,
+ fn path_generic_args<'gcx, 'tcx>(
+ self: PrintCx<'_, 'gcx, 'tcx, Self>,
+ print_prefix: impl FnOnce(
+ PrintCx<'_, 'gcx, 'tcx, Self>,
+ ) -> Result<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,
+ })
+ }
+}
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(())
})
}
};
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)
}
}
};
$(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));+
}
};
}
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("("));
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 {
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);
};
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
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(())
})
}
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;
}
}
// 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;
}
}
first = false;
- let _ = cx.print_def_path(
+ nest!(|cx| cx.print_def_path(
def_id,
None,
Namespace::TypeNS,
iter::empty(),
- )?;
+ ));
}
}
}
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,
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,
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,
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))
if let BrNamed(_, name) = *self {
if name != "" && name != "'_" {
p!(write("{}", name));
- return Ok(());
+ return Ok(cx.printer);
}
}
//
// 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;
}
//
// 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;
}
// 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
// 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;
}
}
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: {})->{:?}",
//
// 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;
}
]
(self, cx) {
display {
- cx.in_binder(self)?
+ nest!(|cx| cx.in_binder(self))
}
}
}
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));
}
}
}
}
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 }))
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) => {
}
}
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("("));
}
}
}
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))
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);
}
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.
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.
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);
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.
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(),
- )?;
+ ));
}
}
}
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"))
}
}
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};
}
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()
})
}
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.
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,
ty::Adt(..) | ty::Foreign(_) |
ty::Bool | ty::Char | ty::Str |
ty::Int(_) | ty::Uint(_) | ty::Float(_)
- if impl_prefix.is_none() && trait_ref.is_none() =>
+ if trait_ref.is_none() =>
{
- return self.pretty_path_qualified(None, self_ty, trait_ref, ns);
+ return self.pretty_path_qualified(self_ty, trait_ref, ns);
}
_ => {}
}
- // HACK(eddyb) make sure to finalize the last component of the
- // `impl` prefix, to avoid it fusing with the following text.
- let impl_prefix = match impl_prefix {
- Some(prefix) => {
- let mut prefix = self.path_append(prefix, "")?;
-
- // HACK(eddyb) also avoid an unnecessary `::`.
- prefix.empty = true;
-
- Some(prefix)
- }
- None => None,
- };
-
let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
- let r = self.pretty_path_qualified(impl_prefix, self_ty, trait_ref, ns);
- self.printer.keep_within_component = kept_within_component;
- r
+ let mut path = self.pretty_path_qualified(self_ty, trait_ref, ns)?;
+ path.keep_within_component = kept_within_component;
+ Ok(path)
+ }
+
+ fn path_append_impl<'gcx, 'tcx>(
+ self: PrintCx<'_, 'gcx, 'tcx, Self>,
+ print_prefix: impl FnOnce(
+ PrintCx<'_, 'gcx, 'tcx, Self>,
+ ) -> Result<Self::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(
- 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> {
- if self.keep_within_component {
+ let keep_within_component = self.printer.keep_within_component;
+
+ let mut path = print_prefix(self)?;
+
+ if keep_within_component {
// HACK(eddyb) print the path similarly to how `FmtPrinter` prints it.
- if !path.empty {
- self.printer.write_str("::")?;
- } else {
- path.empty = text.is_empty();
- }
+ path.write_str("::")?;
} else {
- self.printer.finalize_pending_component();
- path.empty = false;
+ path.finalize_pending_component();
}
- self.printer.write_str(text)?;
+ path.write_str(text)?;
Ok(path)
}
- fn path_generic_args(
- self: &mut PrintCx<'_, '_, 'tcx, Self>,
- path: Self::Path,
+ fn path_generic_args<'gcx, 'tcx>(
+ self: PrintCx<'_, 'gcx, 'tcx, Self>,
+ print_prefix: impl FnOnce(
+ PrintCx<'_, 'gcx, 'tcx, Self>,
+ ) -> Result<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)
}
}
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()
});