diff options
| -rw-r--r-- | src/librustc/infer/error_reporting/mod.rs | 37 | ||||
| -rw-r--r-- | src/librustc/mir/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/ty/print.rs | 387 | ||||
| -rw-r--r-- | src/librustc/util/ppaux.rs | 205 | ||||
| -rw-r--r-- | src/librustc_codegen_utils/symbol_names.rs | 117 | ||||
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 54 |
6 files changed, 498 insertions, 304 deletions
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 68b2d201fb0..6b1fea581e6 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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()) }) }; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 7ee8eec11ee..70ebb7111ef 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -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 { diff --git a/src/librustc/ty/print.rs b/src/librustc/ty/print.rs index 005dd18177d..986d65b2d9b 100644 --- a/src/librustc/ty/print.rs +++ b/src/librustc/ty/print.rs @@ -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 { - 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, @@ -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) + 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, + }) + } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 55e0544d2bb..ff5d9335909 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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,17 +1214,19 @@ 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) { - 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. @@ -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,17 +1257,19 @@ 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) { - 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. @@ -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")) } } diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 8f4b1d1638a..2f962733118 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -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 + 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) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ffdf47db547..536ee3d58d6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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() }); |
