rustc: Use coherence for operator overloading.
The only use of the old-style impls is now placement new.
This commit is contained in:
parent
e6d2e49852
commit
93c2f5e0e4
23 changed files with 348 additions and 295 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 } }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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); }
|
||||
_ {
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -16,24 +16,31 @@ use std;
|
|||
import io::writer_util;
|
||||
import std::map::hashmap;
|
||||
|
||||
type cmplx = {re: f64, im: f64};
|
||||
struct cmplx {
|
||||
re: f64;
|
||||
im: f64;
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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]};
|
||||
|
||||
trait times_and_plus {
|
||||
fn *(x: cmplx) -> cmplx;
|
||||
fn +(x: cmplx) -> cmplx;
|
||||
}
|
||||
|
||||
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}
|
||||
}
|
||||
|
||||
fn +(x: cmplx) -> cmplx {
|
||||
{re: self.re + x.re, im: self.im + x.im}
|
||||
}
|
||||
}
|
||||
|
||||
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});
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
type point = { x: int, y: int };
|
||||
|
||||
trait add_and_times {
|
||||
pure fn +(z: int) -> int;
|
||||
fn *(z: int) -> int;
|
||||
struct Point {
|
||||
x: int;
|
||||
y: int;
|
||||
}
|
||||
|
||||
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 : ops::add<int,int> {
|
||||
pure fn add(&&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
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
// error-pattern:unresolved name: debug
|
||||
#[no_core];
|
||||
|
||||
fn main() {
|
||||
log(debug, 0);
|
||||
}
|
|
@ -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() {}
|
|
@ -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;
|
||||
|
|
|
@ -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() {}
|
||||
|
|
|
@ -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));
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue