]> git.lizzy.rs Git - rust.git/commitdiff
rustc: merge PrintCx::parameterized and def_path printing.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Fri, 21 Dec 2018 15:10:21 +0000 (17:10 +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/ty/print.rs
src/librustc/util/ppaux.rs
src/librustc_codegen_utils/symbol_names.rs
src/librustdoc/clean/mod.rs
src/librustdoc/lib.rs
src/test/ui/symbol-names/impl1.rs
src/test/ui/symbol-names/impl1.stderr

index 2a638853992f3c39fb12db58b4794bacacce4407..c99ab215b35801e9d517a4120748436fcc7c10fd 100644 (file)
@@ -450,8 +450,11 @@ fn check_and_note_conflicting_crates(
             if !(did1.is_local() || did2.is_local()) && did1.krate != did2.krate {
                 let exp_path = self.tcx.def_path_str(did1);
                 let found_path = self.tcx.def_path_str(did2);
-                let exp_abs_path = self.tcx.absolute_def_path_str(did1);
-                let found_abs_path = self.tcx.absolute_def_path_str(did2);
+                // HACK(eddyb) switch form `with_forced_absolute_paths`
+                // to a custom implementation of `ty::print::Printer`.
+                let (exp_abs_path, found_abs_path) = ty::print::with_forced_absolute_paths(|| {
+                    (self.tcx.def_path_str(did1), self.tcx.def_path_str(did2))
+                });
                 // We compare strings because DefPath can be different
                 // for imported and non-imported crates
                 if exp_path == found_path || exp_abs_path == found_abs_path {
index de0c3ee7fff8e8bd70c01745c484db484b39ab4a..45762460f2dbc1d35b17db007f8bad9be2495130 100644 (file)
@@ -2,7 +2,7 @@
 use crate::hir::map::DefPathData;
 use crate::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
 use crate::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable};
-use crate::ty::subst::{Subst, SubstsRef};
+use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
 use crate::middle::cstore::{ExternCrate, ExternCrateSource};
 use syntax::ast;
 use syntax::symbol::{keywords, Symbol};
@@ -12,6 +12,7 @@
 
 use std::cell::Cell;
 use std::fmt::{self, Write as _};
+use std::iter;
 use std::ops::Deref;
 
 thread_local! {
@@ -151,8 +152,9 @@ fn print_def_path(
         def_id: DefId,
         substs: Option<SubstsRef<'tcx>>,
         ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
     ) -> Self::Path {
-        self.default_print_def_path(def_id, substs, ns)
+        self.default_print_def_path(def_id, substs, ns, projections)
     }
     #[must_use]
     fn print_impl_path(
@@ -167,6 +169,12 @@ fn print_impl_path(
     #[must_use]
     fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path;
     #[must_use]
+    fn path_qualified(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Self::Path;
+    #[must_use]
     fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path;
     #[must_use]
     fn path_append(
@@ -174,6 +182,15 @@ fn path_append(
         path: Self::Path,
         text: &str,
     ) -> Self::Path;
+    #[must_use]
+    fn path_generic_args(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        path: Self::Path,
+        params: &[ty::GenericParamDef],
+        substs: SubstsRef<'tcx>,
+        ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
+    ) -> Self::Path;
 }
 
 #[must_use]
@@ -193,6 +210,7 @@ fn guess_def_namespace(self, def_id: DefId) -> Namespace {
             DefPathData::EnumVariant(..) |
             DefPathData::Field(..) |
             DefPathData::AnonConst |
+            DefPathData::ConstParam(..) |
             DefPathData::ClosureExpr |
             DefPathData::StructCtor => Namespace::ValueNS,
 
@@ -212,14 +230,10 @@ pub fn def_path_str_with_substs_and_ns(
         ns: Namespace,
     ) -> String {
         debug!("def_path_str: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
-        if FORCE_ABSOLUTE.with(|force| force.get()) {
-            PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, substs, ns)
-        } else {
-            let mut s = String::new();
-            let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s })
-                .print_def_path(def_id, substs, ns);
-            s
-        }
+        let mut s = String::new();
+        let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s })
+            .print_def_path(def_id, substs, ns, iter::empty());
+        s
     }
 
     /// Returns a string identifying this `DefId`. This string is
@@ -227,7 +241,11 @@ pub fn def_path_str_with_substs_and_ns(
     /// root, unless with_forced_absolute_paths was used.
     pub fn def_path_str(self, def_id: DefId) -> String {
         let ns = self.guess_def_namespace(def_id);
-        self.def_path_str_with_substs_and_ns(def_id, None, ns)
+        debug!("def_path_str: def_id={:?}, ns={:?}", def_id, ns);
+        let mut s = String::new();
+        let _ = PrintCx::new(self, FmtPrinter { fmt: &mut s })
+            .print_def_path(def_id, None, ns, iter::empty());
+        s
     }
 
     /// Returns a string identifying this local node-id.
@@ -235,14 +253,6 @@ pub fn def_path_str(self, def_id: DefId) -> String {
     pub fn node_path_str(self, id: ast::NodeId) -> String {
         self.def_path_str(self.hir().local_def_id(id))
     }
-
-    /// Returns a string identifying this `DefId`. This string is
-    /// suitable for user output. It always begins with a crate identifier.
-    pub fn absolute_def_path_str(self, def_id: DefId) -> String {
-        debug!("absolute_def_path_str: def_id={:?}", def_id);
-        let ns = self.guess_def_namespace(def_id);
-        PrintCx::new(self, AbsolutePathPrinter).print_def_path(def_id, None, ns)
-    }
 }
 
 impl<P: Printer> PrintCx<'a, 'gcx, 'tcx, P> {
@@ -251,10 +261,12 @@ pub fn default_print_def_path(
         def_id: DefId,
         substs: Option<SubstsRef<'tcx>>,
         ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
     ) -> P::Path {
         debug!("default_print_def_path: def_id={:?}, substs={:?}, ns={:?}", def_id, substs, ns);
         let key = self.tcx.def_key(def_id);
         debug!("default_print_def_path: key={:?}", key);
+
         match key.disambiguated_data.data {
             DefPathData::CrateRoot => {
                 assert!(key.parent.is_none());
@@ -265,36 +277,46 @@ pub fn default_print_def_path(
                 self.print_impl_path(def_id, substs, ns)
             }
 
-            // Unclear if there is any value in distinguishing these.
-            // Probably eventually (and maybe we would even want
-            // finer-grained distinctions, e.g., between enum/struct).
-            data @ DefPathData::Misc |
-            data @ DefPathData::TypeNs(..) |
-            data @ DefPathData::Trait(..) |
-            data @ DefPathData::TraitAlias(..) |
-            data @ DefPathData::AssocTypeInTrait(..) |
-            data @ DefPathData::AssocTypeInImpl(..) |
-            data @ DefPathData::AssocExistentialInImpl(..) |
-            data @ DefPathData::ValueNs(..) |
-            data @ DefPathData::Module(..) |
-            data @ DefPathData::TypeParam(..) |
-            data @ DefPathData::LifetimeParam(..) |
-            data @ DefPathData::ConstParam(..) |
-            data @ DefPathData::EnumVariant(..) |
-            data @ DefPathData::Field(..) |
-            data @ DefPathData::AnonConst |
-            data @ DefPathData::MacroDef(..) |
-            data @ DefPathData::ClosureExpr |
-            data @ DefPathData::ImplTrait |
-            data @ DefPathData::GlobalMetaData(..) => {
-                let parent_did = self.tcx.parent(def_id).unwrap();
-                let path = self.print_def_path(parent_did, None, ns);
-                self.path_append(path, &data.as_interned_str().as_symbol().as_str())
-            },
-
-            DefPathData::StructCtor => { // present `X` instead of `X::{{constructor}}`
-                let parent_def_id = self.tcx.parent(def_id).unwrap();
-                self.print_def_path(parent_def_id, substs, ns)
+            _ => {
+                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(trait_ref.self_ty(), Some(trait_ref))
+                    } else {
+                        self.print_def_path(parent_def_id, substs, 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(),
+                        )
+                    }
+                };
+
+                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)
+                } else {
+                    path
+                }
             }
         }
     }
@@ -335,7 +357,7 @@ fn default_print_impl_path(
             // 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.
-            let path = self.print_def_path(parent_def_id, None, ns);
+            let path = self.print_def_path(parent_def_id, None, ns, iter::empty());
             if let Some(trait_ref) = impl_trait_ref {
                 return self.path_append(path, &format!("<impl {} for {}>", trait_ref, self_ty));
             } else {
@@ -348,7 +370,7 @@ fn default_print_impl_path(
 
         if let Some(trait_ref) = impl_trait_ref {
             // Trait impls.
-            return self.path_impl(&format!("<{} as {}>", self_ty, trait_ref));
+            return self.path_qualified(self_ty, Some(trait_ref));
         }
 
         // Inherent impls. Try to print `Foo::bar` for an inherent
@@ -356,14 +378,10 @@ fn default_print_impl_path(
         // anything other than a simple path.
         match self_ty.sty {
             ty::Adt(adt_def, substs) => {
-                // FIXME(eddyb) this should recurse to build the path piecewise.
-                // self.print_def_path(adt_def.did, Some(substs), ns)
-                let mut s = String::new();
-                crate::util::ppaux::parameterized(&mut s, adt_def.did, substs, ns).unwrap();
-                self.path_impl(&s)
+                self.print_def_path(adt_def.did, Some(substs), ns, iter::empty())
             }
 
-            ty::Foreign(did) => self.print_def_path(did, None, ns),
+            ty::Foreign(did) => self.print_def_path(did, None, ns, iter::empty()),
 
             ty::Bool |
             ty::Char |
@@ -375,7 +393,7 @@ fn default_print_impl_path(
             }
 
             _ => {
-                self.path_impl(&format!("<{}>", self_ty))
+                self.path_qualified(self_ty, None)
             }
         }
     }
@@ -429,44 +447,15 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option<DefId> {
     }
 }
 
-// FIXME(eddyb) remove, alongside `FORCE_ABSOLUTE` and `absolute_def_path_str`.
-struct AbsolutePathPrinter;
-
-impl Printer for AbsolutePathPrinter {
-    type Path = String;
-
-    fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
-        self.tcx.original_crate_name(cnum).to_string()
-    }
-    fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
-        text.to_string()
-    }
-    fn path_append(
-        self: &mut PrintCx<'_, '_, '_, Self>,
-        mut path: Self::Path,
-        text: &str,
-    ) -> Self::Path {
-        if !path.is_empty() {
-            path.push_str("::");
-        }
-        path.push_str(text);
-        path
-    }
-}
-
 pub struct FmtPrinter<F: fmt::Write> {
     pub fmt: F,
 }
 
-impl<F: fmt::Write> FmtPrinter<F> {
+impl<P: PrettyPrinter> PrintCx<'a, '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(
-        self: &mut PrintCx<'_, '_, '_, Self>,
-        def_id: DefId,
-        ns: Namespace,
-    ) -> Option<<Self as Printer>::Path> {
+    fn try_print_visible_def_path(&mut self, def_id: DefId) -> Option<P::Path> {
         debug!("try_print_visible_def_path: def_id={:?}", def_id);
 
         // If `def_id` is a direct or injected extern crate, return the
@@ -497,7 +486,7 @@ fn try_print_visible_def_path(
                 }) => {
                     debug!("try_print_visible_def_path: def_id={:?}", def_id);
                     let path = if !span.is_dummy() {
-                        self.print_def_path(def_id, None, ns)
+                        self.print_def_path(def_id, None, Namespace::TypeNS, iter::empty())
                     } else {
                         self.path_crate(cnum)
                     };
@@ -530,7 +519,7 @@ fn try_print_visible_def_path(
         }
 
         let visible_parent = visible_parent_map.get(&def_id).cloned()?;
-        let path = self.try_print_visible_def_path(visible_parent, ns)?;
+        let path = self.try_print_visible_def_path(visible_parent)?;
         let actual_parent = self.tcx.parent(def_id);
 
         let data = cur_def_key.disambiguated_data.data;
@@ -593,6 +582,114 @@ fn try_print_visible_def_path(
         debug!("try_print_visible_def_path: symbol={:?}", symbol);
         Some(self.path_append(path, &symbol))
     }
+
+    pub fn pretty_path_qualified(
+        &mut self,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> P::Path {
+        write!(self.printer, "<")?;
+        self_ty.print_display(self)?;
+        if let Some(trait_ref) = trait_ref {
+            write!(self.printer, " as ")?;
+            let _ = self.print_def_path(
+                trait_ref.def_id,
+                Some(trait_ref.substs),
+                Namespace::TypeNS,
+                iter::empty(),
+            )?;
+        }
+        write!(self.printer, ">")?;
+        Ok(PrettyPath { empty: false })
+    }
+
+    pub fn pretty_path_generic_args(
+        &mut self,
+        path: P::Path,
+        params: &[ty::GenericParamDef],
+        substs: SubstsRef<'tcx>,
+        ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
+    ) -> P::Path {
+        let path = path?;
+
+        let mut empty = true;
+        let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
+            if empty {
+                empty = false;
+                write!(cx.printer, "{}", start)
+            } else {
+                write!(cx.printer, "{}", cont)
+            }
+        };
+
+        let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
+
+        // Don't print any regions if they're all erased.
+        let print_regions = params.iter().any(|param| {
+            match substs[param.index as usize].unpack() {
+                UnpackedKind::Lifetime(r) => *r != ty::ReErased,
+                _ => false,
+            }
+        });
+
+        // Don't print args that are the defaults of their respective parameters.
+        let num_supplied_defaults = if self.is_verbose {
+            0
+        } else {
+            params.iter().rev().take_while(|param| {
+                match param.kind {
+                    ty::GenericParamDefKind::Lifetime => false,
+                    ty::GenericParamDefKind::Type { has_default, .. } => {
+                        has_default && substs[param.index as usize] == Kind::from(
+                            self.tcx.type_of(param.def_id).subst(self.tcx, substs)
+                        )
+                    }
+                    ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
+                }
+            }).count()
+        };
+
+        for param in &params[..params.len() - num_supplied_defaults] {
+            match substs[param.index as usize].unpack() {
+                UnpackedKind::Lifetime(region) => {
+                    if !print_regions {
+                        continue;
+                    }
+                    start_or_continue(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,
+                        // or because it refers to some block in the code,
+                        // etc. I'm not sure how best to serialize this.
+                        write!(self.printer, "'_")?;
+                    } else {
+                        region.print_display(self)?;
+                    }
+                }
+                UnpackedKind::Type(ty) => {
+                    start_or_continue(self, start, ", ")?;
+                    ty.print_display(self)?;
+                }
+                UnpackedKind::Const(ct) => {
+                    start_or_continue(self, start, ", ")?;
+                    ct.print_display(self)?;
+                }
+            }
+        }
+
+        for projection in projections {
+            start_or_continue(self, start, ", ")?;
+            write!(self.printer, "{}=",
+                   self.tcx.associated_item(projection.item_def_id).ident)?;
+            projection.ty.print_display(self)?;
+        }
+
+        start_or_continue(self, "", ">")?;
+
+        Ok(path)
+    }
 }
 
 impl<F: fmt::Write> fmt::Write for FmtPrinter<F> {
@@ -609,9 +706,27 @@ fn print_def_path(
         def_id: DefId,
         substs: Option<SubstsRef<'tcx>>,
         ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
     ) -> Self::Path {
-        self.try_print_visible_def_path(def_id, ns)
-            .unwrap_or_else(|| self.default_print_def_path(def_id, substs, ns))
+        // FIXME(eddyb) avoid querying `tcx.generics_of`
+        // both here and in `default_print_def_path`.
+        let generics = substs.map(|_| self.tcx.generics_of(def_id));
+        if // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter`
+            !FORCE_ABSOLUTE.with(|force| force.get()) &&
+            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 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)
+                } else {
+                    path
+                };
+                return path;
+            }
+        }
+
+        self.default_print_def_path(def_id, substs, ns, projections)
     }
     fn print_impl_path(
         self: &mut PrintCx<'_, '_, 'tcx, Self>,
@@ -621,7 +736,9 @@ fn print_impl_path(
     ) -> Self::Path {
         // Always use types for non-local impls, where types are always
         // available, and filename/line-number is mostly uninteresting.
-        let use_types = !impl_def_id.is_local() || {
+        let use_types = // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter`
+            FORCE_ABSOLUTE.with(|force| force.get()) ||
+            !impl_def_id.is_local() || {
             // Otherwise, use filename/line-number if forced.
             let force_no_types = FORCE_IMPL_FILENAME_LINE.with(|f| f.get());
             !force_no_types
@@ -632,7 +749,7 @@ fn print_impl_path(
             // pretty printing some span information. This should
             // only occur very early in the compiler pipeline.
             let parent_def_id = self.tcx.parent(impl_def_id).unwrap();
-            let path = self.print_def_path(parent_def_id, None, ns);
+            let path = self.print_def_path(parent_def_id, None, ns, iter::empty());
             let span = self.tcx.def_span(impl_def_id);
             return self.path_append(path, &format!("<impl at {:?}>", span));
         }
@@ -641,6 +758,11 @@ fn print_impl_path(
     }
 
     fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
+        // HACK(eddyb) remove the `FORCE_ABSOLUTE` hack by bypassing `FmtPrinter`
+        if FORCE_ABSOLUTE.with(|force| force.get()) {
+            write!(self.printer, "{}", self.tcx.original_crate_name(cnum))?;
+            return Ok(PrettyPath { empty: false });
+        }
         if cnum == LOCAL_CRATE {
             if self.tcx.sess.rust_2018() {
                 // We add the `crate::` keyword on Rust 2018, only when desired.
@@ -655,6 +777,13 @@ fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Pat
             Ok(PrettyPath { empty: false })
         }
     }
+    fn path_qualified(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Self::Path {
+        self.pretty_path_qualified(self_ty, trait_ref)
+    }
     fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
         write!(self.printer, "{}", text)?;
         Ok(PrettyPath { empty: false })
@@ -678,6 +807,16 @@ fn path_append(
         write!(self.printer, "{}", text)?;
         Ok(PrettyPath { empty: false })
     }
+    fn path_generic_args(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        path: Self::Path,
+        params: &[ty::GenericParamDef],
+        substs: SubstsRef<'tcx>,
+        ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
+    ) -> Self::Path {
+        self.pretty_path_generic_args(path, params, substs, ns, projections)
+    }
 }
 
 impl<F: fmt::Write> PrettyPrinter for FmtPrinter<F> {}
index 39e26f13233b34e360fd3c42efbe62d779c6ac33..2c38c437cf6e7ede8f741698e873e8b586e16c92 100644 (file)
@@ -1,8 +1,7 @@
 use crate::hir::def::Namespace;
 use crate::hir::def_id::DefId;
-use crate::hir::map::definitions::DefPathData;
 use crate::middle::region;
-use crate::ty::subst::{self, Kind, Subst, SubstsRef, UnpackedKind};
+use crate::ty::subst::{Kind, Subst, SubstsRef, UnpackedKind};
 use crate::ty::{BrAnon, BrEnv, BrFresh, BrNamed};
 use crate::ty::{Bool, Char, Adt};
 use crate::ty::{Error, Str, Array, Slice, Float, FnDef, FnPtr};
@@ -10,7 +9,7 @@
 use crate::ty::{Closure, Generator, GeneratorWitness, Foreign, Projection, Opaque};
 use crate::ty::{Placeholder, UnnormalizedProjection, Dynamic, Int, Uint, Infer};
 use crate::ty::{self, ParamConst, Ty, TypeFoldable};
-use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print};
+use crate::ty::print::{FmtPrinter, PrettyPrinter, PrintCx, Print, Printer};
 use crate::mir::interpret::ConstValue;
 
 use std::cell::Cell;
@@ -284,130 +283,6 @@ fn fn_sig(
         Ok(())
     }
 
-    fn parameterized(
-        &mut self,
-        def_id: DefId,
-        substs: SubstsRef<'tcx>,
-        ns: Namespace,
-        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
-    ) -> fmt::Result {
-        let key = self.tcx.def_key(def_id);
-        let generics = self.tcx.generics_of(def_id);
-
-        if let Some(parent_def_id) = generics.parent {
-            assert_eq!(parent_def_id, DefId { index: key.parent.unwrap(), ..def_id });
-
-            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 parent_has_own_self {
-                print!(self, write("<"), print_display(substs.type_at(0)), write(" as "))?;
-                self.parameterized(parent_def_id, substs, Namespace::TypeNS, iter::empty())?;
-                print!(self, write(">"))?;
-            } else {
-                self.parameterized(parent_def_id, substs, ns, iter::empty())?;
-            }
-
-            // Skip `::{{constructor}}` on tuple/unit structs.
-            match key.disambiguated_data.data {
-                DefPathData::StructCtor => {}
-
-                _ => {
-                    print!(self, write("::{}", key.disambiguated_data.data.as_interned_str()))?;
-                }
-            }
-        } else {
-            // FIXME(eddyb) recurse through printing a path via `self`, instead
-            // instead of using the `tcx` method that produces a `String`.
-            print!(self, write("{}",
-                self.tcx.def_path_str_with_substs_and_ns(def_id, Some(substs), ns)))?;
-
-            // For impls, the above call already prints relevant generics args.
-            if let DefPathData::Impl = key.disambiguated_data.data {
-                return Ok(());
-            }
-        }
-
-        let mut empty = true;
-        let mut start_or_continue = |cx: &mut Self, start: &str, cont: &str| {
-            if empty {
-                empty = false;
-                print!(cx, write("{}", start))
-            } else {
-                print!(cx, write("{}", cont))
-            }
-        };
-
-        let start = if ns == Namespace::ValueNS { "::<" } else { "<" };
-
-        let has_own_self = generics.has_self && generics.parent_count == 0;
-        let params = &generics.params[has_own_self as usize..];
-
-        // Don't print any regions if they're all erased.
-        let print_regions = params.iter().any(|param| {
-            match substs[param.index as usize].unpack() {
-                UnpackedKind::Lifetime(r) => *r != ty::ReErased,
-                _ => false,
-            }
-        });
-
-        // Don't print args that are the defaults of their respective parameters.
-        let num_supplied_defaults = if self.is_verbose {
-            0
-        } else {
-            params.iter().rev().take_while(|param| {
-                match param.kind {
-                    ty::GenericParamDefKind::Lifetime => false,
-                    ty::GenericParamDefKind::Type { has_default, .. } => {
-                        has_default && substs[param.index as usize] == Kind::from(
-                            self.tcx.type_of(param.def_id).subst(self.tcx, substs)
-                        )
-                    }
-                    ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
-                }
-            }).count()
-        };
-
-        for param in &params[..params.len() - num_supplied_defaults] {
-            match substs[param.index as usize].unpack() {
-                UnpackedKind::Lifetime(region) => {
-                    if !print_regions {
-                        continue;
-                    }
-                    start_or_continue(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,
-                        // or because it refers to some block in the code,
-                        // etc. I'm not sure how best to serialize this.
-                        print!(self, write("'_"))?;
-                    } else {
-                        region.print_display(self)?;
-                    }
-                }
-                UnpackedKind::Type(ty) => {
-                    start_or_continue(self, start, ", ")?;
-                    ty.print_display(self)?;
-                }
-                UnpackedKind::Const(ct) => {
-                    start_or_continue(self, start, ", ")?;
-                    ct.print_display(self)?;
-                }
-            }
-        }
-
-        for projection in projections {
-            start_or_continue(self, start, ", ")?;
-            print!(self,
-                    write("{}=",
-                            self.tcx.associated_item(projection.item_def_id).ident),
-                    print_display(projection.ty))?;
-        }
-
-        start_or_continue(self, "", ">")
-    }
-
     fn in_binder<T>(&mut self, value: &ty::Binder<T>) -> fmt::Result
         where T: Print<'tcx, P, Output = fmt::Result> + TypeFoldable<'tcx>
     {
@@ -490,7 +365,8 @@ pub fn parameterized<F: fmt::Write>(
 ) -> fmt::Result {
     PrintCx::with(FmtPrinter { fmt: f }, |mut cx| {
         let substs = cx.tcx.lift(&substs).expect("could not lift for printing");
-        cx.parameterized(did, substs, ns, iter::empty())
+        let _ = cx.print_def_path(did, Some(substs), ns, iter::empty())?;
+        Ok(())
     })
 }
 
@@ -508,7 +384,12 @@ pub fn parameterized<F: fmt::Write>(
                     if let Tuple(ref args) = principal.substs.type_at(0).sty {
                         let mut projections = self.projection_bounds();
                         if let (Some(proj), None) = (projections.next(), projections.next()) {
-                            print!(cx, write("{}", cx.tcx.def_path_str(principal.def_id)))?;
+                            let _ = cx.print_def_path(
+                                principal.def_id,
+                                None,
+                                Namespace::TypeNS,
+                                iter::empty(),
+                            )?;
                             cx.fn_sig(args, false, proj.ty)?;
                             resugared_principal = true;
                         }
@@ -519,9 +400,9 @@ 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);
-                    cx.parameterized(
+                    let _ = cx.print_def_path(
                         principal.def_id,
-                        principal.substs,
+                        Some(principal.substs),
                         Namespace::TypeNS,
                         self.projection_bounds(),
                     )?;
@@ -530,8 +411,10 @@ pub fn parameterized<F: fmt::Write>(
             }
 
             // Builtin bounds.
+            // FIXME(eddyb) avoid printing twice (needed to ensure
+            // that the auto traits are sorted *and* printed via cx).
             let mut auto_traits: Vec<_> = self.auto_traits().map(|did| {
-                cx.tcx.def_path_str(did)
+                (cx.tcx.def_path_str(did), did)
             }).collect();
 
             // The auto traits come ordered by `DefPathHash`. While
@@ -543,13 +426,18 @@ pub fn parameterized<F: fmt::Write>(
             // output, sort the auto-traits alphabetically.
             auto_traits.sort();
 
-            for auto_trait in auto_traits {
+            for (_, def_id) in auto_traits {
                 if !first {
                     print!(cx, write(" + "))?;
                 }
                 first = false;
 
-                print!(cx, write("{}", auto_trait))?;
+                let _ = cx.print_def_path(
+                    def_id,
+                    None,
+                    Namespace::TypeNS,
+                    iter::empty(),
+                )?;
             }
 
             Ok(())
@@ -575,7 +463,13 @@ 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(FmtPrinter { fmt: f }, |mut cx| {
-            print!(cx, write("{}", cx.tcx.def_path_str(self.def_id)))
+            let _ = cx.print_def_path(
+                self.def_id,
+                None,
+                Namespace::TypeNS,
+                iter::empty(),
+            )?;
+            Ok(())
         })
     }
 }
@@ -583,7 +477,13 @@ 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(FmtPrinter { fmt: f }, |mut cx| {
-            print!(cx, write("{}", cx.tcx.def_path_str(self.did)))
+            let _ = cx.print_def_path(
+                self.did,
+                None,
+                Namespace::TypeNS,
+                iter::empty(),
+            )?;
+            Ok(())
         })
     }
 }
@@ -645,10 +545,10 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         display {
             let dummy_self = cx.tcx.mk_infer(ty::FreshTy(0));
 
-            let trait_ref = *ty::Binder::bind(*self)
+            ty::Binder::bind(*self)
                 .with_self_ty(cx.tcx, dummy_self)
-                .skip_binder();
-            cx.parameterized(trait_ref.def_id, trait_ref.substs, Namespace::TypeNS, iter::empty())
+                .skip_binder()
+                .print_display(cx)
         }
         debug {
             self.print_display(cx)
@@ -874,7 +774,8 @@ 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 {
-    fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
+    // HACK(eddyb) `pub(crate)` only for `ty::print`.
+    pub(crate) fn display_outputs_anything<P>(&self, cx: &mut PrintCx<'_, '_, '_, P>) -> bool {
         if cx.is_verbose {
             return true;
         }
@@ -1097,16 +998,17 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 define_print! {
     ('tcx) ty::TraitRef<'tcx>, (self, cx) {
         display {
-            cx.parameterized(self.def_id, self.substs, Namespace::TypeNS, iter::empty())
+            let _ = cx.print_def_path(
+                self.def_id,
+                Some(self.substs),
+                Namespace::TypeNS,
+                iter::empty(),
+            )?;
+            Ok(())
         }
         debug {
-            print!(cx,
-                write("<"),
-                print(self.self_ty()),
-                write(" as "),
-                print_display(self),
-                write(">")
-            )
+            let _ = cx.path_qualified(self.self_ty(), Some(*self))?;
+            Ok(())
         }
     }
 }
@@ -1152,7 +1054,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);
                     print!(cx, print(sig), write(" {{"))?;
-                    cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?;
+                    let _ = cx.print_def_path(
+                        def_id,
+                        Some(substs),
+                        Namespace::ValueNS,
+                        iter::empty(),
+                    )?;
                     print!(cx, write("}}"))
                 }
                 FnPtr(ref bare_fn) => {
@@ -1175,7 +1082,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     }
                 }
                 Adt(def, substs) => {
-                    cx.parameterized(def.did, substs, Namespace::TypeNS, iter::empty())
+                    let _ = cx.print_def_path(
+                        def.did,
+                        Some(substs),
+                        Namespace::TypeNS,
+                        iter::empty(),
+                    )?;
+                    Ok(())
                 }
                 Dynamic(data, r) => {
                     let print_r = r.display_outputs_anything(cx);
@@ -1190,12 +1103,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     Ok(())
                 }
                 Foreign(def_id) => {
-                    cx.parameterized(
+                    let _ = cx.print_def_path(
                         def_id,
-                        subst::InternalSubsts::empty(),
+                        None,
                         Namespace::TypeNS,
                         iter::empty(),
-                    )
+                    )?;
+                    Ok(())
                 }
                 Projection(ref data) => data.print(cx),
                 UnnormalizedProjection(ref data) => {
@@ -1215,7 +1129,7 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                     if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
                         print!(cx, write("{}", name))?;
                         let mut substs = substs.iter();
-                        // FIXME(eddyb) print this with `parameterized`.
+                        // FIXME(eddyb) print this with `print_def_path`.
                         if let Some(first) = substs.next() {
                             print!(cx, write("::<"))?;
                             print!(cx, write("{}", first))?;
@@ -1477,7 +1391,13 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 define_print! {
     ('tcx) ty::ProjectionTy<'tcx>, (self, cx) {
         display {
-            cx.parameterized(self.item_def_id, self.substs, Namespace::TypeNS, iter::empty())
+            let _ = cx.print_def_path(
+                self.item_def_id,
+                Some(self.substs),
+                Namespace::TypeNS,
+                iter::empty(),
+            )?;
+            Ok(())
         }
     }
 }
@@ -1505,16 +1425,33 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 ty::Predicate::Projection(ref predicate) => predicate.print(cx),
                 ty::Predicate::WellFormed(ty) => print!(cx, print(ty), write(" well-formed")),
                 ty::Predicate::ObjectSafe(trait_def_id) => {
-                    print!(cx, write("the trait `{}` is object-safe",
-                        cx.tcx.def_path_str(trait_def_id)))
+                    print!(cx, write("the trait `"))?;
+                    let _ = cx.print_def_path(
+                        trait_def_id,
+                        None,
+                        Namespace::TypeNS,
+                        iter::empty(),
+                    )?;
+                    print!(cx, write("` is object-safe"))
                 }
                 ty::Predicate::ClosureKind(closure_def_id, _closure_substs, kind) => {
-                    print!(cx, write("the closure `{}` implements the trait `{}`",
-                           cx.tcx.def_path_str(closure_def_id), kind))
+                    print!(cx, write("the closure `"))?;
+                    let _ = cx.print_def_path(
+                        closure_def_id,
+                        None,
+                        Namespace::ValueNS,
+                        iter::empty(),
+                    )?;
+                    print!(cx, write("` implements the trait `{}`", kind))
                 }
                 ty::Predicate::ConstEvaluatable(def_id, substs) => {
                     print!(cx, write("the constant `"))?;
-                    cx.parameterized(def_id, substs, Namespace::ValueNS, iter::empty())?;
+                    let _ = cx.print_def_path(
+                        def_id,
+                        Some(substs),
+                        Namespace::ValueNS,
+                        iter::empty(),
+                    )?;
                     print!(cx, write("` can be evaluated"))
                 }
             }
index b417091704d72091c6bf0178c488a85619990326..4c7b00ae0780d6845cc8687e44f80b78beb9639c 100644 (file)
@@ -93,7 +93,7 @@
 use rustc::hir::CodegenFnAttrFlags;
 use rustc::hir::map::definitions::DefPathData;
 use rustc::ich::NodeIdHashingMode;
-use rustc::ty::print::{PrintCx, Printer};
+use rustc::ty::print::{PrettyPath, PrettyPrinter, PrintCx, Printer};
 use rustc::ty::query::Providers;
 use rustc::ty::subst::SubstsRef;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 
 use log::debug;
 
-use std::fmt::Write;
-use std::mem::discriminant;
+use std::fmt::{self, Write};
+use std::iter;
+use std::mem::{self, discriminant};
 
 pub fn provide(providers: &mut Providers<'_>) {
     *providers = Providers {
@@ -225,9 +226,9 @@ fn get_symbol_hash<'a, 'tcx>(
 
 fn def_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::SymbolName {
     ty::print::with_forced_absolute_paths(|| {
-        PrintCx::new(tcx, SymbolPathPrinter)
-            .print_def_path(def_id, None, Namespace::ValueNS)
-            .into_interned()
+        let mut cx = PrintCx::new(tcx, SymbolPath::new(tcx));
+        let _ = cx.print_def_path(def_id, None, Namespace::ValueNS, iter::empty());
+        cx.printer.into_interned()
     })
 }
 
@@ -323,7 +324,7 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance
     let mut buf = SymbolPath::from_interned(tcx.def_symbol_name(def_id), tcx);
 
     if instance.is_vtable_shim() {
-        buf.push("{{vtable-shim}}");
+        let _ = buf.write_str("{{vtable-shim}}");
     }
 
     buf.finish(hash)
@@ -347,6 +348,12 @@ struct SymbolPath {
     result: String,
     temp_buf: String,
     strict_naming: bool,
+
+    // When `true`, `finalize_pending_component` is a noop.
+    // This is needed when recursing into `path_qualified`,
+    // or `path_generic_args`, as any nested paths are
+    // logically within one component.
+    keep_within_component: bool,
 }
 
 impl SymbolPath {
@@ -355,6 +362,7 @@ fn new(tcx: TyCtxt<'_, '_, '_>) -> Self {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16),
             strict_naming: tcx.has_strict_asm_symbol_naming(),
+            keep_within_component: false,
         };
         result.result.push_str("_ZN"); // _Z == Begin name-sequence, N == nested
         result
@@ -365,109 +373,139 @@ fn from_interned(symbol: ty::SymbolName, tcx: TyCtxt<'_, '_, '_>) -> Self {
             result: String::with_capacity(64),
             temp_buf: String::with_capacity(16),
             strict_naming: tcx.has_strict_asm_symbol_naming(),
+            keep_within_component: false,
         };
         result.result.push_str(&symbol.as_str());
         result
     }
 
-    fn into_interned(self) -> ty::SymbolName {
+    fn into_interned(mut self) -> ty::SymbolName {
+        self.finalize_pending_component();
         ty::SymbolName {
             name: Symbol::intern(&self.result).as_interned_str(),
         }
     }
 
-    fn push(&mut self, text: &str) {
-        self.temp_buf.clear();
-        let need_underscore = sanitize(&mut self.temp_buf, text, self.strict_naming);
-        let _ = write!(
-            self.result,
-            "{}",
-            self.temp_buf.len() + (need_underscore as usize)
-        );
-        if need_underscore {
-            self.result.push('_');
+    fn finalize_pending_component(&mut self) {
+        if !self.keep_within_component && !self.temp_buf.is_empty() {
+            let _ = write!(self.result, "{}{}", self.temp_buf.len(), self.temp_buf);
+            self.temp_buf.clear();
         }
-        self.result.push_str(&self.temp_buf);
     }
 
     fn finish(mut self, hash: u64) -> String {
+        self.finalize_pending_component();
         // E = end name-sequence
         let _ = write!(self.result, "17h{:016x}E", hash);
         self.result
     }
 }
 
-struct SymbolPathPrinter;
+// HACK(eddyb) this relies on using the `fmt` interface to get
+// `PrettyPrinter` aka pretty printing of e.g. types in paths,
+// symbol names should have their own printing machinery.
 
-impl Printer for SymbolPathPrinter {
-    type Path = SymbolPath;
+impl Printer for SymbolPath {
+    type Path = Result<PrettyPath, fmt::Error>;
 
     fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
-        let mut path = SymbolPath::new(self.tcx);
-        path.push(&self.tcx.original_crate_name(cnum).as_str());
-        path
+        self.printer.write_str(&self.tcx.original_crate_name(cnum).as_str())?;
+        Ok(PrettyPath { empty: false })
+    }
+    fn path_qualified(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        self_ty: Ty<'tcx>,
+        trait_ref: Option<ty::TraitRef<'tcx>>,
+    ) -> Self::Path {
+        let kept_within_component = mem::replace(&mut self.printer.keep_within_component, true);
+        let r = self.pretty_path_qualified(self_ty, trait_ref);
+        self.printer.keep_within_component = kept_within_component;
+        r
     }
     fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
-        let mut path = SymbolPath::new(self.tcx);
-        path.push(text);
-        path
+        self.printer.write_str(text)?;
+        Ok(PrettyPath { empty: false })
     }
     fn path_append(
         self: &mut PrintCx<'_, '_, '_, Self>,
-        mut path: Self::Path,
+        _: Self::Path,
         text: &str,
     ) -> Self::Path {
-        path.push(text);
-        path
+        self.printer.finalize_pending_component();
+        self.printer.write_str(text)?;
+        Ok(PrettyPath { empty: false })
+    }
+    fn path_generic_args(
+        self: &mut PrintCx<'_, '_, 'tcx, Self>,
+        path: Self::Path,
+        params: &[ty::GenericParamDef],
+        substs: SubstsRef<'tcx>,
+        ns: Namespace,
+        projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
+    ) -> Self::Path {
+        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
     }
 }
 
-// Name sanitation. LLVM will happily accept identifiers with weird names, but
-// gas doesn't!
-// gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
-// NVPTX assembly has more strict naming rules than gas, so additionally, dots
-// are replaced with '$' there.
-//
-// returns true if an underscore must be added at the start
-fn sanitize(result: &mut String, s: &str, strict_naming: bool) -> bool {
-    for c in s.chars() {
-        match c {
-            // Escape these with $ sequences
-            '@' => result.push_str("$SP$"),
-            '*' => result.push_str("$BP$"),
-            '&' => result.push_str("$RF$"),
-            '<' => result.push_str("$LT$"),
-            '>' => result.push_str("$GT$"),
-            '(' => result.push_str("$LP$"),
-            ')' => result.push_str("$RP$"),
-            ',' => result.push_str("$C$"),
-
-            '-' | ':' | '.' if strict_naming => {
-                // NVPTX doesn't support these characters in symbol names.
-                result.push('$')
+impl PrettyPrinter for SymbolPath {}
+
+impl fmt::Write for SymbolPath {
+    fn write_str(&mut self, s: &str) -> fmt::Result {
+        // Name sanitation. LLVM will happily accept identifiers with weird names, but
+        // gas doesn't!
+        // gas accepts the following characters in symbols: a-z, A-Z, 0-9, ., _, $
+        // NVPTX assembly has more strict naming rules than gas, so additionally, dots
+        // are replaced with '$' there.
+
+        for c in s.chars() {
+            if self.temp_buf.is_empty() {
+                match c {
+                    'a'..='z' | 'A'..='Z' | '_' => {}
+                    _ => {
+                        // Underscore-qualify anything that didn't start as an ident.
+                        self.temp_buf.push('_');
+                    }
+                }
             }
+            match c {
+                // Escape these with $ sequences
+                '@' => self.temp_buf.push_str("$SP$"),
+                '*' => self.temp_buf.push_str("$BP$"),
+                '&' => self.temp_buf.push_str("$RF$"),
+                '<' => self.temp_buf.push_str("$LT$"),
+                '>' => self.temp_buf.push_str("$GT$"),
+                '(' => self.temp_buf.push_str("$LP$"),
+                ')' => self.temp_buf.push_str("$RP$"),
+                ',' => self.temp_buf.push_str("$C$"),
+
+                '-' | ':' | '.' if self.strict_naming => {
+                    // NVPTX doesn't support these characters in symbol names.
+                    self.temp_buf.push('$')
+                }
 
-            // '.' doesn't occur in types and functions, so reuse it
-            // for ':' and '-'
-            '-' | ':' => result.push('.'),
-
-            // These are legal symbols
-            'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => result.push(c),
-
-            _ => {
-                result.push('$');
-                for c in c.escape_unicode().skip(1) {
-                    match c {
-                        '{' => {}
-                        '}' => result.push('$'),
-                        c => result.push(c),
+                // '.' doesn't occur in types and functions, so reuse it
+                // for ':' and '-'
+                '-' | ':' => self.temp_buf.push('.'),
+
+                // These are legal symbols
+                'a'..='z' | 'A'..='Z' | '0'..='9' | '_' | '.' | '$' => self.temp_buf.push(c),
+
+                _ => {
+                    self.temp_buf.push('$');
+                    for c in c.escape_unicode().skip(1) {
+                        match c {
+                            '{' => {}
+                            '}' => self.temp_buf.push('$'),
+                            c => self.temp_buf.push(c),
+                        }
                     }
                 }
             }
         }
-    }
 
-    // Underscore-qualify anything that didn't start as an ident.
-    !result.is_empty() && result.as_bytes()[0] != '_' as u8
-        && !(result.as_bytes()[0] as char).is_xid_start()
+        Ok(())
+    }
 }
index 6cf8a9896d513cf4c0102831ef5b0252e0de3004..f629447fc64faecdfb6e0dbb7d276cff42a37f4c 100644 (file)
@@ -39,7 +39,7 @@
 use std::hash::{Hash, Hasher};
 use std::default::Default;
 use std::{mem, slice, vec};
-use std::iter::{FromIterator, once};
+use std::iter::{self, FromIterator, once};
 use std::rc::Rc;
 use std::str::FromStr;
 use std::cell::RefCell;
@@ -4235,6 +4235,18 @@ impl Printer for AbsolutePathPrinter {
         fn path_crate(self: &mut PrintCx<'_, '_, '_, Self>, cnum: CrateNum) -> Self::Path {
             vec![self.tcx.original_crate_name(cnum).to_string()]
         }
+        fn path_qualified(
+            self: &mut PrintCx<'_, '_, 'tcx, Self>,
+            self_ty: Ty<'tcx>,
+            trait_ref: Option<ty::TraitRef<'tcx>>,
+        ) -> Self::Path {
+            // This shouldn't ever be needed, but just in case:
+            if let Some(trait_ref) = trait_ref {
+                vec![format!("{:?}", trait_ref)]
+            } else {
+                vec![format!("<{}>", self_ty)]
+            }
+        }
         fn path_impl(self: &mut PrintCx<'_, '_, '_, Self>, text: &str) -> Self::Path {
             vec![text.to_string()]
         }
@@ -4246,10 +4258,20 @@ fn path_append(
             path.push(text.to_string());
             path
         }
+        fn path_generic_args(
+            self: &mut PrintCx<'_, '_, 'tcx, Self>,
+            path: Self::Path,
+            _params: &[ty::GenericParamDef],
+            _substs: SubstsRef<'tcx>,
+            _ns: Namespace,
+            _projections: impl Iterator<Item = ty::ExistentialProjection<'tcx>>,
+        ) -> Self::Path {
+            path
+        }
     }
 
     let names = PrintCx::new(tcx, AbsolutePathPrinter)
-        .print_def_path(def_id, None, Namespace::TypeNS);
+        .print_def_path(def_id, None, Namespace::TypeNS, iter::empty());
 
     hir::Path {
         span: DUMMY_SP,
index 58ba827ee05f3d4268ec4af6e968cb683770761d..2ac44d0109f3a7649457cc614dfceb6f6fee0ee1 100644 (file)
@@ -8,6 +8,7 @@
 #![feature(arbitrary_self_types)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(in_band_lifetimes)]
 #![feature(nll)]
 #![feature(set_stdio)]
 #![feature(test)]
index 992527017fb7c0f3a3149496cf2cc6a96c751949..c712137e828f94e1d4e2ee8d6ce13b6cd716c944 100644 (file)
@@ -5,7 +5,7 @@ mod foo {
     pub struct Foo { x: u32 }
 
     impl Foo {
-        #[rustc_symbol_name] //~ ERROR _ZN15impl1..foo..Foo3bar
+        #[rustc_symbol_name] //~ ERROR _ZN5impl13foo3Foo3bar
         #[rustc_def_path] //~ ERROR def-path(foo::Foo::bar)
         fn bar() { }
     }
index d225c53e4927a9b6e79d4b435407afc35d554238..eda8646b5b4de1f035fbf03a7bbe5766bbf51acc 100644 (file)
@@ -1,4 +1,4 @@
-error: symbol-name(_ZN15impl1..foo..Foo3bar17hc487d6ec13fe9124E)
+error: symbol-name(_ZN5impl13foo3Foo3bar17hc487d6ec13fe9124E)
   --> $DIR/impl1.rs:8:9
    |
 LL |         #[rustc_symbol_name]