rustc: introduce a ty::print::PrettyPrinter helper for printing "<...>".
This commit is contained in:
parent
35e5123f51
commit
ab26b26d34
2 changed files with 133 additions and 118 deletions
|
@ -336,7 +336,7 @@ pub trait PrettyPrinter:
|
|||
/// nested components in some larger context.
|
||||
fn nest<'a, 'gcx, 'tcx, E>(
|
||||
self: PrintCx<'a, 'gcx, 'tcx, Self>,
|
||||
f: impl for<'b> FnOnce(PrintCx<'b, 'gcx, 'tcx, Self>) -> Result<Self, E>,
|
||||
f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result<Self, E>,
|
||||
) -> Result<PrintCx<'a, 'gcx, 'tcx, Self>, E> {
|
||||
let printer = f(PrintCx {
|
||||
tcx: self.tcx,
|
||||
|
@ -350,6 +350,17 @@ pub trait PrettyPrinter:
|
|||
})
|
||||
}
|
||||
|
||||
/// Print `<...>` around what `f` prints.
|
||||
fn generic_delimiters<'gcx, 'tcx>(
|
||||
mut self: PrintCx<'_, 'gcx, 'tcx, Self>,
|
||||
f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result<Self, Self::Error>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
write!(self.printer, "<")?;
|
||||
let mut printer = f(self)?;
|
||||
write!(printer, ">")?;
|
||||
Ok(printer)
|
||||
}
|
||||
|
||||
/// Return `true` if the region should be printed in path generic args
|
||||
/// even when it's `'_`, such as in e.g. `Foo<'_, '_, '_>`.
|
||||
fn always_print_region_in_paths(
|
||||
|
@ -746,7 +757,7 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
|
|||
}
|
||||
|
||||
pub fn pretty_path_qualified(
|
||||
mut self,
|
||||
self,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
|
@ -772,20 +783,19 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
|
|||
}
|
||||
}
|
||||
|
||||
write!(self.printer, "<")?;
|
||||
nest!(self, |cx| self_ty.print_display(cx));
|
||||
if let Some(trait_ref) = trait_ref {
|
||||
write!(self.printer, " as ")?;
|
||||
nest!(self, |cx| cx.print_def_path(
|
||||
trait_ref.def_id,
|
||||
Some(trait_ref.substs),
|
||||
Namespace::TypeNS,
|
||||
iter::empty(),
|
||||
));
|
||||
}
|
||||
write!(self.printer, ">")?;
|
||||
|
||||
Ok(self.printer)
|
||||
self.generic_delimiters(|mut cx| {
|
||||
nest!(cx, |cx| self_ty.print_display(cx));
|
||||
if let Some(trait_ref) = trait_ref {
|
||||
write!(cx.printer, " as ")?;
|
||||
nest!(cx, |cx| cx.print_def_path(
|
||||
trait_ref.def_id,
|
||||
Some(trait_ref.substs),
|
||||
Namespace::TypeNS,
|
||||
iter::empty(),
|
||||
));
|
||||
}
|
||||
Ok(cx.printer)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pretty_path_append_impl(
|
||||
|
@ -796,17 +806,18 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
|
|||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<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, ">")?;
|
||||
nest!(self, print_prefix);
|
||||
|
||||
Ok(self.printer)
|
||||
self.generic_delimiters(|mut cx| {
|
||||
write!(cx.printer, "impl ")?;
|
||||
if let Some(trait_ref) = trait_ref {
|
||||
nest!(cx, |cx| trait_ref.print_display(cx));
|
||||
write!(cx.printer, " for ")?;
|
||||
}
|
||||
nest!(cx, |cx| self_ty.print_display(cx));
|
||||
|
||||
Ok(cx.printer)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pretty_path_generic_args(
|
||||
|
@ -821,18 +832,6 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
|
|||
) -> Result<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 {
|
||||
empty = false;
|
||||
start
|
||||
} else {
|
||||
cont
|
||||
})
|
||||
};
|
||||
|
||||
let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
|
||||
|
||||
// Don't print `'_` if there's no printed region.
|
||||
let print_regions = params.iter().any(|param| {
|
||||
match substs[param.index as usize].unpack() {
|
||||
|
@ -861,45 +860,75 @@ impl<'gcx, 'tcx, P: PrettyPrinter> PrintCx<'_, 'gcx, 'tcx, P> {
|
|||
}).count()
|
||||
};
|
||||
|
||||
for param in ¶ms[..params.len() - num_supplied_defaults] {
|
||||
match substs[param.index as usize].unpack() {
|
||||
UnpackedKind::Lifetime(region) => {
|
||||
if !print_regions {
|
||||
continue;
|
||||
}
|
||||
start_or_continue(&mut self, start, ", ")?;
|
||||
if !self.print_region_outputs_anything(region) {
|
||||
// This happens when the value of the region
|
||||
// parameter is not easily serialized. This may be
|
||||
// because the user omitted it in the first place,
|
||||
// or because it refers to some block in the code,
|
||||
// etc. I'm not sure how best to serialize this.
|
||||
write!(self.printer, "'_")?;
|
||||
} else {
|
||||
nest!(self, |cx| region.print_display(cx));
|
||||
}
|
||||
let params = ¶ms[..params.len() - num_supplied_defaults];
|
||||
let mut args = params.iter().map(|param| {
|
||||
substs[param.index as usize].unpack()
|
||||
}).filter(|arg| {
|
||||
match arg {
|
||||
UnpackedKind::Lifetime(_) => print_regions,
|
||||
_ => true,
|
||||
}
|
||||
});
|
||||
let arg0 = args.next();
|
||||
|
||||
let mut projections = projections;
|
||||
let projection0 = projections.next();
|
||||
|
||||
if arg0.is_none() && projection0.is_none() {
|
||||
return Ok(self.printer);
|
||||
}
|
||||
|
||||
// FIXME(eddyb) move this into `generic_delimiters`.
|
||||
if ns == Namespace::ValueNS {
|
||||
write!(self.printer, "::")?;
|
||||
}
|
||||
|
||||
self.generic_delimiters(|mut cx| {
|
||||
let mut empty = true;
|
||||
let mut maybe_comma = |cx: &mut Self| {
|
||||
if empty {
|
||||
empty = false;
|
||||
Ok(())
|
||||
} else {
|
||||
write!(cx.printer, ", ")
|
||||
}
|
||||
UnpackedKind::Type(ty) => {
|
||||
start_or_continue(&mut self, start, ", ")?;
|
||||
nest!(self, |cx| ty.print_display(cx));
|
||||
}
|
||||
UnpackedKind::Const(ct) => {
|
||||
start_or_continue(&mut self, start, ", ")?;
|
||||
nest!(self, |cx| ct.print_display(cx));
|
||||
};
|
||||
|
||||
for arg in arg0.into_iter().chain(args) {
|
||||
maybe_comma(&mut cx)?;
|
||||
|
||||
match arg {
|
||||
UnpackedKind::Lifetime(region) => {
|
||||
if !cx.print_region_outputs_anything(region) {
|
||||
// This happens when the value of the region
|
||||
// parameter is not easily serialized. This may be
|
||||
// because the user omitted it in the first place,
|
||||
// or because it refers to some block in the code,
|
||||
// etc. I'm not sure how best to serialize this.
|
||||
write!(cx.printer, "'_")?;
|
||||
} else {
|
||||
nest!(cx, |cx| region.print_display(cx));
|
||||
}
|
||||
}
|
||||
UnpackedKind::Type(ty) => {
|
||||
nest!(cx, |cx| ty.print_display(cx));
|
||||
}
|
||||
UnpackedKind::Const(ct) => {
|
||||
nest!(cx, |cx| ct.print_display(cx));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for projection in projections {
|
||||
start_or_continue(&mut self, start, ", ")?;
|
||||
write!(self.printer, "{}=",
|
||||
self.tcx.associated_item(projection.item_def_id).ident)?;
|
||||
nest!(self, |cx| projection.ty.print_display(cx));
|
||||
}
|
||||
for projection in projection0.into_iter().chain(projections) {
|
||||
maybe_comma(&mut cx)?;
|
||||
|
||||
start_or_continue(&mut self, "", ">")?;
|
||||
write!(cx.printer, "{}=",
|
||||
cx.tcx.associated_item(projection.item_def_id).ident)?;
|
||||
nest!(cx, |cx| projection.ty.print_display(cx));
|
||||
}
|
||||
|
||||
Ok(self.printer)
|
||||
Ok(cx.printer)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1087,7 +1116,15 @@ impl<F: fmt::Write> Printer for FmtPrinter<F> {
|
|||
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)
|
||||
self.pretty_path_append_impl(|cx| {
|
||||
let mut printer = print_prefix(cx)?;
|
||||
|
||||
if !printer.empty {
|
||||
write!(printer, "::")?;
|
||||
}
|
||||
|
||||
Ok(printer)
|
||||
}, self_ty, trait_ref)
|
||||
}
|
||||
fn path_append<'gcx, 'tcx>(
|
||||
self: PrintCx<'_, 'gcx, 'tcx, Self>,
|
||||
|
@ -1126,7 +1163,7 @@ impl<F: fmt::Write> Printer 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>,
|
||||
f: impl FnOnce(PrintCx<'_, '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 {
|
||||
|
|
|
@ -434,28 +434,12 @@ impl Printer for SymbolPath {
|
|||
Ok(self.printer)
|
||||
}
|
||||
fn path_qualified(
|
||||
mut self: PrintCx<'_, '_, 'tcx, Self>,
|
||||
self: PrintCx<'_, '_, 'tcx, Self>,
|
||||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<ty::TraitRef<'tcx>>,
|
||||
ns: Namespace,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
// HACK(eddyb) avoid `keep_within_component` for the cases
|
||||
// that print without `<...>` around `self_ty`.
|
||||
match self_ty.sty {
|
||||
ty::Adt(..) | ty::Foreign(_) |
|
||||
ty::Bool | ty::Char | ty::Str |
|
||||
ty::Int(_) | ty::Uint(_) | ty::Float(_)
|
||||
if trait_ref.is_none() =>
|
||||
{
|
||||
return self.pretty_path_qualified(self_ty, trait_ref, ns);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
|
||||
let mut path = self.pretty_path_qualified(self_ty, trait_ref, ns)?;
|
||||
path.keep_within_component = kept_within_component;
|
||||
Ok(path)
|
||||
self.pretty_path_qualified(self_ty, trait_ref, ns)
|
||||
}
|
||||
|
||||
fn path_append_impl<'gcx, 'tcx>(
|
||||
|
@ -466,18 +450,11 @@ impl Printer for SymbolPath {
|
|||
self_ty: Ty<'tcx>,
|
||||
trait_ref: Option<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.pretty_path_append_impl(
|
||||
|cx| cx.path_append(print_prefix, ""),
|
||||
self_ty,
|
||||
trait_ref,
|
||||
)?;
|
||||
path.keep_within_component = kept_within_component;
|
||||
Ok(path)
|
||||
)
|
||||
}
|
||||
fn path_append<'gcx, 'tcx>(
|
||||
self: PrintCx<'_, 'gcx, 'tcx, Self>,
|
||||
|
@ -486,11 +463,9 @@ impl Printer for SymbolPath {
|
|||
) -> Result<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 {
|
||||
if path.keep_within_component {
|
||||
// HACK(eddyb) print the path similarly to how `FmtPrinter` prints it.
|
||||
path.write_str("::")?;
|
||||
} else {
|
||||
|
@ -510,20 +485,7 @@ impl Printer for SymbolPath {
|
|||
ns: Namespace,
|
||||
projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
|
||||
) -> Result<Self::Path, Self::Error> {
|
||||
let kept_within_component = self.printer.keep_within_component;
|
||||
let mut path = self.pretty_path_generic_args(
|
||||
|cx| {
|
||||
let mut path = print_prefix(cx)?;
|
||||
path.keep_within_component = true;
|
||||
Ok(path)
|
||||
},
|
||||
params,
|
||||
substs,
|
||||
ns,
|
||||
projections,
|
||||
)?;
|
||||
path.keep_within_component = kept_within_component;
|
||||
Ok(path)
|
||||
self.pretty_path_generic_args(print_prefix, params, substs, ns, projections)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -534,6 +496,22 @@ impl PrettyPrinter for SymbolPath {
|
|||
) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn generic_delimiters<'gcx, 'tcx>(
|
||||
mut self: PrintCx<'_, 'gcx, 'tcx, Self>,
|
||||
f: impl FnOnce(PrintCx<'_, 'gcx, 'tcx, Self>) -> Result<Self, Self::Error>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
write!(self.printer, "<")?;
|
||||
|
||||
let kept_within_component =
|
||||
mem::replace(&mut self.printer.keep_within_component, true);
|
||||
let mut path = f(self)?;
|
||||
path.keep_within_component = kept_within_component;
|
||||
|
||||
write!(path, ">")?;
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for SymbolPath {
|
||||
|
|
Loading…
Add table
Reference in a new issue