]> git.lizzy.rs Git - rust.git/commitdiff
rustc: pass ty::print::PrintCx by value.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Thu, 10 Jan 2019 11:27:11 +0000 (13:27 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Fri, 15 Mar 2019 11:25:10 +0000 (13:25 +0200)
src/librustc/infer/error_reporting/mod.rs
src/librustc/mir/mod.rs
src/librustc/ty/print.rs
src/librustc/util/ppaux.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustdoc/clean/mod.rs

index 68b2d201fb00a071b8cf4623d6c15452add9253d..6b1fea581e60f23466c516b4f99253d59b8c2d3d 100644 (file)
@@ -459,37 +459,52 @@ impl Printer for AbsolutePathPrinter {
             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 @@ fn path_generic_args<'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())
                     })
                 };
index 7ee8eec11ee42002a6267e014378bf142bdc1784..70ebb7111ef7aa5deba3383fee9b4c9d38485ce9 100644 (file)
@@ -2369,7 +2369,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
                 };
 
                 // 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 {
index 005dd18177d2380ea444a54ff7277817aa9b9122..986d65b2d9b6a374a3007f0775cb0a9c31dad505 100644 (file)
@@ -88,7 +88,7 @@ pub struct PrintCx<'a, 'gcx, 'tcx, P> {
     pub(crate) config: &'a mut PrintConfig,
 }
 
-// HACK(eddyb) this is solely for `self: &mut PrintCx<Self>`, e.g. to
+// HACK(eddyb) this is solely for `self: PrintCx<Self>`, e.g. to
 // implement traits on the printer and call the methods on the context.
 impl<P> Deref for PrintCx<'_, '_, '_, P> {
     type Target = P;
@@ -127,21 +127,29 @@ pub trait Print<'tcx, P> {
     type Output;
     type Error;
 
-    fn print(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error>;
+    fn print(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error>;
     fn print_display(
         &self,
-        cx: &mut PrintCx<'_, '_, 'tcx, P>,
+        cx: PrintCx<'_, '_, 'tcx, P>,
     ) -> Result<Self::Output, Self::Error> {
         let old_debug = cx.config.is_debug;
         cx.config.is_debug = false;
-        let result = self.print(cx);
+        let result = self.print(PrintCx {
+            tcx: cx.tcx,
+            printer: cx.printer,
+            config: cx.config,
+        });
         cx.config.is_debug = old_debug;
         result
     }
-    fn print_debug(&self, cx: &mut PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
+    fn print_debug(&self, cx: PrintCx<'_, '_, 'tcx, P>) -> Result<Self::Output, Self::Error> {
         let old_debug = cx.config.is_debug;
         cx.config.is_debug = true;
-        let result = self.print(cx);
+        let result = self.print(PrintCx {
+            tcx: cx.tcx,
+            printer: cx.printer,
+            config: cx.config,
+        });
         cx.config.is_debug = old_debug;
         result
     }
@@ -153,7 +161,7 @@ pub trait Printer: Sized {
     type Path;
 
     fn print_def_path(
-        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        self: PrintCx<'_, '_, 'tcx, Self>,
         def_id: DefId,
         substs: Option<SubstsRef<'tcx>>,
         ns: Namespace,
@@ -162,7 +170,7 @@ fn print_def_path(
         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 @@ fn print_impl_path(
     }
 
     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 @@ fn path_generic_args(
     ) -> 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 @@ pub fn def_path_str(self, def_id: DefId) -> String {
         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 @@ pub fn def_path_str(self, def_id: DefId) -> String {
 
 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 @@ pub fn default_print_def_path(
                 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 @@ fn default_print_impl_path(
             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 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<Option<P::Path
             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 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<Option<P::Path
                     ..
                 }) => {
                     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 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<Option<P::Path
 
         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 @@ fn try_print_visible_def_path(&mut self, def_id: DefId) -> Result<Option<P::Path
             },
         };
         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 @@ pub fn pretty_path_qualified(
 
                 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 @@ pub fn pretty_path_qualified(
         }
 
         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 @@ pub fn pretty_path_generic_args(
                     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 @@ pub fn pretty_path_generic_args(
                         // 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 @@ pub fn pretty_path_generic_args(
         }
 
         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 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
 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 @@ fn print_def_path(
         // 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 @@ fn print_def_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),
+                );
             }
         }
 
@@ -748,7 +833,7 @@ fn print_def_path(
     }
 
     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 @@ fn path_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,
+        })
+    }
+}
index 55e0544d2bbe5cd21491e8585cb9e1a762c0e2b7..ff5d9335909eee7fee9d5864872ef7ed4248db1e 100644 (file)
@@ -161,8 +161,9 @@ pub fn placeholder_highlight(&self, p: ty::PlaceholderRegion) -> Option<usize> {
 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 @@ impl fmt::Debug for $target {
 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! 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 @@ fn fn_sig(
             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 @@ fn name_by_region_index(index: usize) -> InternedString {
         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 @@ fn name_by_region_index(index: usize) -> InternedString {
             };
             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 @@ pub fn parameterized<F: fmt::Write>(
                     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 @@ pub fn parameterized<F: fmt::Write>(
                     // 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 @@ pub fn parameterized<F: fmt::Write>(
                 }
                 first = false;
 
-                let _ = cx.print_def_path(
+                nest!(|cx| cx.print_def_path(
                     def_id,
                     None,
                     Namespace::TypeNS,
                     iter::empty(),
-                )?;
+                ));
             }
         }
     }
@@ -486,8 +504,8 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 
 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
             if let BrNamed(_, name) = *self {
                 if name != "" && name != "'_" {
                     p!(write("{}", name));
-                    return Ok(());
+                    return Ok(cx.printer);
                 }
             }
 
@@ -628,7 +647,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 //
 // 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 @@ fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
 //
 // 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 @@ fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
             // 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 @@ fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
 // 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 @@ pub(crate) fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>
             }
 
             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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 //
 // 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
     ]
     (self, cx) {
         display {
-            cx.in_binder(self)?
+            nest!(|cx| cx.in_binder(self))
         }
     }
 }
@@ -1019,15 +1038,15 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 }
                 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     }
                 }
                 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     }
                 }
                 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                             }
                             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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                             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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 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"))
                 }
             }
index 8f4b1d1638a80e383768d4c067f28c63e4dfe6fc..2f9627331189f7e3faec2f4bb11644ec4a300005 100644 (file)
@@ -93,7 +93,7 @@
 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 @@ fn finish(mut self, hash: u64) -> String {
 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 @@ fn path_qualified(
             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)
     }
 }
 
index ffdf47db54723bdfea2f4b03ad664e4477a627d8..536ee3d58d65ff1b1f444d2402af32f85dd24a13 100644 (file)
@@ -4235,50 +4235,70 @@ impl Printer for AbsolutePathPrinter {
         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()
     });