about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-27 19:32:42 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-27 19:35:24 -0700
commit93c2f5e0e43532a2288ed6dec378564264d1a77c (patch)
tree2d8d3f5d4667f7a009fa338bc34076216873b35c /src
parente6d2e49852873c52b872185a0ae5a8ca941ed2f1 (diff)
downloadrust-93c2f5e0e43532a2288ed6dec378564264d1a77c.tar.gz
rust-93c2f5e0e43532a2288ed6dec378564264d1a77c.zip
rustc: Use coherence for operator overloading.
The only use of the old-style impls is now placement new.
Diffstat (limited to 'src')
-rw-r--r--src/libcore/core.rs3
-rw-r--r--src/libcore/ops.rs50
-rw-r--r--src/libstd/ebml.rs20
-rw-r--r--src/libsyntax/ast.rs53
-rw-r--r--src/libsyntax/ast_util.rs16
-rw-r--r--src/libsyntax/ext/pipes/ast_builder.rs17
-rw-r--r--src/libsyntax/ext/pipes/pipec.rs2
-rw-r--r--src/rustc/driver/driver.rs4
-rw-r--r--src/rustc/middle/astencode.rs16
-rw-r--r--src/rustc/middle/lang_items.rs24
-rw-r--r--src/rustc/middle/resolve3.rs113
-rw-r--r--src/rustc/middle/ty.rs24
-rw-r--r--src/rustc/middle/typeck/check.rs16
-rw-r--r--src/rustc/middle/typeck/check/method.rs3
-rw-r--r--src/test/bench/shootout-mandelbrot.rs35
-rw-r--r--src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs31
-rw-r--r--src/test/compile-fail/no-core-attribute.rs6
-rw-r--r--src/test/compile-fail/pure-overloaded-op.rs33
-rw-r--r--src/test/compile-fail/selftype-astparam.rs6
-rw-r--r--src/test/compile-fail/selftype-ifacetype.rs4
-rw-r--r--src/test/run-pass/operator-overloading-leaks.rs91
-rw-r--r--src/test/run-pass/operator-overloading.rs45
-rw-r--r--src/test/run-pass/selftype-add-ints.rs19
23 files changed, 342 insertions, 289 deletions
diff --git a/src/libcore/core.rs b/src/libcore/core.rs
index fdf53524188..cd7252be9ec 100644
--- a/src/libcore/core.rs
+++ b/src/libcore/core.rs
@@ -31,7 +31,8 @@ import f32::num;
 import f64::num;
 import num::num;
 import ops::{const, copy, send, owned};
-import ops::{add, sub, mul, div, modulo, neg, bitops, index};
+import ops::{add, sub, mul, div, modulo, neg, bitand, bitor, bitxor, shl};
+import ops::{shr, index};
 
 export path, option, some, none, unreachable;
 export extensions;
diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs
index 61efe704974..2a05aeb72c2 100644
--- a/src/libcore/ops.rs
+++ b/src/libcore/ops.rs
@@ -1,64 +1,96 @@
 // Core operators and kinds.
 
+#[cfg(notest)]
 #[lang="const"]
 trait const {
     // Empty.
 }
 
+#[cfg(notest)]
 #[lang="copy"]
 trait copy {
     // Empty.
 }
 
+#[cfg(notest)]
 #[lang="send"]
 trait send {
     // Empty.
 }
 
+#[cfg(notest)]
 #[lang="owned"]
 trait owned {
     // Empty.
 }
 
+#[cfg(notest)]
 #[lang="add"]
 trait add<RHS,Result> {
     pure fn add(rhs: RHS) -> Result;
 }
 
+#[cfg(notest)]
 #[lang="sub"]
 trait sub<RHS,Result> {
     pure fn sub(rhs: RHS) -> Result;
 }
 
+#[cfg(notest)]
 #[lang="mul"]
 trait mul<RHS,Result> {
     pure fn mul(rhs: RHS) -> Result;
 }
 
+#[cfg(notest)]
 #[lang="div"]
 trait div<RHS,Result> {
     pure fn div(rhs: RHS) -> Result;
 }
 
+#[cfg(notest)]
 #[lang="modulo"]
 trait modulo<RHS,Result> {
     pure fn modulo(rhs: RHS) -> Result;
 }
 
+#[cfg(notest)]
 #[lang="neg"]
-trait neg<RHS,Result> {
-    pure fn neg(rhs: RHS) -> Result;
+trait neg<Result> {
+    pure fn neg() -> Result;
 }
 
-#[lang="bitops"]
-trait bitops<RHS,BitCount,Result> {
-    pure fn and(rhs: RHS) -> Result;
-    pure fn or(rhs: RHS) -> Result;
-    pure fn xor(rhs: RHS) -> Result;
-    pure fn shl(n: BitCount) -> Result;
-    pure fn shr(n: BitCount) -> Result;
+#[cfg(notest)]
+#[lang="bitand"]
+trait bitand<RHS,Result> {
+    pure fn bitand(rhs: RHS) -> Result;
 }
 
+#[cfg(notest)]
+#[lang="bitor"]
+trait bitor<RHS,Result> {
+    pure fn bitor(rhs: RHS) -> Result;
+}
+
+#[cfg(notest)]
+#[lang="bitxor"]
+trait bitxor<RHS,Result> {
+    pure fn bitxor(rhs: RHS) -> Result;
+}
+
+#[cfg(notest)]
+#[lang="shl"]
+trait shl<RHS,Result> {
+    pure fn shl(rhs: RHS) -> Result;
+}
+
+#[cfg(notest)]
+#[lang="shr"]
+trait shr<RHS,Result> {
+    pure fn shr(rhs: RHS) -> Result;
+}
+
+#[cfg(notest)]
 #[lang="index"]
 trait index<Index,Result> {
     pure fn index(index: Index) -> Result;
diff --git a/src/libstd/ebml.rs b/src/libstd/ebml.rs
index d29727046d8..8dbb39d1831 100644
--- a/src/libstd/ebml.rs
+++ b/src/libstd/ebml.rs
@@ -27,6 +27,8 @@ export serializer;
 export ebml_deserializer;
 export deserializer;
 export with_doc_data;
+export get_doc;
+export extensions;
 
 type ebml_tag = {id: uint, size: uint};
 
@@ -40,6 +42,24 @@ type doc = {data: @~[u8], start: uint, end: uint};
 
 type tagged_doc = {tag: uint, doc: doc};
 
+trait get_doc {
+    fn [](tag: uint) -> doc;
+}
+
+impl extensions of get_doc for doc {
+    fn [](tag: uint) -> doc {
+        get_doc(self, tag)
+    }
+}
+
+impl extensions of ops::index<uint,doc> for doc {
+    pure fn index(&&tag: uint) -> doc {
+        unchecked {
+            get_doc(self, tag)
+        }
+    }
+}
+
 fn vuint_at(data: &[u8], start: uint) -> {val: uint, next: uint} {
     let a = data[start];
     if a & 0x80u8 != 0u8 {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 933e693345d..b7cb85a5610 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -773,6 +773,59 @@ enum inlined_item {
     ii_dtor(class_dtor, ident, ~[ty_param], def_id /* parent id */)
 }
 
+// Convenience functions
+
+pure fn simple_path(id: ident, span: span) -> @path {
+    @{span: span,
+      global: false,
+      idents: ~[id],
+      rp: none,
+      types: ~[]}
+}
+
+pure fn empty_span() -> span {
+    {lo: 0, hi: 0, expn_info: none}
+}
+
+// Convenience implementations
+
+// Remove after snapshot!
+trait path_concat {
+    pure fn +(&&id: ident) -> @path;
+}
+
+// Remove after snapshot!
+impl methods of path_concat for ident {
+    pure fn +(&&id: ident) -> @path {
+        simple_path(self, empty_span()) + id
+    }
+}
+
+impl methods of ops::add<ident,@path> for ident {
+    pure fn add(&&id: ident) -> @path {
+        simple_path(self, empty_span()) + id
+    }
+}
+
+// Remove after snapshot!
+impl methods of path_concat for @path {
+    pure fn +(&&id: ident) -> @path {
+        @{
+            idents: vec::append_one(self.idents, id)
+            with *self
+        }
+    }
+}
+
+impl methods of ops::add<ident,@path> for @path {
+    pure fn add(&&id: ident) -> @path {
+        @{
+            idents: vec::append_one(self.idents, id)
+            with *self
+        }
+    }
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 26e0c70442d..98b42ce79ae 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -87,6 +87,22 @@ pure fn binop_to_str(op: binop) -> ~str {
     }
 }
 
+pure fn binop_to_method_name(op: binop) -> option<~str> {
+    alt op {
+      add { ret some(~"add"); }
+      subtract { ret some(~"sub"); }
+      mul { ret some(~"mul"); }
+      div { ret some(~"div"); }
+      rem { ret some(~"modulo"); }
+      bitxor { ret some(~"bitxor"); }
+      bitand { ret some(~"bitand"); }
+      bitor { ret some(~"bitor"); }
+      shl { ret some(~"shl"); }
+      shr { ret some(~"shr"); }
+      and | or | eq | lt | le | ne | ge | gt { ret none; }
+    }
+}
+
 pure fn lazy_binop(b: binop) -> bool {
     alt b { and { true } or { true } _ { false } }
 }
diff --git a/src/libsyntax/ext/pipes/ast_builder.rs b/src/libsyntax/ext/pipes/ast_builder.rs
index f367fb63985..bb5b35233cd 100644
--- a/src/libsyntax/ext/pipes/ast_builder.rs
+++ b/src/libsyntax/ext/pipes/ast_builder.rs
@@ -31,23 +31,6 @@ fn empty_span() -> span {
     {lo: 0, hi: 0, expn_info: none}
 }
 
-trait path_concat {
-    fn +(id: ident) -> @ast::path;
-}
-
-impl methods of path_concat for ident {
-    fn +(id: ident) -> @ast::path {
-        path(self, empty_span()) + id
-    }
-}
-
-impl methods of path_concat for @ast::path {
-    fn +(id: ident) -> @ast::path {
-        @{idents: vec::append_one(self.idents, id)
-          with *self}
-    }
-}
-
 trait append_types {
     fn add_ty(ty: @ast::ty) -> @ast::path;
     fn add_tys(+tys: ~[@ast::ty]) -> @ast::path;
diff --git a/src/libsyntax/ext/pipes/pipec.rs b/src/libsyntax/ext/pipes/pipec.rs
index 392e6ba392a..c1274d12f1d 100644
--- a/src/libsyntax/ext/pipes/pipec.rs
+++ b/src/libsyntax/ext/pipes/pipec.rs
@@ -16,12 +16,12 @@ import ext::base::{mk_ctxt, ext_ctxt};
 import parse;
 import parse::*;
 import proto::*;
+import ast::methods;
 
 import ast_builder::append_types;
 import ast_builder::ast_builder;
 import ast_builder::methods;
 import ast_builder::path;
-import ast_builder::path_concat;
 
 // Transitional reexports so qquote can find the paths it is looking for
 mod syntax {
diff --git a/src/rustc/driver/driver.rs b/src/rustc/driver/driver.rs
index 6c7d24973b9..ee0f28c9a0e 100644
--- a/src/rustc/driver/driver.rs
+++ b/src/rustc/driver/driver.rs
@@ -170,7 +170,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
                              session::sess_os_to_meta_os(sess.targ_cfg.os),
                              sess.opts.static));
 
-    time(time_passes, ~"language item collection", ||
+    let lang_items = time(time_passes, ~"language item collection", ||
          middle::lang_items::collect_language_items(crate, sess));
 
     let { def_map: def_map,
@@ -178,7 +178,7 @@ fn compile_upto(sess: session, cfg: ast::crate_cfg,
           impl_map: impl_map,
           trait_map: trait_map } =
         time(time_passes, ~"resolution", ||
-             middle::resolve3::resolve_crate(sess, ast_map, crate));
+             middle::resolve3::resolve_crate(sess, lang_items, crate));
 
     let freevars = time(time_passes, ~"freevar finding", ||
         freevars::annotate_freevars(def_map, crate));
diff --git a/src/rustc/middle/astencode.rs b/src/rustc/middle/astencode.rs
index d47598cd8cb..84ada7726ab 100644
--- a/src/rustc/middle/astencode.rs
+++ b/src/rustc/middle/astencode.rs
@@ -13,6 +13,8 @@ import std::ebml;
 import std::ebml::writer;
 import std::ebml::serializer;
 import std::ebml::deserializer;
+import std::ebml::extensions;
+import std::ebml::get_doc;
 import std::map::hashmap;
 import std::serialization::serializer;
 import std::serialization::deserializer;
@@ -285,7 +287,7 @@ fn simplify_ast(ii: ast::inlined_item) -> ast::inlined_item {
 }
 
 fn decode_ast(par_doc: ebml::doc) -> ast::inlined_item {
-    let chi_doc = par_doc[c::tag_tree];
+    let chi_doc = par_doc[c::tag_tree as uint];
     let d = ebml::ebml_deserializer(chi_doc);
     ast::deserialize_inlined_item(d)
 }
@@ -776,15 +778,11 @@ fn encode_side_tables_for_id(ecx: @e::encode_ctxt,
 
 trait doc_decoder_helpers {
     fn as_int() -> int;
-    fn [](tag: c::astencode_tag) -> ebml::doc;
     fn opt_child(tag: c::astencode_tag) -> option<ebml::doc>;
 }
 
 impl decoder of doc_decoder_helpers for ebml::doc {
     fn as_int() -> int { ebml::doc_as_u64(self) as int }
-    fn [](tag: c::astencode_tag) -> ebml::doc {
-        ebml::get_doc(self, tag as uint)
-    }
     fn opt_child(tag: c::astencode_tag) -> option<ebml::doc> {
         ebml::maybe_get_doc(self, tag as uint)
     }
@@ -843,9 +841,9 @@ impl decoder of ebml_deserializer_decoder_helpers
 fn decode_side_tables(xcx: extended_decode_ctxt,
                       ast_doc: ebml::doc) {
     let dcx = xcx.dcx;
-    let tbl_doc = ast_doc[c::tag_table];
+    let tbl_doc = ast_doc[c::tag_table as uint];
     for ebml::docs(tbl_doc) |tag, entry_doc| {
-        let id0 = entry_doc[c::tag_table_id].as_int();
+        let id0 = entry_doc[c::tag_table_id as uint].as_int();
         let id = xcx.tr_id(id0);
 
         #debug[">> Side table document with tag 0x%x \
@@ -855,7 +853,7 @@ fn decode_side_tables(xcx: extended_decode_ctxt,
         if tag == (c::tag_table_mutbl as uint) {
             dcx.maps.mutbl_map.insert(id, ());
         } else {
-            let val_doc = entry_doc[c::tag_table_val];
+            let val_doc = entry_doc[c::tag_table_val as uint];
             let val_dsr = ebml::ebml_deserializer(val_doc);
             if tag == (c::tag_table_def as uint) {
                 let def = decode_def(xcx, val_doc);
@@ -916,7 +914,7 @@ fn encode_item_ast(ebml_w: ebml::writer, item: @ast::item) {
 
 #[cfg(test)]
 fn decode_item_ast(par_doc: ebml::doc) -> @ast::item {
-    let chi_doc = par_doc[c::tag_tree];
+    let chi_doc = par_doc[c::tag_tree as uint];
     let d = ebml::ebml_deserializer(chi_doc);
     @ast::deserialize_item(d)
 }
diff --git a/src/rustc/middle/lang_items.rs b/src/rustc/middle/lang_items.rs
index 2353da51f98..0aaacee019a 100644
--- a/src/rustc/middle/lang_items.rs
+++ b/src/rustc/middle/lang_items.rs
@@ -34,7 +34,11 @@ class LanguageItems {
     let mut div_trait: option<def_id>;
     let mut modulo_trait: option<def_id>;
     let mut neg_trait: option<def_id>;
-    let mut bitops_trait: option<def_id>;
+    let mut bitxor_trait: option<def_id>;
+    let mut bitand_trait: option<def_id>;
+    let mut bitor_trait: option<def_id>;
+    let mut shl_trait: option<def_id>;
+    let mut shr_trait: option<def_id>;
     let mut index_trait: option<def_id>;
 
     new() {
@@ -49,7 +53,11 @@ class LanguageItems {
         self.div_trait = none;
         self.modulo_trait = none;
         self.neg_trait = none;
-        self.bitops_trait = none;
+        self.bitxor_trait = none;
+        self.bitand_trait = none;
+        self.bitor_trait = none;
+        self.shl_trait = none;
+        self.shr_trait = none;
         self.index_trait = none;
     }
 }
@@ -84,7 +92,11 @@ class LanguageItemCollector {
         self.item_refs.insert(~"div", &mut self.items.div_trait);
         self.item_refs.insert(~"modulo", &mut self.items.modulo_trait);
         self.item_refs.insert(~"neg", &mut self.items.neg_trait);
-        self.item_refs.insert(~"bitops", &mut self.items.bitops_trait);
+        self.item_refs.insert(~"bitxor", &mut self.items.bitxor_trait);
+        self.item_refs.insert(~"bitand", &mut self.items.bitand_trait);
+        self.item_refs.insert(~"bitor", &mut self.items.bitor_trait);
+        self.item_refs.insert(~"shl", &mut self.items.shl_trait);
+        self.item_refs.insert(~"shr", &mut self.items.shr_trait);
         self.item_refs.insert(~"index", &mut self.items.index_trait);
     }
 
@@ -125,8 +137,8 @@ class LanguageItemCollector {
                     some(original_def_id)
                             if original_def_id != item_def_id => {
 
-                        self.session.warn(#fmt("duplicate entry for `%s`",
-                                               value));
+                        self.session.err(#fmt("duplicate entry for `%s`",
+                                              value));
                     }
                     some(_) | none => {
                         // OK.
@@ -184,7 +196,7 @@ class LanguageItemCollector {
         for self.item_refs.each |key, item_ref| {
             alt copy *item_ref {
                 none => {
-                    self.session.warn(#fmt("no item found for `%s`", key));
+                    self.session.err(#fmt("no item found for `%s`", key));
                 }
                 some(did) => {
                     // OK.
diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs
index 8af823ac072..8b40d8136ab 100644
--- a/src/rustc/middle/resolve3.rs
+++ b/src/rustc/middle/resolve3.rs
@@ -3,33 +3,38 @@ import metadata::csearch::{each_path, get_impls_for_mod};
 import metadata::csearch::{get_method_names_if_trait, lookup_defs};
 import metadata::cstore::find_use_stmt_cnum;
 import metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
+import middle::lang_items::LanguageItems;
 import middle::lint::{deny, allow, forbid, level, unused_imports, warn};
-import syntax::ast::{_mod, arm, blk, bound_const, bound_copy, bound_trait};
-import syntax::ast::{bound_owned};
-import syntax::ast::{bound_send, capture_clause, class_ctor, class_dtor};
-import syntax::ast::{class_member, class_method, crate, crate_num, decl_item};
-import syntax::ast::{def, def_arg, def_binding, def_class, def_const, def_fn};
+import syntax::ast::{_mod, add, arm, bitand, bitor, bitxor, blk, bound_const};
+import syntax::ast::{bound_copy, bound_owned, bound_send, bound_trait};
+import syntax::ast::{capture_clause, class_ctor, class_dtor, class_member};
+import syntax::ast::{class_method, crate, crate_num, decl_item, def, def_arg};
+import syntax::ast::{def_binding, def_class, def_const, def_fn};
 import syntax::ast::{def_foreign_mod, def_id, def_local, def_mod};
 import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param,
                      def_typaram_binder};
 import syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
 import syntax::ast::{expr_binary, expr_cast, expr_field, expr_fn};
 import syntax::ast::{expr_fn_block, expr_index, expr_new, expr_path};
+import syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
+import syntax::ast::{def_upvar, def_use, def_variant, div, eq, expr};
+import syntax::ast::{expr_assign_op, expr_binary, expr_cast, expr_field};
+import syntax::ast::{expr_fn, expr_fn_block, expr_index, expr_new, expr_path};
 import syntax::ast::{expr_struct, expr_unary, fn_decl, foreign_item};
-import syntax::ast::{foreign_item_fn, ident, trait_ref, impure_fn};
+import syntax::ast::{foreign_item_fn, ge, gt, ident, trait_ref, impure_fn};
 import syntax::ast::{instance_var, item, item_class, item_const, item_enum};
 import syntax::ast::{item_fn, item_mac, item_foreign_mod, item_impl};
-import syntax::ast::{item_mod, item_trait, item_ty, local, local_crate};
-import syntax::ast::{method, node_id, pat, pat_enum, pat_ident};
-import syntax::ast::{path, prim_ty, pat_box, pat_uniq, pat_lit, pat_range};
-import syntax::ast::{pat_rec, pat_tup, pat_wild, stmt_decl};
-import syntax::ast::{ty, ty_bool, ty_char, ty_f, ty_f32, ty_f64};
-import syntax::ast::{ty_float, ty_i, ty_i16, ty_i32, ty_i64, ty_i8, ty_int};
-import syntax::ast::{ty_param, ty_path, ty_str, ty_u, ty_u16, ty_u32, ty_u64};
-import syntax::ast::{ty_u8, ty_uint, variant, view_item, view_item_export};
-import syntax::ast::{view_item_import, view_item_use, view_path_glob};
-import syntax::ast::{view_path_list, view_path_simple};
-import syntax::ast::{required, provided};
+import syntax::ast::{item_mod, item_trait, item_ty, le, local, local_crate};
+import syntax::ast::{lt, method, mul, ne, neg, node_id, pat, pat_enum};
+import syntax::ast::{pat_ident, path, prim_ty, pat_box, pat_uniq, pat_lit};
+import syntax::ast::{pat_range, pat_rec, pat_tup, pat_wild, provided};
+import syntax::ast::{required, rem, shl, stmt_decl, subtract, ty, ty_bool};
+import syntax::ast::{ty_char, ty_f, ty_f32, ty_f64, ty_float, ty_i, ty_i16};
+import syntax::ast::{ty_i32, ty_i64, ty_i8, ty_int, ty_param, ty_path};
+import syntax::ast::{ty_str, ty_u, ty_u16, ty_u32, ty_u64, ty_u8, ty_uint};
+import syntax::ast::{variant, view_item, view_item_export, view_item_import};
+import syntax::ast::{view_item_use, view_path_glob, view_path_list};
+import syntax::ast::{view_path_simple};
 import syntax::ast_util::{def_id_of_def, dummy_sp, local_def, new_def_hash};
 import syntax::ast_util::{walk_pat};
 import syntax::attr::{attr_metas, contains_name};
@@ -47,8 +52,7 @@ import str::{connect, split_str};
 import vec::pop;
 
 import std::list::{cons, list, nil};
-import std::map::{hashmap, int_hash};
-import ASTMap = syntax::ast_map::map;
+import std::map::{hashmap, int_hash, str_hash};
 import str_eq = str::eq;
 
 // Definition mapping
@@ -608,7 +612,7 @@ class PrimitiveTypeTable {
 /// The main resolver class.
 class Resolver {
     let session: session;
-    let ast_map: ASTMap;
+    let lang_items: LanguageItems;
     let crate: @crate;
 
     let atom_table: @AtomTable;
@@ -655,9 +659,9 @@ class Resolver {
     let export_map: ExportMap;
     let trait_map: TraitMap;
 
-    new(session: session, ast_map: ASTMap, crate: @crate) {
+    new(session: session, lang_items: LanguageItems, crate: @crate) {
         self.session = session;
-        self.ast_map = ast_map;
+        self.lang_items = copy lang_items;
         self.crate = crate;
 
         self.atom_table = @AtomTable();
@@ -4312,16 +4316,61 @@ class Resolver {
 
     fn record_candidate_traits_for_expr_if_necessary(expr: @expr) {
         alt expr.node {
-            expr_field(_, ident, _) {
+            expr_field(_, ident, _) => {
                 let atom = (*self.atom_table).intern(ident);
                 let traits = self.search_for_traits_containing_method(atom);
                 self.trait_map.insert(expr.id, traits);
             }
-            _ {
+            expr_binary(add, _, _) | expr_assign_op(add, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.add_trait);
+            }
+            expr_binary(subtract, _, _) | expr_assign_op(subtract, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.sub_trait);
+            }
+            expr_binary(mul, _, _) | expr_assign_op(mul, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.mul_trait);
+            }
+            expr_binary(div, _, _) | expr_assign_op(div, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.div_trait);
+            }
+            expr_binary(rem, _, _) | expr_assign_op(rem, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.modulo_trait);
+            }
+            expr_binary(bitxor, _, _) | expr_assign_op(bitxor, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.bitxor_trait);
+            }
+            expr_binary(bitand, _, _) | expr_assign_op(bitand, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.bitand_trait);
+            }
+            expr_binary(bitor, _, _) | expr_assign_op(bitor, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.bitor_trait);
+            }
+            expr_binary(shl, _, _) | expr_assign_op(shl, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.shl_trait);
+            }
+            expr_binary(shr, _, _) | expr_assign_op(shr, _, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.shr_trait);
+            }
+            expr_unary(neg, _) => {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.neg_trait);
+            }
+            expr_index(*) {
+                self.add_fixed_trait_for_expr(expr.id,
+                                              self.lang_items.index_trait);
+            }
+            _ => {
                 // Nothing to do.
-                //
-                // XXX: Handle more here... operator overloading, placement
-                // new, etc.
             }
         }
     }
@@ -4414,6 +4463,12 @@ class Resolver {
         }
     }
 
+    fn add_fixed_trait_for_expr(expr_id: node_id, +trait_id: option<def_id>) {
+        let traits = @dvec();
+        traits.push(trait_id.get());
+        self.trait_map.insert(expr_id, traits);
+    }
+
     fn record_def(node_id: node_id, def: def) {
         #debug("(recording def) recording %? for %?", def, node_id);
         self.def_map.insert(node_id, def);
@@ -4622,13 +4677,13 @@ class Resolver {
 }
 
 /// Entry point to crate resolution.
-fn resolve_crate(session: session, ast_map: ASTMap, crate: @crate)
+fn resolve_crate(session: session, lang_items: LanguageItems, crate: @crate)
               -> { def_map: DefMap,
                    exp_map: ExportMap,
                    impl_map: ImplMap,
                    trait_map: TraitMap } {
 
-    let resolver = @Resolver(session, ast_map, crate);
+    let resolver = @Resolver(session, lang_items, crate);
     (*resolver).resolve(resolver);
     ret {
         def_map: resolver.def_map,
diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs
index d99e35ce418..891bbca5d19 100644
--- a/src/rustc/middle/ty.rs
+++ b/src/rustc/middle/ty.rs
@@ -1472,6 +1472,30 @@ impl operators for kind {
     }
 }
 
+impl operators of ops::bitand<kind,kind> for kind {
+    pure fn bitand(other: kind) -> kind {
+        unchecked {
+            lower_kind(self, other)
+        }
+    }
+}
+
+impl operators of ops::bitor<kind,kind> for kind {
+    pure fn bitor(other: kind) -> kind {
+        unchecked {
+            raise_kind(self, other)
+        }
+    }
+}
+
+impl operators of ops::sub<kind,kind> for kind {
+    pure fn sub(other: kind) -> kind {
+        unchecked {
+            kind_(*self & !*other)
+        }
+    }
+}
+
 // Using these query functions is preferable to direct comparison or matching
 // against the kind constants, as we may modify the kind hierarchy in the
 // future.
diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs
index ce7536b5bf9..d472991d85f 100644
--- a/src/rustc/middle/typeck/check.rs
+++ b/src/rustc/middle/typeck/check.rs
@@ -961,14 +961,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
         ret if_bot;
     }
 
-    fn binop_method(op: ast::binop) -> option<~str> {
-        alt op {
-          ast::add | ast::subtract | ast::mul | ast::div | ast::rem |
-          ast::bitxor | ast::bitand | ast::bitor | ast::shl | ast::shr
-          { some(ast_util::binop_to_str(op)) }
-          _ { none }
-        }
-    }
     fn lookup_op_method(fcx: @fn_ctxt, op_ex: @ast::expr,
                         self_ex: @ast::expr, self_t: ty::t,
                         opname: ~str, args: ~[@ast::expr])
@@ -1041,7 +1033,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
                         lhs_expr: @ast::expr, lhs_resolved_t: ty::t,
                         op: ast::binop, rhs: @ast::expr) -> (ty::t, bool) {
         let tcx = fcx.ccx.tcx;
-        alt binop_method(op) {
+        alt ast_util::binop_to_method_name(op) {
           some(name) {
             alt lookup_op_method(fcx, ex,
                                  lhs_expr, lhs_resolved_t,
@@ -1365,7 +1357,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
             oprnd_t = structurally_resolved_type(fcx, oprnd.span, oprnd_t);
             if !(ty::type_is_integral(oprnd_t) ||
                  ty::get(oprnd_t).struct == ty::ty_bool) {
-                oprnd_t = check_user_unop(fcx, ~"!", ~"!", expr,
+                oprnd_t = check_user_unop(fcx, ~"!", ~"not", expr,
                                          oprnd, oprnd_t);
             }
           }
@@ -1373,7 +1365,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
             oprnd_t = structurally_resolved_type(fcx, oprnd.span, oprnd_t);
             if !(ty::type_is_integral(oprnd_t) ||
                  ty::type_is_fp(oprnd_t)) {
-                oprnd_t = check_user_unop(fcx, ~"-", ~"unary-", expr,
+                oprnd_t = check_user_unop(fcx, ~"-", ~"neg", expr,
                                          oprnd, oprnd_t);
             }
           }
@@ -1831,7 +1823,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
           none {
             let resolved = structurally_resolved_type(fcx, expr.span,
                                                       raw_base_t);
-            alt lookup_op_method(fcx, expr, base, resolved, ~"[]",
+            alt lookup_op_method(fcx, expr, base, resolved, ~"index",
                                  ~[idx]) {
               some((ret_ty, _)) { fcx.write_ty(id, ret_ty); }
               _ {
diff --git a/src/rustc/middle/typeck/check/method.rs b/src/rustc/middle/typeck/check/method.rs
index 7f269944059..a9ecf5e092e 100644
--- a/src/rustc/middle/typeck/check/method.rs
+++ b/src/rustc/middle/typeck/check/method.rs
@@ -447,8 +447,7 @@ class lookup {
         // Add trait methods.
         alt self.fcx.ccx.trait_map.find(self.expr.id) {
             none {
-                // XXX: This particular operation is not yet trait-ified;
-                // leave it alone for now.
+                // Should only happen for placement new right now.
             }
             some(trait_ids) {
                 for (*trait_ids).each |trait_id| {
diff --git a/src/test/bench/shootout-mandelbrot.rs b/src/test/bench/shootout-mandelbrot.rs
index 6cf51513c77..8a3a9371adb 100644
--- a/src/test/bench/shootout-mandelbrot.rs
+++ b/src/test/bench/shootout-mandelbrot.rs
@@ -16,24 +16,31 @@ use std;
 import io::writer_util;
 import std::map::hashmap;
 
-type cmplx = {re: f64, im: f64};
-type line = {i: uint, b: ~[u8]};
-
-trait times_and_plus {
-    fn *(x: cmplx) -> cmplx;
-    fn +(x: cmplx) -> cmplx;
+struct cmplx {
+    re: f64;
+    im: f64;
 }
 
-impl arith of times_and_plus for cmplx {
-    fn *(x: cmplx) -> cmplx {
-        {re: self.re*x.re - self.im*x.im, im: self.re*x.im + self.im*x.re}
+impl cmplx : ops::mul<cmplx,cmplx> {
+    pure fn mul(x: cmplx) -> cmplx {
+        cmplx {
+            re: self.re*x.re - self.im*x.im,
+            im: self.re*x.im + self.im*x.re
+        }
     }
+}
 
-    fn +(x: cmplx) -> cmplx {
-        {re: self.re + x.re, im: self.im + x.im}
+impl cmplx : ops::add<cmplx,cmplx> {
+    pure fn add(x: cmplx) -> cmplx {
+        cmplx {
+            re: self.re + x.re,
+            im: self.im + x.im
+        }
     }
 }
 
+type line = {i: uint, b: ~[u8]};
+
 pure fn cabs(x: cmplx) -> f64
 {
     x.re*x.re + x.im*x.im
@@ -41,7 +48,7 @@ pure fn cabs(x: cmplx) -> f64
 
 fn mb(x: cmplx) -> bool
 {
-    let mut z = {re: 0f64, im: 0f64};
+    let mut z = cmplx {re: 0f64, im: 0f64};
     let mut i = 0;
     let mut in = true;
     while i < 50 {
@@ -59,7 +66,7 @@ fn fillbyte(x: cmplx, incr: f64) -> u8 {
     let mut rv = 0_u8;
     let mut i = 0_u8;
     while i < 8_u8 {
-        let z = {re: x.re + (i as f64)*incr, im: x.im};
+        let z = cmplx {re: x.re + (i as f64)*incr, im: x.im};
         if mb(z) {
             rv += 1_u8 << (7_u8 - i);
         }
@@ -75,7 +82,7 @@ fn chanmb(i: uint, size: uint, ch: comm::chan<line>) -> ()
     let y = incr*(i as f64) - 1f64;
     let xincr = 8f64*incr;
     for uint::range(0_u, size/8_u) |j| {
-        let x = {re: xincr*(j as f64) - 1.5f64, im: y};
+        let x = cmplx {re: xincr*(j as f64) - 1.5f64, im: y};
         vec::push(crv, fillbyte(x, incr));
     };
     comm::send(ch, {i:i, b:crv});
diff --git a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
index 4e084ba35c3..00ce2485b68 100644
--- a/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
+++ b/src/test/compile-fail/borrowck-loan-rcvr-overloaded-op.rs
@@ -1,25 +1,30 @@
-type point = { x: int, y: int };
+struct Point { 
+    x: int;
+    y: int;
+}
 
-trait add_and_times {
-    pure fn +(z: int) -> int;
-    fn *(z: int) -> int;
+impl Point : ops::add<int,int> {
+    pure fn add(&&z: int) -> int {
+        self.x + self.y + z
+    }
 }
 
-impl foo of add_and_times for point {
-    pure fn +(z: int) -> int { self.x + self.y + z }
-    fn *(z: int) -> int { self.x * self.y * z }
+impl Point {
+    fn times(z: int) -> int {
+        self.x * self.y * z
+    }
 }
 
 fn a() {
-    let mut p = {x: 3, y: 4};
+    let mut p = Point {x: 3, y: 4};
 
     // ok (we can loan out rcvr)
     p + 3;
-    p * 3;
+    p.times(3);
 }
 
 fn b() {
-    let mut p = {x: 3, y: 4};
+    let mut p = Point {x: 3, y: 4};
 
     // Here I create an outstanding loan and check that we get conflicts:
 
@@ -27,20 +32,20 @@ fn b() {
     //~^ NOTE prior loan as mutable granted here
 
     p + 3; //~ ERROR loan of mutable local variable as immutable conflicts with prior loan
-    p * 3; //~ ERROR loan of mutable local variable as immutable conflicts with prior loan
+    p.times(3); //~ ERROR loan of mutable local variable as immutable conflicts with prior loan
 }
 
 fn c() {
     // Here the receiver is in aliased memory and hence we cannot
     // consider it immutable:
-    let q = @mut {x: 3, y: 4};
+    let q = @mut Point {x: 3, y: 4};
 
     // ...this is ok for pure fns
     *q + 3;
 
 
     // ...but not impure fns
-    *q * 3; //~ ERROR illegal borrow unless pure: creating immutable alias to aliasable, mutable memory
+    (*q).times(3); //~ ERROR illegal borrow unless pure: creating immutable alias to aliasable, mutable memory
     //~^ NOTE impure due to access to impure function
 }
 
diff --git a/src/test/compile-fail/no-core-attribute.rs b/src/test/compile-fail/no-core-attribute.rs
deleted file mode 100644
index 7ed010476cd..00000000000
--- a/src/test/compile-fail/no-core-attribute.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// error-pattern:unresolved name: debug
-#[no_core];
-
-fn main() {
-    log(debug, 0);
-}
\ No newline at end of file
diff --git a/src/test/compile-fail/pure-overloaded-op.rs b/src/test/compile-fail/pure-overloaded-op.rs
deleted file mode 100644
index c07512e20f5..00000000000
--- a/src/test/compile-fail/pure-overloaded-op.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-type point = { x: int, y: int };
-
-trait operators {
-    pure fn +(z: int) -> int;
-    fn *(z: int) -> int;
-    fn [](z: int) -> int;
-    fn unary-() -> int;
-}
-
-impl foo of operators for point {
-    // expr_binary
-    pure fn +(z: int) -> int { self.x + self.y + z }
-    fn *(z: int) -> int { self.x * self.y * z }
-
-    // expr_index
-    fn [](z: int) -> int { self.x * self.y * z }
-
-    // expr_unary
-    fn unary-() -> int { -(self.x * self.y) }
-}
-
-pure fn a(p: point) -> int { p + 3 }
-
-pure fn b(p: point) -> int { p * 3 }
-//~^ ERROR access to impure function prohibited in pure context
-
-pure fn c(p: point) -> int { p[3] }
-//~^ ERROR access to impure function prohibited in pure context
-
-pure fn d(p: point) -> int { -p }
-//~^ ERROR access to impure function prohibited in pure context
-
-fn main() {}
diff --git a/src/test/compile-fail/selftype-astparam.rs b/src/test/compile-fail/selftype-astparam.rs
index 8136e0c7440..df7f8cd6cad 100644
--- a/src/test/compile-fail/selftype-astparam.rs
+++ b/src/test/compile-fail/selftype-astparam.rs
@@ -1,12 +1,12 @@
 iface add {
-    fn +(++x: self) -> self;
+    fn plus(++x: self) -> self;
 }
 
 impl of add for int {
-    fn +(++x: int) -> int { self + x }
+    fn plus(++x: int) -> int { self + x }
 }
 
-fn do_add<A:add>(x: A, y: A) -> A { x + y }
+fn do_add<A:add>(x: A, y: A) -> A { x.plus(y) }
 
 fn main() {
     let x = 3 as add;
diff --git a/src/test/compile-fail/selftype-ifacetype.rs b/src/test/compile-fail/selftype-ifacetype.rs
index bbaf49e85bf..a4bd394d529 100644
--- a/src/test/compile-fail/selftype-ifacetype.rs
+++ b/src/test/compile-fail/selftype-ifacetype.rs
@@ -1,9 +1,9 @@
 iface add {
-    fn +(x: self) -> self;
+    fn plus(x: self) -> self;
 }
 
 fn do_add(x: add, y: add) -> add {
-    x + y //~ ERROR can not call a method that contains a self type through a boxed iface
+    x.plus(y) //~ ERROR can not call a method that contains a self type through a boxed iface
 }
 
 fn main() {}
diff --git a/src/test/run-pass/operator-overloading-leaks.rs b/src/test/run-pass/operator-overloading-leaks.rs
deleted file mode 100644
index c3a0dcec7df..00000000000
--- a/src/test/run-pass/operator-overloading-leaks.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-// The cases commented as "Leaks" need to not leak. Issue #2581
-
-trait minus_and_foo<T> {
-    fn -(x: &[T]) -> ~[T];
-    fn foo(x: &[T]) -> ~[T];
-}
-
-impl methods<T: copy> of minus_and_foo<T> for ~[T] {
-    fn -(x: &[T]) -> ~[T] {
-        ~[x[0], x[0], x[0]]
-    }
-
-    fn foo(x: &[T]) -> ~[T] {
-        ~[x[0], x[0], x[0]]
-    }
-}
-
-trait plus_uniq<T> {
-    fn +(rhs: ~T) -> ~T;
-}
-
-impl methods<T: copy> of plus_uniq<T> for ~T {
-    fn +(rhs: ~T) -> ~T {
-        rhs
-    }
-}
-
-trait minus {
-    fn -(rhs: ~int) -> ~int;
-}
-
-impl methods of minus for ~int {
-    fn -(rhs: ~int) -> ~int {
-        ~(*self - *rhs)
-    }
-}
-
-trait plus_boxed {
-    fn +(rhs: @int) -> @int;
-}
-
-impl methods of plus_boxed for @int {
-    fn +(rhs: @int) -> @int {
-        @(*self + *rhs)
-    }
-}
-
-fn main() {
-    // leaks
-    let mut bar = ~[1, 2, 3];
-    bar -= ~[3, 2, 1];
-    bar -= ~[4, 5, 6];
-    
-    io::println(#fmt("%?", bar));
-
-    // okay
-    let mut bar = ~[1, 2, 3];
-    bar = bar.foo(~[3, 2, 1]);
-    bar = bar.foo(~[4, 5, 6]);
-
-    io::println(#fmt("%?", bar));
-
-    // okay
-    let mut bar = ~[1, 2, 3];
-    bar = bar - ~[3, 2, 1];
-    bar = bar - ~[4, 5, 6];
-
-    io::println(#fmt("%?", bar));
-
-    // Leaks
-    let mut bar = ~1;
-    bar += ~2;
-    bar += ~3;
-    
-    io:: println(#fmt("%?", bar));
-
-    // Leaks
-    let mut bar = ~1;
-    bar -= ~2;
-    bar -= ~3;
-    
-    io:: println(#fmt("%?", bar));
-
-    // Leaks
-    let mut bar = @1;
-    bar += @2;
-    bar += @3;
-    
-    io:: println(#fmt("%?", bar));
-
-}
diff --git a/src/test/run-pass/operator-overloading.rs b/src/test/run-pass/operator-overloading.rs
index fb8cdd47f78..1404ee54331 100644
--- a/src/test/run-pass/operator-overloading.rs
+++ b/src/test/run-pass/operator-overloading.rs
@@ -1,33 +1,38 @@
-type point = {x: int, y: int};
-
-trait ops {
-    fn +(other: point) -> point;
-    fn -(other: point) -> point;
-    fn unary-() -> point;
-    fn [](x: bool) -> int;
+struct Point {
+    x: int;
+    y: int;
 }
 
-impl point_ops of ops for point {
-    fn +(other: point) -> point {
-        {x: self.x + other.x, y: self.y + other.y}
+impl Point : ops::add<Point,Point> {
+    pure fn add(other: Point) -> Point {
+        Point {x: self.x + other.x, y: self.y + other.y}
     }
-    fn -(other: point) -> point {
-        {x: self.x - other.x, y: self.y - other.y}
+}
+
+impl Point : ops::sub<Point,Point> {
+    pure fn sub(other: Point) -> Point {
+        Point {x: self.x - other.x, y: self.y - other.y}
     }
-    fn unary-() -> point {
-        {x: -self.x, y: -self.y}
+}
+
+impl Point : ops::neg<Point> {
+    pure fn neg() -> Point {
+        Point {x: -self.x, y: -self.y}
     }
-    fn [](x: bool) -> int {
+}
+
+impl Point : ops::index<bool,int> {
+    pure fn index(&&x: bool) -> int {
         if x { self.x } else { self.y }
     }
 }
 
 fn main() {
-    let mut p = {x: 10, y: 20};
-    p += {x: 101, y: 102};
-    p -= {x: 100, y: 100};
-    assert p + {x: 5, y: 5} == {x: 16, y: 27};
-    assert -p == {x: -11, y: -22};
+    let mut p = Point {x: 10, y: 20};
+    p += Point {x: 101, y: 102};
+    p -= Point {x: 100, y: 100};
+    assert p + Point {x: 5, y: 5} == Point {x: 16, y: 27};
+    assert -p == Point {x: -11, y: -22};
     assert p[true] == 11;
     assert p[false] == 22;
     // Issue #1733
diff --git a/src/test/run-pass/selftype-add-ints.rs b/src/test/run-pass/selftype-add-ints.rs
deleted file mode 100644
index 64aae3d1544..00000000000
--- a/src/test/run-pass/selftype-add-ints.rs
+++ /dev/null
@@ -1,19 +0,0 @@
-iface add {
-    fn +(++x: self) -> self;
-}
-
-impl of add for int {
-    fn +(x: int) -> int { self + x }
-}
-
-impl of add for @const int {
-    fn +(x: @const int) -> @const int { @(*self + *x) }
-}
-
-fn do_add<A:add>(+x: A, +y: A) -> A { x + y }
-
-fn main() {
-    assert do_add(3, 4) == 7;
-    assert do_add(@3, @4) == @7;
-    assert do_add(@mut 3, @mut 4) == @mut 7;
-}