diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2012-07-27 19:32:42 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2012-07-27 19:35:24 -0700 |
| commit | 93c2f5e0e43532a2288ed6dec378564264d1a77c (patch) | |
| tree | 2d8d3f5d4667f7a009fa338bc34076216873b35c /src | |
| parent | e6d2e49852873c52b872185a0ae5a8ca941ed2f1 (diff) | |
| download | rust-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')
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; -} |
