@@ -42,58 +42,68 @@ pub enum LangItem {
DropTraitLangItem, // 3

AddTraitLangItem, // 4
SubTraitLangItem, // 5
MulTraitLangItem, // 6
DivTraitLangItem, // 7
RemTraitLangItem, // 8
NegTraitLangItem, // 9
NotTraitLangItem, // 10
BitXorTraitLangItem, // 11
BitAndTraitLangItem, // 12
BitOrTraitLangItem, // 13
ShlTraitLangItem, // 14
ShrTraitLangItem, // 15
IndexTraitLangItem, // 16

EqTraitLangItem, // 17
OrdTraitLangItem, // 18

StrEqFnLangItem, // 19
UniqStrEqFnLangItem, // 20
FailFnLangItem, // 21
FailBoundsCheckFnLangItem, // 22
ExchangeMallocFnLangItem, // 23
ClosureExchangeMallocFnLangItem, // 24
ExchangeFreeFnLangItem, // 25
MallocFnLangItem, // 26
FreeFnLangItem, // 27
BorrowAsImmFnLangItem, // 28
BorrowAsMutFnLangItem, // 29
ReturnToMutFnLangItem, // 30
CheckNotBorrowedFnLangItem, // 31
StrDupUniqFnLangItem, // 32
RecordBorrowFnLangItem, // 33
UnrecordBorrowFnLangItem, // 34

StartFnLangItem, // 35

TyDescStructLangItem, // 36
TyVisitorTraitLangItem, // 37
OpaqueStructLangItem, // 38

EventLoopFactoryLangItem, // 39

TypeIdLangItem, // 40
AddAssignTraitLangItem, // 5
SubTraitLangItem, // 6
SubAssignTraitLangItem, // 7
MulTraitLangItem, // 8
MulAssignTraitLangItem, // 9
DivTraitLangItem, // 10
DivAssignTraitLangItem, // 11
RemTraitLangItem, // 12
RemAssignTraitLangItem, // 13
NegTraitLangItem, // 14
NotTraitLangItem, // 15
BitXorTraitLangItem, // 16
BitXorAssignTraitLangItem, // 17
BitAndTraitLangItem, // 18
BitAndAssignTraitLangItem, // 19
BitOrTraitLangItem, // 20
BitOrAssignTraitLangItem, // 21
ShlTraitLangItem, // 22
ShlAssignTraitLangItem, // 23
ShrTraitLangItem, // 24
ShrAssignTraitLangItem, // 25
IndexTraitLangItem, // 26

EqTraitLangItem, // 27
OrdTraitLangItem, // 28

StrEqFnLangItem, // 29
UniqStrEqFnLangItem, // 30
FailFnLangItem, // 31
FailBoundsCheckFnLangItem, // 32
ExchangeMallocFnLangItem, // 33
ClosureExchangeMallocFnLangItem, // 34
ExchangeFreeFnLangItem, // 35
MallocFnLangItem, // 36
FreeFnLangItem, // 37
BorrowAsImmFnLangItem, // 38
BorrowAsMutFnLangItem, // 39
ReturnToMutFnLangItem, // 40
CheckNotBorrowedFnLangItem, // 41
StrDupUniqFnLangItem, // 42
RecordBorrowFnLangItem, // 43
UnrecordBorrowFnLangItem, // 44

StartFnLangItem, // 45

TyDescStructLangItem, // 46
TyVisitorTraitLangItem, // 47
OpaqueStructLangItem, // 48

EventLoopFactoryLangItem, // 49

TypeIdLangItem, // 50
}

pub struct LanguageItems {
items: [Option<ast::DefId>, ..41]
items: [Option<ast::DefId>, ..51]
}

impl LanguageItems {
pub fn new() -> LanguageItems {
LanguageItems {
items: [ None, ..41 ]
items: [ None, ..51 ]
}
}

@@ -110,47 +120,57 @@ impl LanguageItems {
3 => "drop",

4 => "add",
5 => "sub",
6 => "mul",
7 => "div",
8 => "rem",
9 => "neg",
10 => "not",
11 => "bitxor",
12 => "bitand",
13 => "bitor",
14 => "shl",
15 => "shr",
16 => "index",
17 => "eq",
18 => "ord",

19 => "str_eq",
20 => "uniq_str_eq",
21 => "fail_",
22 => "fail_bounds_check",
23 => "exchange_malloc",
24 => "closure_exchange_malloc",
25 => "exchange_free",
26 => "malloc",
27 => "free",
28 => "borrow_as_imm",
29 => "borrow_as_mut",
30 => "return_to_mut",
31 => "check_not_borrowed",
32 => "strdup_uniq",
33 => "record_borrow",
34 => "unrecord_borrow",

35 => "start",

36 => "ty_desc",
37 => "ty_visitor",
38 => "opaque",

39 => "event_loop_factory",

40 => "type_id",
5 => "add_assign",
6 => "sub",
7 => "sub_assign",
8 => "mul",
9 => "mul_assign",
10 => "div",
11 => "div_assign",
12 => "rem",
13 => "rem_assign",
14 => "neg",
15 => "not",
16 => "bitxor",
17 => "bitxor_assign",
18 => "bitand",
19 => "bitand_assign",
20 => "bitor",
21 => "bitor_assign",
22 => "shl",
23 => "shl_assign",
24 => "shr",
25 => "shr_assign",
26 => "index",
27 => "eq",
28 => "ord",

29 => "str_eq",
30 => "uniq_str_eq",
31 => "fail_",
32 => "fail_bounds_check",
33 => "exchange_malloc",
34 => "closure_exchange_malloc",
35 => "exchange_free",
36 => "malloc",
37 => "free",
38 => "borrow_as_imm",
39 => "borrow_as_mut",
40 => "return_to_mut",
41 => "check_not_borrowed",
42 => "strdup_uniq",
43 => "record_borrow",
44 => "unrecord_borrow",

45 => "start",

46 => "ty_desc",
47 => "ty_visitor",
48 => "opaque",

49 => "event_loop_factory",

50 => "type_id",

_ => "???"
}
@@ -195,18 +215,33 @@ impl LanguageItems {
pub fn add_trait(&self) -> Option<ast::DefId> {
self.items[AddTraitLangItem as uint]
}
pub fn add_assign_trait(&self) -> Option<ast::DefId> {
self.items[AddAssignTraitLangItem as uint]
}
pub fn sub_trait(&self) -> Option<ast::DefId> {
self.items[SubTraitLangItem as uint]
}
pub fn sub_assign_trait(&self) -> Option<ast::DefId> {
self.items[SubAssignTraitLangItem as uint]
}
pub fn mul_trait(&self) -> Option<ast::DefId> {
self.items[MulTraitLangItem as uint]
}
pub fn mul_assign_trait(&self) -> Option<ast::DefId> {
self.items[MulAssignTraitLangItem as uint]
}
pub fn div_trait(&self) -> Option<ast::DefId> {
self.items[DivTraitLangItem as uint]
}
pub fn div_assign_trait(&self) -> Option<ast::DefId> {
self.items[DivAssignTraitLangItem as uint]
}
pub fn rem_trait(&self) -> Option<ast::DefId> {
self.items[RemTraitLangItem as uint]
}
pub fn rem_assign_trait(&self) -> Option<ast::DefId> {
self.items[RemAssignTraitLangItem as uint]
}
pub fn neg_trait(&self) -> Option<ast::DefId> {
self.items[NegTraitLangItem as uint]
}
@@ -216,18 +251,33 @@ impl LanguageItems {
pub fn bitxor_trait(&self) -> Option<ast::DefId> {
self.items[BitXorTraitLangItem as uint]
}
pub fn bitxor_assign_trait(&self) -> Option<ast::DefId> {
self.items[BitXorAssignTraitLangItem as uint]
}
pub fn bitand_trait(&self) -> Option<ast::DefId> {
self.items[BitAndTraitLangItem as uint]
}
pub fn bitand_assign_trait(&self) -> Option<ast::DefId> {
self.items[BitAndAssignTraitLangItem as uint]
}
pub fn bitor_trait(&self) -> Option<ast::DefId> {
self.items[BitOrTraitLangItem as uint]
}
pub fn bitor_assign_trait(&self) -> Option<ast::DefId> {
self.items[BitOrAssignTraitLangItem as uint]
}
pub fn shl_trait(&self) -> Option<ast::DefId> {
self.items[ShlTraitLangItem as uint]
}
pub fn shl_assign_trait(&self) -> Option<ast::DefId> {
self.items[ShlAssignTraitLangItem as uint]
}
pub fn shr_trait(&self) -> Option<ast::DefId> {
self.items[ShrTraitLangItem as uint]
}
pub fn shr_assign_trait(&self) -> Option<ast::DefId> {
self.items[ShrAssignTraitLangItem as uint]
}
pub fn index_trait(&self) -> Option<ast::DefId> {
self.items[IndexTraitLangItem as uint]
}
@@ -350,17 +400,27 @@ impl LanguageItemCollector {
item_refs.insert("drop", DropTraitLangItem as uint);

item_refs.insert("add", AddTraitLangItem as uint);
item_refs.insert("add_assign", AddAssignTraitLangItem as uint);
item_refs.insert("sub", SubTraitLangItem as uint);
item_refs.insert("sub_assign", SubAssignTraitLangItem as uint);
item_refs.insert("mul", MulTraitLangItem as uint);
item_refs.insert("mul_assign", MulAssignTraitLangItem as uint);
item_refs.insert("div", DivTraitLangItem as uint);
item_refs.insert("div_assign", DivAssignTraitLangItem as uint);
item_refs.insert("rem", RemTraitLangItem as uint);
item_refs.insert("rem_assign", RemAssignTraitLangItem as uint);
item_refs.insert("neg", NegTraitLangItem as uint);
item_refs.insert("not", NotTraitLangItem as uint);
item_refs.insert("bitxor", BitXorTraitLangItem as uint);
item_refs.insert("bitxor_assign", BitXorAssignTraitLangItem as uint);
item_refs.insert("bitand", BitAndTraitLangItem as uint);
item_refs.insert("bitand_assign", BitAndAssignTraitLangItem as uint);
item_refs.insert("bitor", BitOrTraitLangItem as uint);
item_refs.insert("bitor_assign", BitOrAssignTraitLangItem as uint);
item_refs.insert("shl", ShlTraitLangItem as uint);
item_refs.insert("shl_assign", ShlAssignTraitLangItem as uint);
item_refs.insert("shr", ShrTraitLangItem as uint);
item_refs.insert("shr_assign", ShrAssignTraitLangItem as uint);
item_refs.insert("index", IndexTraitLangItem as uint);

item_refs.insert("eq", EqTraitLangItem as uint);
@@ -5132,46 +5132,86 @@ impl Resolver {
let traits = self.search_for_traits_containing_method(ident);
self.trait_map.insert(expr.id, @mut traits);
}
ExprBinary(_, BiAdd, _, _) | ExprAssignOp(_, BiAdd, _, _) => {
ExprBinary(_, BiAdd, _, _) => {
let i = self.lang_items.add_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiSub, _, _) | ExprAssignOp(_, BiSub, _, _) => {
ExprAssignOp(_, BiAdd, _, _) => {
let i = self.lang_items.add_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiSub, _, _) => {
let i = self.lang_items.sub_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiMul, _, _) | ExprAssignOp(_, BiMul, _, _) => {
ExprAssignOp(_, BiSub, _, _) => {
let i = self.lang_items.sub_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiMul, _, _) => {
let i = self.lang_items.mul_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiDiv, _, _) | ExprAssignOp(_, BiDiv, _, _) => {
ExprAssignOp(_, BiMul, _, _) => {
let i = self.lang_items.mul_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiDiv, _, _) => {
let i = self.lang_items.div_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiRem, _, _) | ExprAssignOp(_, BiRem, _, _) => {
ExprAssignOp(_, BiDiv, _, _) => {
let i = self.lang_items.div_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiRem, _, _) => {
let i = self.lang_items.rem_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiBitXor, _, _) | ExprAssignOp(_, BiBitXor, _, _) => {
ExprAssignOp(_, BiRem, _, _) => {
let i = self.lang_items.rem_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiBitXor, _, _) => {
let i = self.lang_items.bitxor_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiBitAnd, _, _) | ExprAssignOp(_, BiBitAnd, _, _) => {
ExprAssignOp(_, BiBitXor, _, _) => {
let i = self.lang_items.bitxor_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiBitAnd, _, _) => {
let i = self.lang_items.bitand_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiBitOr, _, _) | ExprAssignOp(_, BiBitOr, _, _) => {
ExprAssignOp(_, BiBitAnd, _, _) => {
let i = self.lang_items.bitand_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiBitOr, _, _) => {
let i = self.lang_items.bitor_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiShl, _, _) | ExprAssignOp(_, BiShl, _, _) => {
ExprAssignOp(_, BiBitOr, _, _) => {
let i = self.lang_items.bitor_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiShl, _, _) => {
let i = self.lang_items.shl_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiShr, _, _) | ExprAssignOp(_, BiShr, _, _) => {
ExprAssignOp(_, BiShl, _, _) => {
let i = self.lang_items.shl_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiShr, _, _) => {
let i = self.lang_items.shr_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprAssignOp(_, BiShr, _, _) => {
let i = self.lang_items.shr_assign_trait();
self.add_fixed_trait_for_expr(expr.id, i);
}
ExprBinary(_, BiLt, _, _) | ExprBinary(_, BiLe, _, _) |
ExprBinary(_, BiGe, _, _) | ExprBinary(_, BiGt, _, _) => {
let i = self.lang_items.ord_trait();
@@ -1900,18 +1900,36 @@ impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
}
}

impl ops::BitOrAssign<TypeContents> for TypeContents {
fn bitor_assign(&mut self, other: &TypeContents) {
self.bits |= other.bits;
}
}

impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
fn bitand(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits & other.bits}
}
}

impl ops::BitAndAssign<TypeContents> for TypeContents {
fn bitand_assign(&mut self, other: &TypeContents) {
self.bits &= other.bits;
}
}

impl ops::Sub<TypeContents,TypeContents> for TypeContents {
fn sub(&self, other: &TypeContents) -> TypeContents {
TypeContents {bits: self.bits & !other.bits}
}
}

impl ops::SubAssign<TypeContents> for TypeContents {
fn sub_assign(&mut self, other: &TypeContents) {
self.bits &= !other.bits;
}
}

impl ToStr for TypeContents {
fn to_str(&self) -> ~str {
format!("TypeContents({})", self.bits.to_str_radix(2))
@@ -210,13 +210,6 @@ impl PurityState {
}
}

/// Whether `check_binop` allows overloaded operators to be invoked.
#[deriving(Eq)]
enum AllowOverloadedOperatorsFlag {
AllowOverloadedOperators,
DontAllowOverloadedOperators,
}

#[deriving(Clone)]
pub struct FnCtxt {
// Number of errors that had been reported when we started
@@ -2039,16 +2032,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}

// could be either a expr_binop or an expr_assign_binop
fn check_binop(fcx: @mut FnCtxt,
callee_id: ast::NodeId,
expr: @ast::Expr,
op: ast::BinOp,
lhs: @ast::Expr,
rhs: @ast::Expr,
// Used only in the error case
expected_result: Option<ty::t>,
allow_overloaded_operators: AllowOverloadedOperatorsFlag
expected_result: Option<ty::t>
) {
let tcx = fcx.ccx.tcx;

@@ -2099,28 +2090,14 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}

// Check for overloaded operators if allowed.
let result_t;
if allow_overloaded_operators == AllowOverloadedOperators {
result_t = check_user_binop(fcx,
let result_t = check_user_binop(fcx,
callee_id,
expr,
lhs,
lhs_t,
op,
rhs,
expected_result);
} else {
fcx.type_error_message(expr.span,
|actual| {
format!("binary operation {} cannot be \
applied to type `{}`",
ast_util::binop_to_str(op),
actual)
},
lhs_t,
None);
result_t = ty::mk_err();
}

fcx.write_ty(expr.id, result_t);
if ty::type_is_error(result_t) {
@@ -2170,6 +2147,95 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
ty::mk_err()
}

fn check_assign_op(fcx: @mut FnCtxt,
callee_id: ast::NodeId,
expr: @ast::Expr,
op: ast::BinOp,
lhs: @ast::Expr,
rhs: @ast::Expr,
// Used only in the error case
expected_result: Option<ty::t>
) {
let tcx = fcx.ccx.tcx;

check_expr(fcx, lhs);
// Callee does bot / err checking
let lhs_t = structurally_resolved_type(fcx, lhs.span,
fcx.expr_ty(lhs));

if ty::type_is_integral(lhs_t) && ast_util::is_shift_binop(op) {
// Shift is a special case: rhs can be any integral type
check_expr(fcx, rhs);
let rhs_t = fcx.expr_ty(rhs);
require_integral(fcx, rhs.span, rhs_t);
fcx.write_ty(expr.id, lhs_t);
return;
}

if ty::is_binopable(tcx, lhs_t, op) {
let tvar = fcx.infcx().next_ty_var();
demand::suptype(fcx, expr.span, tvar, lhs_t);
check_expr_has_type(fcx, rhs, tvar);

let result_t = match op {
ast::BiEq | ast::BiNe | ast::BiLt | ast::BiLe | ast::BiGe |
ast::BiGt => {
ty::mk_bool()
}
_ => {
lhs_t
}
};

fcx.write_ty(expr.id, result_t);
return;
}

// Check for overloaded operators if allowed.
let result_t = check_user_assign_op(fcx,
callee_id,
expr,
lhs,
lhs_t,
op,
rhs,
expected_result);

fcx.write_ty(expr.id, result_t);
if ty::type_is_error(result_t) {
fcx.write_ty(rhs.id, result_t);
}
}

fn check_user_assign_op(fcx: @mut FnCtxt,
callee_id: ast::NodeId,
ex: @ast::Expr,
lhs_expr: @ast::Expr,
lhs_resolved_t: ty::t,
op: ast::BinOp,
rhs: @ast::Expr,
expected_result: Option<ty::t>) -> ty::t {
match ast_util::assign_op_to_method_name(op) {
Some(ref name) => {
let if_op_unbound = || {
fcx.type_error_message(ex.span, |actual| {
format!("binary assignment operation {} cannot be applied to type `{}`",
ast_util::assign_op_to_str(op).unwrap(), actual)},
lhs_resolved_t, None)
};
// No need for a separate lookup_assign_op_method, lookup_op_method will do
return lookup_op_method(fcx, callee_id, ex, lhs_expr, lhs_resolved_t,
fcx.tcx().sess.ident_of(*name).name,
~[rhs], DoDerefArgs, DontAutoderefReceiver, if_op_unbound,
expected_result);
}
None => ()
};
check_expr(fcx, rhs);

ty::mk_err()
}

fn check_user_unop(fcx: @mut FnCtxt,
callee_id: ast::NodeId,
op_str: &str,
@@ -2660,8 +2726,7 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
op,
lhs,
rhs,
expected,
AllowOverloadedOperators);
expected);

let lhs_ty = fcx.expr_ty(lhs);
let rhs_ty = fcx.expr_ty(rhs);
@@ -2675,30 +2740,28 @@ pub fn check_expr_with_unifier(fcx: @mut FnCtxt,
}
}
ast::ExprAssignOp(callee_id, op, lhs, rhs) => {
check_binop(fcx,
callee_id,
expr,
op,
lhs,
rhs,
expected,
DontAllowOverloadedOperators);
check_assign_op(fcx,
callee_id,
expr,
op,
lhs,
rhs,
expected);

let lhs_t = fcx.expr_ty(lhs);
let result_t = fcx.expr_ty(expr);
demand::suptype(fcx, expr.span, result_t, lhs_t);
let lhs_ty = fcx.expr_ty(lhs);
let rhs_ty = fcx.expr_ty(rhs);

let tcx = fcx.tcx();
if !ty::expr_is_lval(tcx, fcx.ccx.method_map, lhs) {
tcx.sess.span_err(lhs.span, "illegal left-hand side expression");
}

// Overwrite result of check_binop...this preserves existing behavior
// but seems quite dubious with regard to user-defined methods
// and so forth. - Niko
if !ty::type_is_error(result_t)
&& !ty::type_is_bot(result_t) {
fcx.write_nil(expr.id);
if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
fcx.write_error(id);
} else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
fcx.write_bot(id);
} else {
fcx.write_nil(id);
}
}
ast::ExprUnary(callee_id, unop, oprnd) => {
@@ -150,7 +150,7 @@ impl<A> FromIterator<A> for @[A] {
pub mod traits {
use at_vec::append;
use clone::Clone;
use ops::Add;
use ops::{Add, AddAssign};
use vec::Vector;

impl<'self,T:Clone, V: Vector<T>> Add<V,@[T]> for @[T] {
@@ -159,6 +159,8 @@ pub mod traits {
append(*self, rhs.as_slice())
}
}

impl<'self, T: Clone, V: Vector<T>> AddAssign<V> for @[T] {}
}

#[cfg(test)]
@@ -255,30 +255,45 @@ impl Add<f32,f32> for f32 {
fn add(&self, other: &f32) -> f32 { *self + *other }
}

#[cfg(not(test))]
impl AddAssign<f32> for f32 {}

#[cfg(not(test))]
impl Sub<f32,f32> for f32 {
#[inline]
fn sub(&self, other: &f32) -> f32 { *self - *other }
}

#[cfg(not(test))]
impl SubAssign<f32> for f32 {}

#[cfg(not(test))]
impl Mul<f32,f32> for f32 {
#[inline]
fn mul(&self, other: &f32) -> f32 { *self * *other }
}

#[cfg(not(test))]
impl MulAssign<f32> for f32 {}

#[cfg(not(test))]
impl Div<f32,f32> for f32 {
#[inline]
fn div(&self, other: &f32) -> f32 { *self / *other }
}

#[cfg(not(test))]
impl DivAssign<f32> for f32 {}

#[cfg(not(test))]
impl Rem<f32,f32> for f32 {
#[inline]
fn rem(&self, other: &f32) -> f32 { *self % *other }
}

#[cfg(not(test))]
impl RemAssign<f32> for f32 {}

#[cfg(not(test))]
impl Neg<f32> for f32 {
#[inline]
@@ -277,26 +277,46 @@ impl Add<f64,f64> for f64 {
#[inline]
fn add(&self, other: &f64) -> f64 { *self + *other }
}

#[cfg(not(test))]
impl AddAssign<f64> for f64 {}

#[cfg(not(test))]
impl Sub<f64,f64> for f64 {
#[inline]
fn sub(&self, other: &f64) -> f64 { *self - *other }
}

#[cfg(not(test))]
impl SubAssign<f64> for f64 {}

#[cfg(not(test))]
impl Mul<f64,f64> for f64 {
#[inline]
fn mul(&self, other: &f64) -> f64 { *self * *other }
}

#[cfg(not(test))]
impl MulAssign<f64> for f64 {}

#[cfg(not(test))]
impl Div<f64,f64> for f64 {
#[inline]
fn div(&self, other: &f64) -> f64 { *self / *other }
}

#[cfg(not(test))]
impl DivAssign<f64> for f64 {}

#[cfg(not(test))]
impl Rem<f64,f64> for f64 {
#[inline]
fn rem(&self, other: &f64) -> f64 { *self % *other }
}

#[cfg(not(test))]
impl RemAssign<f64> for f64 {}

#[cfg(not(test))]
impl Neg<f64> for f64 {
#[inline]
@@ -87,18 +87,27 @@ impl Add<$T,$T> for $T {
fn add(&self, other: &$T) -> $T { *self + *other }
}

#[cfg(not(test))]
impl AddAssign<$T> for $T {}

#[cfg(not(test))]
impl Sub<$T,$T> for $T {
#[inline]
fn sub(&self, other: &$T) -> $T { *self - *other }
}

#[cfg(not(test))]
impl SubAssign<$T> for $T {}

#[cfg(not(test))]
impl Mul<$T,$T> for $T {
#[inline]
fn mul(&self, other: &$T) -> $T { *self * *other }
}

#[cfg(not(test))]
impl MulAssign<$T> for $T {}

#[cfg(not(test))]
impl Div<$T,$T> for $T {
///
@@ -123,6 +132,9 @@ impl Div<$T,$T> for $T {
fn div(&self, other: &$T) -> $T { *self / *other }
}

#[cfg(not(test))]
impl DivAssign<$T> for $T {}

#[cfg(not(test))]
impl Rem<$T,$T> for $T {
///
@@ -150,6 +162,9 @@ impl Rem<$T,$T> for $T {
fn rem(&self, other: &$T) -> $T { *self % *other }
}

#[cfg(not(test))]
impl RemAssign<$T> for $T {}

#[cfg(not(test))]
impl Neg<$T> for $T {
#[inline]
@@ -323,30 +338,45 @@ impl BitOr<$T,$T> for $T {
fn bitor(&self, other: &$T) -> $T { *self | *other }
}

#[cfg(not(test))]
impl BitOrAssign<$T> for $T {}

#[cfg(not(test))]
impl BitAnd<$T,$T> for $T {
#[inline]
fn bitand(&self, other: &$T) -> $T { *self & *other }
}

#[cfg(not(test))]
impl BitAndAssign<$T> for $T {}

#[cfg(not(test))]
impl BitXor<$T,$T> for $T {
#[inline]
fn bitxor(&self, other: &$T) -> $T { *self ^ *other }
}

#[cfg(not(test))]
impl BitXorAssign<$T> for $T {}

#[cfg(not(test))]
impl Shl<$T,$T> for $T {
#[inline]
fn shl(&self, other: &$T) -> $T { *self << *other }
}

#[cfg(not(test))]
impl ShlAssign<$T> for $T {}

#[cfg(not(test))]
impl Shr<$T,$T> for $T {
#[inline]
fn shr(&self, other: &$T) -> $T { *self >> *other }
}

#[cfg(not(test))]
impl ShrAssign<$T> for $T {}

#[cfg(not(test))]
impl Not<$T> for $T {
#[inline]
@@ -17,7 +17,7 @@

use clone::{Clone, DeepClone};
use cmp::{Eq, ApproxEq, Ord};
use ops::{Add, Sub, Mul, Div, Rem, Neg};
use ops::{Add, AddAssign, Sub, SubAssign, Mul, MulAssign, Div, DivAssign, Rem, RemAssign, Neg};
use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr};
use option::{Option, Some, None};

@@ -27,10 +27,15 @@ pub mod strconv;
pub trait Num: Eq + Zero + One
+ Neg<Self>
+ Add<Self,Self>
+ AddAssign<Self>
+ Sub<Self,Self>
+ SubAssign<Self>
+ Mul<Self,Self>
+ MulAssign<Self>
+ Div<Self,Self>
+ Rem<Self,Self> {}
+ DivAssign<Self>
+ Rem<Self,Self>
+ RemAssign<Self> {}

pub trait Orderable: Ord {
// These should be methods on `Ord`, with overridable default implementations. We don't want
@@ -467,10 +472,15 @@ pub trait Primitive: Clone
+ Bounded
+ Neg<Self>
+ Add<Self,Self>
+ AddAssign<Self>
+ Sub<Self,Self>
+ SubAssign<Self>
+ Mul<Self,Self>
+ MulAssign<Self>
+ Div<Self,Self>
+ Rem<Self,Self> {
+ DivAssign<Self>
+ Rem<Self,Self>
+ RemAssign<Self> {
// FIXME (#5527): These should be associated constants
// FIXME (#8888): Removing `unused_self` requires #8888 to be fixed.
fn bits(unused_self: Option<Self>) -> uint;
@@ -90,30 +90,45 @@ impl Add<$T,$T> for $T {
fn add(&self, other: &$T) -> $T { *self + *other }
}

#[cfg(not(test))]
impl AddAssign<$T> for $T {}

#[cfg(not(test))]
impl Sub<$T,$T> for $T {
#[inline]
fn sub(&self, other: &$T) -> $T { *self - *other }
}

#[cfg(not(test))]
impl SubAssign<$T> for $T {}

#[cfg(not(test))]
impl Mul<$T,$T> for $T {
#[inline]
fn mul(&self, other: &$T) -> $T { *self * *other }
}

#[cfg(not(test))]
impl MulAssign<$T> for $T {}

#[cfg(not(test))]
impl Div<$T,$T> for $T {
#[inline]
fn div(&self, other: &$T) -> $T { *self / *other }
}

#[cfg(not(test))]
impl DivAssign<$T> for $T {}

#[cfg(not(test))]
impl Rem<$T,$T> for $T {
#[inline]
fn rem(&self, other: &$T) -> $T { *self % *other }
}

#[cfg(not(test))]
impl RemAssign<$T> for $T {}

#[cfg(not(test))]
impl Neg<$T> for $T {
#[inline]
@@ -184,30 +199,45 @@ impl BitOr<$T,$T> for $T {
fn bitor(&self, other: &$T) -> $T { *self | *other }
}

#[cfg(not(test))]
impl BitOrAssign<$T> for $T {}

#[cfg(not(test))]
impl BitAnd<$T,$T> for $T {
#[inline]
fn bitand(&self, other: &$T) -> $T { *self & *other }
}

#[cfg(not(test))]
impl BitAndAssign<$T> for $T {}

#[cfg(not(test))]
impl BitXor<$T,$T> for $T {
#[inline]
fn bitxor(&self, other: &$T) -> $T { *self ^ *other }
}

#[cfg(not(test))]
impl BitXorAssign<$T> for $T {}

#[cfg(not(test))]
impl Shl<$T,$T> for $T {
#[inline]
fn shl(&self, other: &$T) -> $T { *self << *other }
}

#[cfg(not(test))]
impl ShlAssign<$T> for $T {}

#[cfg(not(test))]
impl Shr<$T,$T> for $T {
#[inline]
fn shr(&self, other: &$T) -> $T { *self >> *other }
}

#[cfg(not(test))]
impl ShrAssign<$T> for $T {}

#[cfg(not(test))]
impl Not<$T> for $T {
#[inline]
@@ -113,6 +113,14 @@ pub trait Add<RHS,Result> {
fn add(&self, rhs: &RHS) -> Result;
}

#[lang="add_assign"]
pub trait AddAssign<RHS>: Add<RHS, Self> {
#[inline]
fn add_assign(&mut self, rhs: &RHS) {
*self = *self + *rhs;
}
}

/**
*
* The `Sub` trait is used to specify the functionality of `-`.
@@ -142,6 +150,14 @@ pub trait Sub<RHS,Result> {
fn sub(&self, rhs: &RHS) -> Result;
}

#[lang="sub_assign"]
pub trait SubAssign<RHS>: Sub<RHS, Self> {
#[inline]
fn sub_assign(&mut self, rhs: &RHS) {
*self = *self - *rhs;
}
}

/**
*
* The `Mul` trait is used to specify the functionality of `*`.
@@ -171,6 +187,14 @@ pub trait Mul<RHS,Result> {
fn mul(&self, rhs: &RHS) -> Result;
}

#[lang="mul_assign"]
pub trait MulAssign<RHS>: Mul<RHS, Self> {
#[inline]
fn mul_assign(&mut self, rhs: &RHS) {
*self = *self * *rhs;
}
}

/**
*
* The `Div` trait is used to specify the functionality of `/`.
@@ -200,6 +224,14 @@ pub trait Div<RHS,Result> {
fn div(&self, rhs: &RHS) -> Result;
}

#[lang="div_assign"]
pub trait DivAssign<RHS>: Div<RHS, Self> {
#[inline]
fn div_assign(&mut self, rhs: &RHS) {
*self = *self / *rhs;
}
}

/**
*
* The `Rem` trait is used to specify the functionality of `%`.
@@ -229,6 +261,14 @@ pub trait Rem<RHS,Result> {
fn rem(&self, rhs: &RHS) -> Result;
}

#[lang="rem_assign"]
pub trait RemAssign<RHS>: Rem<RHS, Self> {
#[inline]
fn rem_assign(&mut self, rhs: &RHS) {
*self = *self % *rhs;
}
}

/**
*
* The `Neg` trait is used to specify the functionality of unary `-`.
@@ -316,6 +356,14 @@ pub trait BitAnd<RHS,Result> {
fn bitand(&self, rhs: &RHS) -> Result;
}

#[lang="bitand_assign"]
pub trait BitAndAssign<RHS>: BitAnd<RHS, Self> {
#[inline]
fn bitand_assign(&mut self, rhs: &RHS) {
*self = *self & *rhs;
}
}

/**
*
* The `BitOr` trait is used to specify the functionality of `|`.
@@ -345,6 +393,14 @@ pub trait BitOr<RHS,Result> {
fn bitor(&self, rhs: &RHS) -> Result;
}

#[lang="bitor_assign"]
pub trait BitOrAssign<RHS>: BitOr<RHS, Self> {
#[inline]
fn bitor_assign(&mut self, rhs: &RHS) {
*self = *self | *rhs;
}
}

/**
*
* The `BitXor` trait is used to specify the functionality of `^`.
@@ -374,6 +430,14 @@ pub trait BitXor<RHS,Result> {
fn bitxor(&self, rhs: &RHS) -> Result;
}

#[lang="bitxor_assign"]
pub trait BitXorAssign<RHS>: BitXor<RHS, Self> {
#[inline]
fn bitxor_assign(&mut self, rhs: &RHS) {
*self = *self ^ *rhs;
}
}

/**
*
* The `Shl` trait is used to specify the functionality of `<<`.
@@ -403,6 +467,14 @@ pub trait Shl<RHS,Result> {
fn shl(&self, rhs: &RHS) -> Result;
}

#[lang="shl_assign"]
pub trait ShlAssign<RHS>: Shl<RHS, Self> {
#[inline]
fn shl_assign(&mut self, rhs: &RHS) {
*self = *self << *rhs;
}
}

/**
*
* The `Shr` trait is used to specify the functionality of `>>`.
@@ -432,6 +504,14 @@ pub trait Shr<RHS,Result> {
fn shr(&self, rhs: &RHS) -> Result;
}

#[lang="shr_assign"]
pub trait ShrAssign<RHS>: Shr<RHS, Self> {
#[inline]
fn shr_assign(&mut self, rhs: &RHS) {
*self = *self >> *rhs;
}
}

/**
*
* The `Index` trait is used to specify the functionality of indexing operations
@@ -31,9 +31,12 @@ pub use either::{Either, Left, Right};
pub use kinds::Sized;
pub use kinds::{Freeze, Send};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{AddAssign, SubAssign, MulAssign, DivAssign, RemAssign};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{BitAndAssign, BitOrAssign, BitXorAssign};
pub use ops::{Drop};
pub use ops::{Shl, Shr, Index};
pub use ops::{ShlAssign, ShrAssign};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

@@ -1163,7 +1163,7 @@ Section: Trait implementations
#[cfg(not(test))]
#[allow(missing_doc)]
pub mod traits {
use ops::Add;
use ops::{Add, AddAssign};
use cmp::{TotalOrd, Ordering, Less, Equal, Greater, Eq, Ord, Equiv, TotalEq};
use super::{Str, eq_slice};
use option::{Some, None};
@@ -1177,6 +1177,24 @@ pub mod traits {
}
}

// There can be no AddAssign to match the above Add; &mut str isn't a valid type

impl<'self> Add<&'self str,~str> for ~str {
#[inline]
fn add(&self, rhs: & &'self str) -> ~str {
let mut ret = self.to_owned();
ret.push_str(*rhs);
ret
}
}

impl<'self> AddAssign<&'self str> for ~str {
#[inline]
fn add_assign(&mut self, rhs: & &'self str) {
self.push_str(*rhs);
}
}

impl<'self> TotalOrd for &'self str {
#[inline]
fn cmp(&self, other: & &'self str) -> Ordering {
@@ -614,7 +614,7 @@ pub mod traits {
use clone::Clone;
use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Equiv};
use iter::order;
use ops::Add;
use ops::{Add, AddAssign};

impl<'self,T:Eq> Eq for &'self [T] {
fn eq(&self, other: & &'self [T]) -> bool {
@@ -739,12 +739,21 @@ pub mod traits {
}
}

// There can be no AddAssign to match the above Add; &mut [T] cannot be extended.

impl<T:Clone, V: Vector<T>> Add<V, ~[T]> for ~[T] {
#[inline]
fn add(&self, rhs: &V) -> ~[T] {
self.as_slice() + rhs.as_slice()
}
}

impl<'self, T: Clone, V: Vector<T>> AddAssign<V> for ~[T] {
#[inline]
fn add_assign(&mut self, rhs: &V) {
self.push_all(rhs.as_slice());
}
}
}

#[cfg(test)]
@@ -75,6 +75,22 @@ pub fn def_id_of_def(d: Def) -> DefId {
}
}

pub fn assign_op_to_str(op: BinOp) -> Option<~str> {
match op {
BiAdd => return Some(~"+="),
BiSub => return Some(~"-="),
BiMul => return Some(~"*="),
BiDiv => return Some(~"/="),
BiRem => return Some(~"%="),
BiBitXor => return Some(~"^="),
BiBitAnd => return Some(~"&="),
BiBitOr => return Some(~"|="),
BiShl => return Some(~"<<="),
BiShr => return Some(~">>="),
BiLt | BiLe | BiGe | BiGt | BiEq | BiNe | BiAnd | BiOr => return None
}
}

pub fn binop_to_str(op: BinOp) -> ~str {
match op {
BiAdd => return ~"+",
@@ -98,6 +114,22 @@ pub fn binop_to_str(op: BinOp) -> ~str {
}
}

pub fn assign_op_to_method_name(op: BinOp) -> Option<~str> {
match op {
BiAdd => return Some(~"add_assign"),
BiSub => return Some(~"sub_assign"),
BiMul => return Some(~"mul_assign"),
BiDiv => return Some(~"div_assign"),
BiRem => return Some(~"rem_assign"),
BiBitXor => return Some(~"bitxor_assign"),
BiBitAnd => return Some(~"bitand_assign"),
BiBitOr => return Some(~"bitor_assign"),
BiShl => return Some(~"shl_assign"),
BiShr => return Some(~"shr_assign"),
BiLt | BiLe | BiGe | BiGt | BiEq | BiNe | BiAnd | BiOr => return None
}
}

pub fn binop_to_method_name(op: BinOp) -> Option<~str> {
match op {
BiAdd => return Some(~"add"),
@@ -54,12 +54,24 @@ impl Add<BytePos, BytePos> for BytePos {
}
}

impl AddAssign<BytePos> for BytePos {
fn add_assign(&mut self, rhs: &BytePos) {
**self += **rhs;
}
}

impl Sub<BytePos, BytePos> for BytePos {
fn sub(&self, rhs: &BytePos) -> BytePos {
BytePos(**self - **rhs)
}
}

impl SubAssign<BytePos> for BytePos {
fn sub_assign(&mut self, rhs: &BytePos) {
**self -= **rhs;
}
}

impl Pos for CharPos {
fn from_uint(n: uint) -> CharPos { CharPos(n) }
fn to_uint(&self) -> uint { **self }
@@ -71,12 +83,24 @@ impl Add<CharPos,CharPos> for CharPos {
}
}

impl AddAssign<CharPos> for CharPos {
fn add_assign(&mut self, rhs: &CharPos) {
**self += **rhs;
}
}

impl Sub<CharPos,CharPos> for CharPos {
fn sub(&self, rhs: &CharPos) -> CharPos {
CharPos(**self - **rhs)
}
}

impl SubAssign<CharPos> for CharPos {
fn sub_assign(&mut self, rhs: &CharPos) {
**self -= **rhs;
}
}

/**
Spans represent a region of code, used for error reporting. Positions in spans
are *absolute* positions from the beginning of the codemap, not positions