about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZack Corr <zack@z0w0.me>2013-02-17 00:31:57 +1000
committerZack Corr <zack@z0w0.me>2013-02-17 00:31:57 +1000
commitfe9f1d155ab674e402cdb1b530df8ecb66bb7dd4 (patch)
tree0ae36dfaed3da347ee1676941d59942b5e19d4e0
parent9ad8a1f46566ddcd705cc918863cee2946d8b946 (diff)
downloadrust-fe9f1d155ab674e402cdb1b530df8ecb66bb7dd4.tar.gz
rust-fe9f1d155ab674e402cdb1b530df8ecb66bb7dd4.zip
syntax: Implement recursive sorting of meta items. Closes #607
-rw-r--r--src/librustc/back/link.rs16
-rw-r--r--src/libsyntax/attr.rs30
2 files changed, 31 insertions, 15 deletions
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 894e846e11f..bd9c7f1616d 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -497,8 +497,7 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
 
         let cmh_items = attr::sort_meta_items(cmh_items);
 
-        symbol_hasher.reset();
-        for cmh_items.each |m| {
+        fn hash(symbol_hasher: &hash::State, m: &@ast::meta_item) {
             match m.node {
               ast::meta_name_value(ref key, value) => {
                 symbol_hasher.write_str(len_and_str((*key)));
@@ -507,13 +506,20 @@ pub fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
               ast::meta_word(ref name) => {
                 symbol_hasher.write_str(len_and_str((*name)));
               }
-              ast::meta_list(_, _) => {
-                // FIXME (#607): Implement this
-                fail!(~"unimplemented meta_item variant");
+              ast::meta_list(ref name, ref mis) => {
+                symbol_hasher.write_str(len_and_str((*name)));
+                for mis.each |m_| {
+                    hash(symbol_hasher, m_);
+                }
               }
             }
         }
 
+        symbol_hasher.reset();
+        for cmh_items.each |m| {
+            hash(symbol_hasher, m);
+        }
+
         for dep_hashes.each |dh| {
             symbol_hasher.write_str(len_and_str(*dh));
         }
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index 893647ca9ad..605d944c70d 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -192,13 +192,15 @@ fn eq(a: @ast::meta_item, b: @ast::meta_item) -> bool {
             }
             _ => false
           },
-          ast::meta_list(*) => {
-
-            // ~[Fixme-sorting]
-            // FIXME (#607): Needs implementing
-            // This involves probably sorting the list by name and
-            // meta_item variant
-            fail!(~"unimplemented meta_item variant")
+          ast::meta_list(ref na, misa) => match b.node {
+            ast::meta_list(ref nb, misb) => {
+                if na != nb { return false; }
+                for misa.each |&mi| {
+                    if !contains(misb, mi) { return false; }
+                }
+                true
+            }
+            _ => false
           }
         }
 }
@@ -253,8 +255,6 @@ pub fn last_meta_item_list_by_name(items: ~[@ast::meta_item], name: ~str)
 
 /* Higher-level applications */
 
-// FIXME (#607): This needs to sort by meta_item variant in addition to
-// the item name (See [Fixme-sorting])
 pub fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
     pure fn lteq(ma: &@ast::meta_item, mb: &@ast::meta_item) -> bool {
         pure fn key(m: &ast::meta_item) -> ~str {
@@ -270,7 +270,17 @@ pub fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
     // This is sort of stupid here, converting to a vec of mutables and back
     let mut v: ~[@ast::meta_item] = items;
     std::sort::quick_sort(v, lteq);
-    v
+
+    // There doesn't seem to be a more optimal way to do this
+    do v.map |&m| {
+        match m.node {
+          ast::meta_list(n, mis) => @spanned {
+              node: ast::meta_list(n, sort_meta_items(mis)),
+              .. *m
+          },
+          _ => m
+        }
+    }
 }
 
 pub fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: ~str) ->