about summary refs log tree commit diff
path: root/src/comp
diff options
context:
space:
mode:
authorLindsey Kuper <lkuper@mozilla.com>2011-07-07 17:10:17 -0700
committerLindsey Kuper <lkuper@mozilla.com>2011-07-07 17:29:15 -0700
commit32431440469f403b1532e25dfd60c3d958840dc1 (patch)
tree99d3e0c082357e94081ad2a508e047c8f93b1752 /src/comp
parent301f6aaa31594f996ae70ed84cf4e2ba7d8b3030 (diff)
downloadrust-32431440469f403b1532e25dfd60c3d958840dc1.tar.gz
rust-32431440469f403b1532e25dfd60c3d958840dc1.zip
Fix a bug that was interfering with method overriding. Issue #543.
Previously, we were creating both a normal vtable entry and a
forwarding function for overriding methods, when they should have just
gotten a vtable entry.  This patch fixes that.
Diffstat (limited to 'src/comp')
-rw-r--r--src/comp/middle/trans.rs59
1 files changed, 36 insertions, 23 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 61b677f058f..e232ce97d36 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -8152,34 +8152,47 @@ fn create_vtbl(@local_ctxt cx, &span sp, TypeRef llself_ty, ty::t self_ty,
                 }
             }
 
-            // Now, filter out any methods that are being replaced.
-            fn filtering_fn(&vtbl_mthd m, vec[vtbl_mthd] addtl_meths) ->
-                option::t[vtbl_mthd] {
-
-                let option::t[vtbl_mthd] rslt;
-                if (std::vec::member[vtbl_mthd](m, addtl_meths)) {
-                    rslt = none;
-                } else {
-                    rslt = some(m);
+            // Now, filter out any methods that we don't need forwarding slots
+            // for, because they're being replaced.
+            fn filtering_fn(@local_ctxt cx, &vtbl_mthd m,
+                            (@ast::method)[] addtl_meths) 
+                -> option::t[vtbl_mthd] {
+
+                alt (m) {
+                    case (fwding_mthd(?fm)) {
+                        // Since fm is a fwding_mthd, and we're checking to
+                        // see if it's in addtl_meths (which only contains
+                        // normal_mthds), we can't just check if fm is a
+                        // member of addtl_meths.  Instead, we have to go
+                        // through addtl_meths and see if there's some method
+                        // in it that has the same name as fm.
+
+                        // FIXME (part of #543): We're only checking names
+                        // here.  If a method is replacing another, it also
+                        // needs to have the same type, but this should
+                        // probably be enforced in typechecking.
+                        for (@ast::method am in addtl_meths) {
+                            if (str::eq(am.node.ident, fm.ident)) {
+                                ret none;
+                            }
+                        }
+                        ret some(fwding_mthd(fm));
+                    }
+                    case (normal_mthd(_)) {
+                        // Should never happen.
+                        cx.ccx.sess.bug("create_vtbl(): shouldn't be any"
+                                        + " normal_mthds in meths here");
+                    }
                 }
-                ret rslt;
             }
-
-            // NB: addtl_meths is just like ob.methods except that it's of
-            // type vec[vtbl_mthd], not vec[@ast::method].
-            let vec[vtbl_mthd] addtl_meths = [];
-            for (@ast::method m in ob.methods) {
-                addtl_meths += [normal_mthd(m)];
-            }
-            auto f = bind filtering_fn(_, addtl_meths);
-
-            // Filter out any methods that we don't need forwarding slots for
-            // (namely, those that are being replaced).
+            auto f = bind filtering_fn(cx, _, ob.methods);
             meths = std::vec::filter_map[vtbl_mthd, vtbl_mthd](f, meths);
             
             // And now add the additional ones (both replacements and entirely
-            // new ones).
-            meths += addtl_meths;
+            // new ones).  These'll just be normal methods.
+            for (@ast::method m in ob.methods) {
+                meths += [normal_mthd(m)];
+            }
         }
     }