]> git.lizzy.rs Git - rust.git/commitdiff
syntax: expand impl_pretty_name to handle more cases.
authorHuon Wilson <dbau.pp+github@gmail.com>
Wed, 1 Jan 2014 05:30:21 +0000 (16:30 +1100)
committerHuon Wilson <dbau.pp+github@gmail.com>
Wed, 1 Jan 2014 15:53:54 +0000 (02:53 +1100)
The resulting symbol names aren't very pretty at all:

    trait Trait { fn method(&self); }
    impl<'a> Trait for ~[(&'a int, fn())] { fn method(&self) {} }

gives

    Trait$$UP$$VEC$$TUP_2$$BP$int$$FN$$::method::...hash...::v0.0

However, at least it contain some reference to the Self type, unlike
`Trait$__extensions__::method:...`, which is what the symbol name used
to be for anything other than `impl Trait for foo::bar::Baz` (which
became, and still becomes, `Trait$Baz::method`).

src/librustc/metadata/encoder.rs
src/libsyntax/ast_map.rs
src/test/compile-fail/ambig_impl_unify.rs

index 73b0ac46cbda96cffe978eea5f3bfd468c02ff15..5312805366a4c49e2ba3cfc3af1a25cdfab30b9c 100644 (file)
@@ -1140,7 +1140,7 @@ fn add_to_index(item: @item, ebml_w: &writer::Encoder,
             let impl_vtables = ty::lookup_impl_vtables(tcx, def_id);
             encode_impl_vtables(ebml_w, ecx, &impl_vtables);
         }
-        let elt = ast_map::impl_pretty_name(opt_trait, ty, item.ident);
+        let elt = ast_map::impl_pretty_name(opt_trait, ty);
         encode_path(ecx, ebml_w, path, elt);
         ebml_w.end_tag();
 
index 63e8251b22c64e427152b88902d69eeba42e0f9b..817cf24eec688fb4f0209f981cdf831a3467e51a 100644 (file)
@@ -82,26 +82,71 @@ pub fn path_elt_to_str(pe: path_elt, itr: @ident_interner) -> ~str {
     }
 }
 
-pub fn impl_pretty_name(trait_ref: &Option<trait_ref>,
-                        ty: &Ty, default: Ident) -> path_elt {
-    let itr = get_ident_interner();
-    let ty_ident = match ty.node {
-        ty_path(ref path, _, _) => path.segments.last().identifier,
-        _ => default
+/// write a "pretty" version of `ty` to `out`. This is designed so
+/// that symbols of `impl`'d methods give some hint of where they came
+/// from, even if it's hard to read (previously they would all just be
+/// listed as `__extensions__::method_name::hash`, with no indication
+/// of the type).
+// XXX: these dollar signs and the names in general are actually a
+//      relic of $ being one of the very few valid symbol names on
+//      unix. These kinds of details shouldn't be exposed way up here
+//      in the ast.
+fn pretty_ty(ty: &Ty, itr: @ident_interner, out: &mut ~str) {
+    let (prefix, subty) = match ty.node {
+        ty_uniq(ty) => ("$UP$", &*ty),
+        ty_box(mt { ty, .. }) => ("$SP$", &*ty),
+        ty_ptr(mt { ty, mutbl }) => (if mutbl == MutMutable {"$RPmut$"} else {"$RP$"},
+                                     &*ty),
+        ty_rptr(_, mt { ty, mutbl }) => (if mutbl == MutMutable {"$BPmut$"} else {"$BP$"},
+                                      &*ty),
+
+        ty_vec(ty) => ("$VEC$", &*ty),
+        ty_fixed_length_vec(ty, _) => ("$FIXEDVEC$", &*ty),
+
+        // these can't be represented as <prefix><contained ty>, so
+        // need custom handling.
+        ty_nil => { out.push_str("$NIL$"); return }
+        ty_path(ref path, _, _) => {
+                        out.push_str(itr.get(path.segments.last().identifier.name));
+                        return
+                    }
+        ty_tup(ref tys) => {
+            out.push_str(format!("$TUP_{}$", tys.len()));
+            for subty in tys.iter() {
+                pretty_ty(*subty, itr, out);
+                out.push_char('$');
+            }
+            return
+        }
+
+        // meh, better than nothing.
+        ty_bot => { out.push_str("$BOT$"); return }
+        ty_closure(..) => { out.push_str("$CLOSURE$"); return }
+        ty_bare_fn(..) => { out.push_str("$FN$"); return }
+        ty_typeof(..) => { out.push_str("$TYPEOF$"); return }
+        ty_infer(..) => { out.push_str("$INFER$"); return }
+
     };
+
+    out.push_str(prefix);
+    pretty_ty(subty, itr, out);
+}
+
+pub fn impl_pretty_name(trait_ref: &Option<trait_ref>, ty: &Ty) -> path_elt {
+    let itr = get_ident_interner();
+
     let hash = (trait_ref, ty).hash();
+    let mut pretty;
     match *trait_ref {
-        None => path_pretty_name(ty_ident, hash),
+        None => pretty = ~"",
         Some(ref trait_ref) => {
-            // XXX: this dollar sign is actually a relic of being one of the
-            //      very few valid symbol names on unix. These kinds of
-            //      details shouldn't be exposed way up here in the ast.
-            let s = format!("{}${}",
-                         itr.get(trait_ref.path.segments.last().identifier.name),
-                         itr.get(ty_ident.name));
-            path_pretty_name(Ident::new(itr.gensym(s)), hash)
+            pretty = itr.get(trait_ref.path.segments.last().identifier.name).to_owned();
+            pretty.push_char('$');
         }
-    }
+    };
+    pretty_ty(ty, itr, &mut pretty);
+
+    path_pretty_name(Ident::new(itr.gensym(pretty)), hash)
 }
 
 #[deriving(Clone)]
@@ -265,7 +310,7 @@ fn visit_item(&mut self, i: @item, _: ()) {
                 // Right now the ident on impls is __extensions__ which isn't
                 // very pretty when debugging, so attempt to select a better
                 // name to use.
-                let elt = impl_pretty_name(maybe_trait, ty, i.ident);
+                let elt = impl_pretty_name(maybe_trait, ty);
 
                 let impl_did = ast_util::local_def(i.id);
                 for m in ms.iter() {
index df88ff1f0d02eb55eee607f31fc0a5cacf7c8177..c758a173f3875a924f03570ac7a4e448fe92b172 100644 (file)
@@ -13,11 +13,11 @@ trait foo {
 }
 
 impl foo for ~[uint] {
-    fn foo(&self) -> int {1} //~ NOTE candidate #1 is `foo$__extensions__::foo`
+    fn foo(&self) -> int {1} //~ NOTE candidate #1 is `foo$$UP$$VEC$uint::foo`
 }
 
 impl foo for ~[int] {
-    fn foo(&self) -> int {2} //~ NOTE candidate #2 is `foo$__extensions__::foo`
+    fn foo(&self) -> int {2} //~ NOTE candidate #2 is `foo$$UP$$VEC$int::foo`
 }
 
 fn main() {