Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
int
Rust
提交
3ae3a5fc
R
Rust
项目概览
int
/
Rust
大约 1 年 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
Rust
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3ae3a5fc
编写于
9月 10, 2015
作者:
J
Jorge Aparicio
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Overloaded augmented assignments
上级
fb5de8ce
变更
15
隐藏空白更改
内联
并排
Showing
15 changed file
with
979 addition
and
85 deletion
+979
-85
src/libcore/ops.rs
src/libcore/ops.rs
+528
-0
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/expr_use_visitor.rs
+11
-5
src/librustc/middle/lang_items.rs
src/librustc/middle/lang_items.rs
+10
-0
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/expr.rs
+19
-3
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/op.rs
+68
-47
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/regionck.rs
+1
-1
src/librustc_typeck/check/writeback.rs
src/librustc_typeck/check/writeback.rs
+45
-18
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/diagnostics.rs
+20
-10
src/libsyntax/feature_gate.rs
src/libsyntax/feature_gate.rs
+6
-0
src/test/auxiliary/augmented_assignments.rs
src/test/auxiliary/augmented_assignments.rs
+22
-0
src/test/compile-fail/assignment-operator-unimplemented.rs
src/test/compile-fail/assignment-operator-unimplemented.rs
+1
-1
src/test/compile-fail/augmented-assignments-feature-gate-cross.rs
.../compile-fail/augmented-assignments-feature-gate-cross.rs
+25
-0
src/test/compile-fail/augmented-assignments-feature-gate.rs
src/test/compile-fail/augmented-assignments-feature-gate.rs
+26
-0
src/test/compile-fail/augmented-assignments.rs
src/test/compile-fail/augmented-assignments.rs
+33
-0
src/test/run-pass/augmented-assignments.rs
src/test/run-pass/augmented-assignments.rs
+164
-0
未找到文件。
src/libcore/ops.rs
浏览文件 @
3ae3a5fc
...
...
@@ -927,6 +927,534 @@ fn shr(self, other: $f) -> $t {
shr_impl_all!
{
u8
u16
u32
u64
usize
i8
i16
i32
i64
isize
}
/// The `AddAssign` trait is used to specify the functionality of `+=`.
///
/// # Examples
///
/// A trivial implementation of `AddAssign`. When `Foo += Foo` happens, it ends up
/// calling `add_assign`, and therefore, `main` prints `Adding!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::AddAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl AddAssign for Foo {
/// fn add_assign(&mut self, _rhs: Foo) {
/// println!("Adding!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo += Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"add_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
AddAssign
<
Rhs
=
Self
>
{
/// The method for the `+=` operator
fn
add_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
add_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
AddAssign
for
$t
{
#[inline]
fn
add_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
+=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
add_assign_impl!
{
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
f32
f64
}
/// The `SubAssign` trait is used to specify the functionality of `-=`.
///
/// # Examples
///
/// A trivial implementation of `SubAssign`. When `Foo -= Foo` happens, it ends up
/// calling `sub_assign`, and therefore, `main` prints `Subtracting!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::SubAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl SubAssign for Foo {
/// fn sub_assign(&mut self, _rhs: Foo) {
/// println!("Subtracting!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo -= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"sub_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
SubAssign
<
Rhs
=
Self
>
{
/// The method for the `-=` operator
fn
sub_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
sub_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
SubAssign
for
$t
{
#[inline]
fn
sub_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
-=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
sub_assign_impl!
{
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
f32
f64
}
/// The `MulAssign` trait is used to specify the functionality of `*=`.
///
/// # Examples
///
/// A trivial implementation of `MulAssign`. When `Foo *= Foo` happens, it ends up
/// calling `mul_assign`, and therefore, `main` prints `Multiplying!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::MulAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl MulAssign for Foo {
/// fn mul_assign(&mut self, _rhs: Foo) {
/// println!("Multiplying!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo *= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"mul_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
MulAssign
<
Rhs
=
Self
>
{
/// The method for the `*=` operator
fn
mul_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
mul_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
MulAssign
for
$t
{
#[inline]
fn
mul_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
*=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
mul_assign_impl!
{
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
f32
f64
}
/// The `DivAssign` trait is used to specify the functionality of `/=`.
///
/// # Examples
///
/// A trivial implementation of `DivAssign`. When `Foo /= Foo` happens, it ends up
/// calling `div_assign`, and therefore, `main` prints `Dividing!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::DivAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl DivAssign for Foo {
/// fn div_assign(&mut self, _rhs: Foo) {
/// println!("Dividing!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo /= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"div_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
DivAssign
<
Rhs
=
Self
>
{
/// The method for the `/=` operator
fn
div_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
div_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
DivAssign
for
$t
{
#[inline]
fn
div_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
/=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
div_assign_impl!
{
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
f32
f64
}
/// The `RemAssign` trait is used to specify the functionality of `%=`.
///
/// # Examples
///
/// A trivial implementation of `RemAssign`. When `Foo %= Foo` happens, it ends up
/// calling `rem_assign`, and therefore, `main` prints `Remainder-ing!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::RemAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl RemAssign for Foo {
/// fn rem_assign(&mut self, _rhs: Foo) {
/// println!("Remainder-ing!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo %= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"rem_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
RemAssign
<
Rhs
=
Self
>
{
/// The method for the `%=` operator
fn
rem_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
rem_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
RemAssign
for
$t
{
#[inline]
fn
rem_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
%=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
rem_assign_impl!
{
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
f32
f64
}
/// The `BitAndAssign` trait is used to specify the functionality of `&=`.
///
/// # Examples
///
/// A trivial implementation of `BitAndAssign`. When `Foo &= Foo` happens, it ends up
/// calling `bitand_assign`, and therefore, `main` prints `Bitwise And-ing!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::BitAndAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl BitAndAssign for Foo {
/// fn bitand_assign(&mut self, _rhs: Foo) {
/// println!("Bitwise And-ing!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo &= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"bitand_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
BitAndAssign
<
Rhs
=
Self
>
{
/// The method for the `&` operator
fn
bitand_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
bitand_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
BitAndAssign
for
$t
{
#[inline]
fn
bitand_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
&=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
bitand_assign_impl!
{
bool
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
}
/// The `BitOrAssign` trait is used to specify the functionality of `|=`.
///
/// # Examples
///
/// A trivial implementation of `BitOrAssign`. When `Foo |= Foo` happens, it ends up
/// calling `bitor_assign`, and therefore, `main` prints `Bitwise Or-ing!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::BitOrAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl BitOrAssign for Foo {
/// fn bitor_assign(&mut self, _rhs: Foo) {
/// println!("Bitwise Or-ing!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo |= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"bitor_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
BitOrAssign
<
Rhs
=
Self
>
{
/// The method for the `|=` operator
fn
bitor_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
bitor_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
BitOrAssign
for
$t
{
#[inline]
fn
bitor_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
|
=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
bitor_assign_impl!
{
bool
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
}
/// The `BitXorAssign` trait is used to specify the functionality of `^=`.
///
/// # Examples
///
/// A trivial implementation of `BitXorAssign`. When `Foo ^= Foo` happens, it ends up
/// calling `bitxor_assign`, and therefore, `main` prints `Bitwise Xor-ing!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::BitXorAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl BitXorAssign for Foo {
/// fn bitxor_assign(&mut self, _rhs: Foo) {
/// println!("Bitwise Xor-ing!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo ^= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"bitxor_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
BitXorAssign
<
Rhs
=
Self
>
{
/// The method for the `^=` operator
fn
bitxor_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
bitxor_assign_impl
{
(
$
(
$t:ty
)
+
)
=>
(
$
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
BitXorAssign
for
$t
{
#[inline]
fn
bitxor_assign
(
&
mut
self
,
other
:
$t
)
{
*
self
^=
other
}
}
)
+
)
}
#[cfg(not(stage0))]
bitxor_assign_impl!
{
bool
usize
u8
u16
u32
u64
isize
i8
i16
i32
i64
}
/// The `ShlAssign` trait is used to specify the functionality of `<<=`.
///
/// # Examples
///
/// A trivial implementation of `ShlAssign`. When `Foo <<= Foo` happens, it ends up
/// calling `shl_assign`, and therefore, `main` prints `Shifting left!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::ShlAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl ShlAssign<Foo> for Foo {
/// fn shl_assign(&mut self, _rhs: Foo) {
/// println!("Shifting left!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo <<= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"shl_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
ShlAssign
<
Rhs
>
{
/// The method for the `<<=` operator
fn
shl_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
shl_assign_impl
{
(
$t:ty
,
$f:ty
)
=>
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
ShlAssign
<
$f
>
for
$t
{
#[inline]
fn
shl_assign
(
&
mut
self
,
other
:
$f
)
{
*
self
<<=
other
}
}
)
}
#[cfg(not(stage0))]
macro_rules!
shl_assign_impl_all
{
(
$
(
$t:ty
)
*
)
=>
(
$
(
shl_assign_impl!
{
$t
,
u8
}
shl_assign_impl!
{
$t
,
u16
}
shl_assign_impl!
{
$t
,
u32
}
shl_assign_impl!
{
$t
,
u64
}
shl_assign_impl!
{
$t
,
usize
}
shl_assign_impl!
{
$t
,
i8
}
shl_assign_impl!
{
$t
,
i16
}
shl_assign_impl!
{
$t
,
i32
}
shl_assign_impl!
{
$t
,
i64
}
shl_assign_impl!
{
$t
,
isize
}
)
*
)
}
#[cfg(not(stage0))]
shl_assign_impl_all!
{
u8
u16
u32
u64
usize
i8
i16
i32
i64
isize
}
/// The `ShrAssign` trait is used to specify the functionality of `>>=`.
///
/// # Examples
///
/// A trivial implementation of `ShrAssign`. When `Foo >>= Foo` happens, it ends up
/// calling `shr_assign`, and therefore, `main` prints `Shifting right!`.
///
/// ```
/// #![feature(augmented_assignments)]
/// #![feature(op_assign_traits)]
///
/// use std::ops::ShrAssign;
///
/// #[derive(Copy, Clone)]
/// struct Foo;
///
/// impl ShrAssign<Foo> for Foo {
/// fn shr_assign(&mut self, _rhs: Foo) {
/// println!("Shifting right!");
/// }
/// }
///
/// fn main() {
/// let mut foo = Foo;
/// foo >>= Foo;
/// }
/// ```
#[cfg(not(stage0))]
#[lang
=
"shr_assign"
]
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
pub
trait
ShrAssign
<
Rhs
=
Self
>
{
/// The method for the `>>=` operator
fn
shr_assign
(
&
mut
self
,
Rhs
);
}
#[cfg(not(stage0))]
macro_rules!
shr_assign_impl
{
(
$t:ty
,
$f:ty
)
=>
(
#[unstable(feature
=
"op_assign_traits"
,
reason
=
"recently added"
,
issue
=
"28235"
)]
impl
ShrAssign
<
$f
>
for
$t
{
#[inline]
fn
shr_assign
(
&
mut
self
,
other
:
$f
)
{
*
self
>>=
other
}
}
)
}
#[cfg(not(stage0))]
macro_rules!
shr_assign_impl_all
{
(
$
(
$t:ty
)
*
)
=>
(
$
(
shr_assign_impl!
{
$t
,
u8
}
shr_assign_impl!
{
$t
,
u16
}
shr_assign_impl!
{
$t
,
u32
}
shr_assign_impl!
{
$t
,
u64
}
shr_assign_impl!
{
$t
,
usize
}
shr_assign_impl!
{
$t
,
i8
}
shr_assign_impl!
{
$t
,
i16
}
shr_assign_impl!
{
$t
,
i32
}
shr_assign_impl!
{
$t
,
i64
}
shr_assign_impl!
{
$t
,
isize
}
)
*
)
}
#[cfg(not(stage0))]
shr_assign_impl_all!
{
u8
u16
u32
u64
usize
i8
i16
i32
i64
isize
}
/// The `Index` trait is used to specify the functionality of indexing operations
/// like `arr[idx]` when used in an immutable context.
///
...
...
src/librustc/middle/expr_use_visitor.rs
浏览文件 @
3ae3a5fc
...
...
@@ -525,11 +525,17 @@ pub fn walk_expr(&mut self, expr: &hir::Expr) {
self
.consume_expr
(
&**
base
);
}
hir
::
ExprAssignOp
(
_
,
ref
lhs
,
ref
rhs
)
=>
{
// This will have to change if/when we support
// overloaded operators for `+=` and so forth.
self
.mutate_expr
(
expr
,
&**
lhs
,
WriteAndRead
);
self
.consume_expr
(
&**
rhs
);
hir
::
ExprAssignOp
(
op
,
ref
lhs
,
ref
rhs
)
=>
{
let
pass_args
=
if
::
rustc_front
::
util
::
is_by_value_binop
(
op
.node
)
{
PassArgs
::
ByValue
}
else
{
PassArgs
::
ByRef
};
if
!
self
.walk_overloaded_operator
(
expr
,
&**
lhs
,
vec!
[
&**
rhs
],
pass_args
)
{
self
.mutate_expr
(
expr
,
&**
lhs
,
WriteAndRead
);
self
.consume_expr
(
&**
rhs
);
}
}
hir
::
ExprRepeat
(
ref
base
,
ref
count
)
=>
{
...
...
src/librustc/middle/lang_items.rs
浏览文件 @
3ae3a5fc
...
...
@@ -286,6 +286,16 @@ pub fn collect_language_items(krate: &hir::Crate,
BitOrTraitLangItem
,
"bitor"
,
bitor_trait
;
ShlTraitLangItem
,
"shl"
,
shl_trait
;
ShrTraitLangItem
,
"shr"
,
shr_trait
;
AddAssignTraitLangItem
,
"add_assign"
,
add_assign_trait
;
SubAssignTraitLangItem
,
"sub_assign"
,
sub_assign_trait
;
MulAssignTraitLangItem
,
"mul_assign"
,
mul_assign_trait
;
DivAssignTraitLangItem
,
"div_assign"
,
div_assign_trait
;
RemAssignTraitLangItem
,
"rem_assign"
,
rem_assign_trait
;
BitXorAssignTraitLangItem
,
"bitxor_assign"
,
bitxor_assign_trait
;
BitAndAssignTraitLangItem
,
"bitand_assign"
,
bitand_assign_trait
;
BitOrAssignTraitLangItem
,
"bitor_assign"
,
bitor_assign_trait
;
ShlAssignTraitLangItem
,
"shl_assign"
,
shl_assign_trait
;
ShrAssignTraitLangItem
,
"shr_assign"
,
shr_assign_trait
;
IndexTraitLangItem
,
"index"
,
index_trait
;
IndexMutTraitLangItem
,
"index_mut"
,
index_mut_trait
;
RangeStructLangItem
,
"range"
,
range_struct
;
...
...
src/librustc_trans/trans/expr.rs
浏览文件 @
3ae3a5fc
...
...
@@ -1018,7 +1018,20 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
}
hir
::
ExprAssignOp
(
op
,
ref
dst
,
ref
src
)
=>
{
trans_assign_op
(
bcx
,
expr
,
op
,
&**
dst
,
&**
src
)
let
has_method_map
=
bcx
.tcx
()
.tables
.borrow
()
.method_map
.contains_key
(
&
MethodCall
::
expr
(
expr
.id
));
if
has_method_map
{
let
dst
=
unpack_datum!
(
bcx
,
trans
(
bcx
,
&**
dst
));
let
src_datum
=
unpack_datum!
(
bcx
,
trans
(
bcx
,
&**
src
));
trans_overloaded_op
(
bcx
,
expr
,
MethodCall
::
expr
(
expr
.id
),
dst
,
Some
((
src_datum
,
src
.id
)),
None
,
false
)
.bcx
}
else
{
trans_assign_op
(
bcx
,
expr
,
op
,
&**
dst
,
&**
src
)
}
}
hir
::
ExprInlineAsm
(
ref
a
)
=>
{
asm
::
trans_inline_asm
(
bcx
,
a
)
...
...
@@ -1207,8 +1220,11 @@ fn make_field(field_name: &str, expr: P<hir::Expr>) -> hir::Field {
// Trait casts used to come this way, now they should be coercions.
bcx
.tcx
()
.sess
.span_bug
(
expr
.span
,
"DPS expr_cast (residual trait cast?)"
)
}
hir
::
ExprAssignOp
(
op
,
ref
dst
,
ref
src
)
=>
{
trans_assign_op
(
bcx
,
expr
,
op
,
&**
dst
,
&**
src
)
hir
::
ExprAssignOp
(
op
,
_
,
_
)
=>
{
bcx
.tcx
()
.sess
.span_bug
(
expr
.span
,
&
format!
(
"augmented assignment `{}=` should always be a rvalue_stmt"
,
rustc_front
::
util
::
binop_to_string
(
op
.node
)))
}
_
=>
{
bcx
.tcx
()
.sess
.span_bug
(
...
...
src/librustc_typeck/check/op.rs
浏览文件 @
3ae3a5fc
...
...
@@ -17,10 +17,8 @@
demand
,
method
,
FnCtxt
,
structurally_resolved_type
,
};
use
middle
::
def_id
::
DefId
;
use
middle
::
traits
;
use
middle
::
ty
::{
Ty
,
HasTypeFlags
,
PreferMutLvalue
};
use
syntax
::
ast
;
use
syntax
::
parse
::
token
;
...
...
@@ -34,34 +32,24 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
lhs_expr
:
&
'tcx
hir
::
Expr
,
rhs_expr
:
&
'tcx
hir
::
Expr
)
{
let
tcx
=
fcx
.ccx.tcx
;
check_expr_with_lvalue_pref
(
fcx
,
lhs_expr
,
PreferMutLvalue
);
check_expr
(
fcx
,
rhs_expr
);
let
lhs_ty
=
structurally_resolved_type
(
fcx
,
lhs_expr
.span
,
fcx
.expr_ty
(
lhs_expr
));
let
rhs_ty
=
structurally_resolved_type
(
fcx
,
rhs_expr
.span
,
fcx
.expr_ty
(
rhs_expr
));
let
lhs_ty
=
fcx
.resolve_type_vars_if_possible
(
fcx
.expr_ty
(
lhs_expr
));
let
(
rhs_ty
,
return_ty
)
=
check_overloaded_binop
(
fcx
,
expr
,
lhs_expr
,
lhs_ty
,
rhs_expr
,
op
,
true
);
let
rhs_ty
=
fcx
.resolve_type_vars_if_possible
(
rhs_ty
);
if
is_builtin_binop
(
lhs_ty
,
rhs_ty
,
op
)
{
if
!
lhs_ty
.is_ty_var
()
&&
!
rhs_ty
.is_ty_var
()
&&
is_builtin_binop
(
lhs_ty
,
rhs_ty
,
op
)
{
enforce_builtin_binop_types
(
fcx
,
lhs_expr
,
lhs_ty
,
rhs_expr
,
rhs_ty
,
op
);
fcx
.write_nil
(
expr
.id
);
}
else
{
// error types are considered "builtin"
assert
!
(
!
lhs_ty
.references_error
()
||
!
rhs_ty
.references_error
());
span_err!
(
tcx
.sess
,
lhs_expr
.span
,
E0368
,
"binary assignment operation `{}=` cannot be applied to types `{}` and `{}`"
,
hir_util
::
binop_to_string
(
op
.node
),
lhs_ty
,
rhs_ty
);
fcx
.write_error
(
expr
.id
);
fcx
.write_ty
(
expr
.id
,
return_ty
);
}
let
tcx
=
fcx
.tcx
();
if
!
tcx
.expr_is_lval
(
lhs_expr
)
{
span_err!
(
tcx
.sess
,
lhs_expr
.span
,
E0067
,
"invalid left-hand side expression"
);
}
fcx
.require_expr_have_sized_type
(
lhs_expr
,
traits
::
AssignmentLhsSized
);
}
/// Check a potentially overloaded binary operator.
...
...
@@ -95,7 +83,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
// overloaded. This is the way to be most flexible w/r/t
// types that get inferred.
let
(
rhs_ty
,
return_ty
)
=
check_overloaded_binop
(
fcx
,
expr
,
lhs_expr
,
lhs_ty
,
rhs_expr
,
op
);
check_overloaded_binop
(
fcx
,
expr
,
lhs_expr
,
lhs_ty
,
rhs_expr
,
op
,
false
);
// Supply type inference hints if relevant. Probably these
// hints should be enforced during select as part of the
...
...
@@ -167,14 +155,16 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
lhs_expr
:
&
'tcx
hir
::
Expr
,
lhs_ty
:
Ty
<
'tcx
>
,
rhs_expr
:
&
'tcx
hir
::
Expr
,
op
:
hir
::
BinOp
)
op
:
hir
::
BinOp
,
assign
:
bool
)
->
(
Ty
<
'tcx
>
,
Ty
<
'tcx
>
)
{
debug!
(
"check_overloaded_binop(expr.id={}, lhs_ty={:?})"
,
debug!
(
"check_overloaded_binop(expr.id={}, lhs_ty={:?}
, assign={}
)"
,
expr
.id
,
lhs_ty
);
lhs_ty
,
assign
);
let
(
name
,
trait_def_id
)
=
name_and_trait_def_id
(
fcx
,
op
);
let
(
name
,
trait_def_id
)
=
name_and_trait_def_id
(
fcx
,
op
,
assign
);
// NB: As we have not yet type-checked the RHS, we don't have the
// type at hand. Make a variable to represent it. The whole reason
...
...
@@ -191,10 +181,17 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
Err
(())
=>
{
// error types are considered "builtin"
if
!
lhs_ty
.references_error
()
{
span_err!
(
fcx
.tcx
()
.sess
,
lhs_expr
.span
,
E0369
,
"binary operation `{}` cannot be applied to type `{}`"
,
hir_util
::
binop_to_string
(
op
.node
),
lhs_ty
);
if
assign
{
span_err!
(
fcx
.tcx
()
.sess
,
lhs_expr
.span
,
E0368
,
"binary assignment operation `{}=` cannot be applied to type `{}`"
,
hir_util
::
binop_to_string
(
op
.node
),
lhs_ty
);
}
else
{
span_err!
(
fcx
.tcx
()
.sess
,
lhs_expr
.span
,
E0369
,
"binary operation `{}` cannot be applied to type `{}`"
,
hir_util
::
binop_to_string
(
op
.node
),
lhs_ty
);
}
}
fcx
.tcx
()
.types.err
}
...
...
@@ -231,27 +228,51 @@ pub fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
}
}
fn
name_and_trait_def_id
(
fcx
:
&
FnCtxt
,
op
:
hir
::
BinOp
)
->
(
&
'static
str
,
Option
<
DefId
>
)
{
fn
name_and_trait_def_id
(
fcx
:
&
FnCtxt
,
op
:
hir
::
BinOp
,
assign
:
bool
)
->
(
&
'static
str
,
Option
<
DefId
>
)
{
let
lang
=
&
fcx
.tcx
()
.lang_items
;
match
op
.node
{
hir
::
BiAdd
=>
(
"add"
,
lang
.add_trait
()),
hir
::
BiSub
=>
(
"sub"
,
lang
.sub_trait
()),
hir
::
BiMul
=>
(
"mul"
,
lang
.mul_trait
()),
hir
::
BiDiv
=>
(
"div"
,
lang
.div_trait
()),
hir
::
BiRem
=>
(
"rem"
,
lang
.rem_trait
()),
hir
::
BiBitXor
=>
(
"bitxor"
,
lang
.bitxor_trait
()),
hir
::
BiBitAnd
=>
(
"bitand"
,
lang
.bitand_trait
()),
hir
::
BiBitOr
=>
(
"bitor"
,
lang
.bitor_trait
()),
hir
::
BiShl
=>
(
"shl"
,
lang
.shl_trait
()),
hir
::
BiShr
=>
(
"shr"
,
lang
.shr_trait
()),
hir
::
BiLt
=>
(
"lt"
,
lang
.ord_trait
()),
hir
::
BiLe
=>
(
"le"
,
lang
.ord_trait
()),
hir
::
BiGe
=>
(
"ge"
,
lang
.ord_trait
()),
hir
::
BiGt
=>
(
"gt"
,
lang
.ord_trait
()),
hir
::
BiEq
=>
(
"eq"
,
lang
.eq_trait
()),
hir
::
BiNe
=>
(
"ne"
,
lang
.eq_trait
()),
hir
::
BiAnd
|
hir
::
BiOr
=>
{
fcx
.tcx
()
.sess
.span_bug
(
op
.span
,
"&& and || are not overloadable"
)
if
assign
{
match
op
.node
{
hir
::
BiAdd
=>
(
"add_assign"
,
lang
.add_assign_trait
()),
hir
::
BiSub
=>
(
"sub_assign"
,
lang
.sub_assign_trait
()),
hir
::
BiMul
=>
(
"mul_assign"
,
lang
.mul_assign_trait
()),
hir
::
BiDiv
=>
(
"div_assign"
,
lang
.div_assign_trait
()),
hir
::
BiRem
=>
(
"rem_assign"
,
lang
.rem_assign_trait
()),
hir
::
BiBitXor
=>
(
"bitxor_assign"
,
lang
.bitxor_assign_trait
()),
hir
::
BiBitAnd
=>
(
"bitand_assign"
,
lang
.bitand_assign_trait
()),
hir
::
BiBitOr
=>
(
"bitor_assign"
,
lang
.bitor_assign_trait
()),
hir
::
BiShl
=>
(
"shl_assign"
,
lang
.shl_assign_trait
()),
hir
::
BiShr
=>
(
"shr_assign"
,
lang
.shr_assign_trait
()),
hir
::
BiLt
|
hir
::
BiLe
|
hir
::
BiGe
|
hir
::
BiGt
|
hir
::
BiEq
|
hir
::
BiNe
|
hir
::
BiAnd
|
hir
::
BiOr
=>
{
fcx
.tcx
()
.sess
.span_bug
(
op
.span
,
&
format!
(
"impossible assignment operation: {}="
,
hir_util
::
binop_to_string
(
op
.node
)))
}
}
}
else
{
match
op
.node
{
hir
::
BiAdd
=>
(
"add"
,
lang
.add_trait
()),
hir
::
BiSub
=>
(
"sub"
,
lang
.sub_trait
()),
hir
::
BiMul
=>
(
"mul"
,
lang
.mul_trait
()),
hir
::
BiDiv
=>
(
"div"
,
lang
.div_trait
()),
hir
::
BiRem
=>
(
"rem"
,
lang
.rem_trait
()),
hir
::
BiBitXor
=>
(
"bitxor"
,
lang
.bitxor_trait
()),
hir
::
BiBitAnd
=>
(
"bitand"
,
lang
.bitand_trait
()),
hir
::
BiBitOr
=>
(
"bitor"
,
lang
.bitor_trait
()),
hir
::
BiShl
=>
(
"shl"
,
lang
.shl_trait
()),
hir
::
BiShr
=>
(
"shr"
,
lang
.shr_trait
()),
hir
::
BiLt
=>
(
"lt"
,
lang
.ord_trait
()),
hir
::
BiLe
=>
(
"le"
,
lang
.ord_trait
()),
hir
::
BiGe
=>
(
"ge"
,
lang
.ord_trait
()),
hir
::
BiGt
=>
(
"gt"
,
lang
.ord_trait
()),
hir
::
BiEq
=>
(
"eq"
,
lang
.eq_trait
()),
hir
::
BiNe
=>
(
"ne"
,
lang
.eq_trait
()),
hir
::
BiAnd
|
hir
::
BiOr
=>
{
fcx
.tcx
()
.sess
.span_bug
(
op
.span
,
"&& and || are not overloadable"
)
}
}
}
}
...
...
src/librustc_typeck/check/regionck.rs
浏览文件 @
3ae3a5fc
...
...
@@ -695,7 +695,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &hir::Expr) {
hir
::
ExprAssignOp
(
_
,
ref
lhs
,
ref
rhs
)
=>
{
if
has_method_map
{
constrain_call
(
rcx
,
expr
,
Some
(
&**
lhs
),
Some
(
&**
rhs
)
.into_iter
(),
tru
e
);
Some
(
&**
rhs
)
.into_iter
(),
fals
e
);
}
visit
::
walk_expr
(
rcx
,
expr
);
...
...
src/librustc_typeck/check/writeback.rs
浏览文件 @
3ae3a5fc
...
...
@@ -17,7 +17,7 @@
use
check
::
FnCtxt
;
use
middle
::
def_id
::
DefId
;
use
middle
::
pat_util
;
use
middle
::
ty
::{
self
,
Ty
,
MethodCall
,
MethodCallee
};
use
middle
::
ty
::{
self
,
Ty
,
MethodCall
,
MethodCallee
,
HasTypeFlags
};
use
middle
::
ty
::
adjustment
;
use
middle
::
ty
::
fold
::{
TypeFolder
,
TypeFoldable
};
use
middle
::
infer
;
...
...
@@ -91,24 +91,51 @@ fn tcx(&self) -> &'cx ty::ctxt<'tcx> {
// we observe that something like `a+b` is (known to be)
// operating on scalars, we clear the overload.
fn
fix_scalar_binary_expr
(
&
mut
self
,
e
:
&
hir
::
Expr
)
{
if
let
hir
::
ExprBinary
(
ref
op
,
ref
lhs
,
ref
rhs
)
=
e
.node
{
let
lhs_ty
=
self
.fcx
.node_ty
(
lhs
.id
);
let
lhs_ty
=
self
.fcx
.infcx
()
.resolve_type_vars_if_possible
(
&
lhs_ty
);
let
rhs_ty
=
self
.fcx
.node_ty
(
rhs
.id
);
let
rhs_ty
=
self
.fcx
.infcx
()
.resolve_type_vars_if_possible
(
&
rhs_ty
);
if
lhs_ty
.is_scalar
()
&&
rhs_ty
.is_scalar
()
{
self
.fcx.inh.tables
.borrow_mut
()
.method_map
.remove
(
&
MethodCall
::
expr
(
e
.id
));
// weird but true: the by-ref binops put an
// adjustment on the lhs but not the rhs; the
// adjustment for rhs is kind of baked into the
// system.
if
!
hir_util
::
is_by_value_binop
(
op
.node
)
{
self
.fcx.inh.tables
.borrow_mut
()
.adjustments
.remove
(
&
lhs
.id
);
match
e
.node
{
hir
::
ExprBinary
(
ref
op
,
ref
lhs
,
ref
rhs
)
|
hir
::
ExprAssignOp
(
ref
op
,
ref
lhs
,
ref
rhs
)
=>
{
let
lhs_ty
=
self
.fcx
.node_ty
(
lhs
.id
);
let
lhs_ty
=
self
.fcx
.infcx
()
.resolve_type_vars_if_possible
(
&
lhs_ty
);
let
rhs_ty
=
self
.fcx
.node_ty
(
rhs
.id
);
let
rhs_ty
=
self
.fcx
.infcx
()
.resolve_type_vars_if_possible
(
&
rhs_ty
);
if
lhs_ty
.is_scalar
()
&&
rhs_ty
.is_scalar
()
{
self
.fcx.inh.tables
.borrow_mut
()
.method_map
.remove
(
&
MethodCall
::
expr
(
e
.id
));
// weird but true: the by-ref binops put an
// adjustment on the lhs but not the rhs; the
// adjustment for rhs is kind of baked into the
// system.
match
e
.node
{
hir
::
ExprBinary
(
..
)
=>
{
if
!
hir_util
::
is_by_value_binop
(
op
.node
)
{
self
.fcx.inh.tables
.borrow_mut
()
.adjustments
.remove
(
&
lhs
.id
);
}
},
hir
::
ExprAssignOp
(
..
)
=>
{
self
.fcx.inh.tables
.borrow_mut
()
.adjustments
.remove
(
&
lhs
.id
);
},
_
=>
{},
}
}
else
{
let
tcx
=
self
.tcx
();
if
let
hir
::
ExprAssignOp
(
..
)
=
e
.node
{
if
!
tcx
.sess.features
.borrow
()
.augmented_assignments
&&
!
self
.fcx
.expr_ty
(
e
)
.references_error
()
{
tcx
.sess
.span_err
(
e
.span
,
"overloaded augmented assignments are not stable"
);
fileline_help!
(
tcx
.sess
,
e
.span
,
"add #![feature(augmented_assignments)] to the crate features
\
to enable"
);
}
}
}
}
}
_
=>
{},
}
}
}
...
...
src/librustc_typeck/diagnostics.rs
浏览文件 @
3ae3a5fc
...
...
@@ -2862,14 +2862,27 @@ fn drop(&mut self) {}
E0368
:
r##"
This error indicates that a binary assignment operator like `+=` or `^=` was
applied to
the wrong types
. For example:
applied to
a type that doesn't support it
. For example:
```
let mut x: u16 = 5;
x ^= true; // error, `^=` cannot be applied to types `u16` and `bool`
x += (); // error, `+=` cannot be applied to types `u16` and `()`
let mut x = 12f32; // error: binary operation `<<` cannot be applied to
// type `f32`
x <<= 2;
```
To fix this error, please check that this type implements this binary
operation. Example:
```
let x = 12u32; // the `u32` type does implement the `ShlAssign` trait
x <<= 2; // ok!
```
It is also possible to overload most operators for your own type by
implementing the `[OP]Assign` traits from `std::ops`.
Another problem you might be facing is this: suppose you've overloaded the `+`
operator for some type `Foo` by implementing the `std::ops::Add` trait for
`Foo`, but you find that using `+=` does not work, as in this example:
...
...
@@ -2889,15 +2902,12 @@ fn add(self, rhs: Foo) -> Foo {
fn main() {
let mut x: Foo = Foo(5);
x += Foo(7); // error, `+= cannot be applied to t
ypes `Foo` and
`Foo`
x += Foo(7); // error, `+= cannot be applied to t
he type
`Foo`
}
```
This is because the binary assignment operators currently do not work off of
traits, so it is not possible to overload them. See [RFC 953] for a proposal
to change this.
[RFC 953]: https://github.com/rust-lang/rfcs/pull/953
This is because `AddAssign` is not automatically implemented, so you need to
manually implement it for your type.
"##
,
E0369
:
r##"
...
...
src/libsyntax/feature_gate.rs
浏览文件 @
3ae3a5fc
...
...
@@ -194,6 +194,9 @@
// allow empty structs/enum variants with braces
(
"braced_empty_structs"
,
"1.5.0"
,
None
,
Active
),
// allow overloading augmented assignment operations like `a += b`
(
"augmented_assignments"
,
"1.5.0"
,
None
,
Active
),
];
// (changing above list without updating src/doc/reference.md makes @cmr sad)
...
...
@@ -457,6 +460,7 @@ pub struct Features {
pub
default_type_parameter_fallback
:
bool
,
pub
type_macros
:
bool
,
pub
cfg_target_feature
:
bool
,
pub
augmented_assignments
:
bool
,
}
impl
Features
{
...
...
@@ -485,6 +489,7 @@ pub fn new() -> Features {
default_type_parameter_fallback
:
false
,
type_macros
:
false
,
cfg_target_feature
:
false
,
augmented_assignments
:
false
,
}
}
}
...
...
@@ -1053,6 +1058,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
default_type_parameter_fallback
:
cx
.has_feature
(
"default_type_parameter_fallback"
),
type_macros
:
cx
.has_feature
(
"type_macros"
),
cfg_target_feature
:
cx
.has_feature
(
"cfg_target_feature"
),
augmented_assignments
:
cx
.has_feature
(
"augmented_assignments"
),
}
}
...
...
src/test/auxiliary/augmented_assignments.rs
0 → 100644
浏览文件 @
3ae3a5fc
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(augmented_assignments)]
#![feature(op_assign_traits)]
use
std
::
ops
::
AddAssign
;
pub
struct
Int
(
i32
);
impl
AddAssign
<
i32
>
for
Int
{
fn
add_assign
(
&
mut
self
,
_
:
i32
)
{
unimplemented!
();
}
}
src/test/compile-fail/assignment-operator-unimplemented.rs
浏览文件 @
3ae3a5fc
...
...
@@ -13,5 +13,5 @@
fn
main
()
{
let
mut
a
=
Foo
;
let
ref
b
=
Foo
;
a
+=
*
b
;
//~ Error: binary assignment operation `+=` cannot be applied to type
s `Foo` and
`Foo`
a
+=
*
b
;
//~ Error: binary assignment operation `+=` cannot be applied to type `Foo`
}
src/test/compile-fail/augmented-assignments-feature-gate-cross.rs
0 → 100644
浏览文件 @
3ae3a5fc
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:augmented_assignments.rs
// Test that the feature gate is needed when using augmented assignments that were overloaded in
// another crate
extern
crate
augmented_assignments
;
use
augmented_assignments
::
Int
;
fn
main
()
{
let
mut
x
=
Int
(
0
);
x
+=
1
;
//~^ error: overloaded augmented assignments are not stable
// | help: add #![feature(augmented_assignments)] to the crate features to enable
}
src/test/compile-fail/augmented-assignments-feature-gate.rs
0 → 100644
浏览文件 @
3ae3a5fc
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use
std
::
ops
::
AddAssign
;
struct
Int
(
i32
);
impl
AddAssign
<
i32
>
for
Int
{
fn
add_assign
(
&
mut
self
,
_
:
i32
)
{
unimplemented!
()
}
}
fn
main
()
{
let
mut
x
=
Int
(
0
);
x
+=
1
;
//~^ error: overloaded augmented assignments are not stable
// | help: add #![feature(augmented_assignments)] to the crate features to enable
}
src/test/compile-fail/augmented-assignments.rs
0 → 100644
浏览文件 @
3ae3a5fc
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(augmented_assignments)]
use
std
::
ops
::
AddAssign
;
struct
Int
(
i32
);
impl
AddAssign
for
Int
{
fn
add_assign
(
&
mut
self
,
_
:
Int
)
{
unimplemented!
()
}
}
fn
main
()
{
let
mut
x
=
Int
(
1
);
x
//~ error: use of moved value: `x`
+=
x
;
//~ note: `x` moved here because it has type `Int`, which is non-copyable
let
y
=
Int
(
2
);
y
//~ error: cannot borrow immutable local variable `y` as mutable
+=
Int
(
1
);
}
src/test/run-pass/augmented-assignments.rs
0 → 100644
浏览文件 @
3ae3a5fc
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(augmented_assignments)]
#![feature(op_assign_traits)]
use
std
::
mem
;
use
std
::
ops
::{
AddAssign
,
BitAndAssign
,
BitOrAssign
,
BitXorAssign
,
DivAssign
,
Index
,
MulAssign
,
RemAssign
,
ShlAssign
,
ShrAssign
,
SubAssign
,
};
#[derive(Debug,
PartialEq)]
struct
Int
(
i32
);
struct
Slice
([
i32
]);
impl
Slice
{
fn
new
(
slice
:
&
mut
[
i32
])
->
&
mut
Slice
{
unsafe
{
mem
::
transmute
(
slice
)
}
}
}
fn
main
()
{
let
mut
x
=
Int
(
1
);
x
+=
Int
(
2
);
assert_eq!
(
x
,
Int
(
0b11
));
x
&=
Int
(
0b01
);
assert_eq!
(
x
,
Int
(
0b01
));
x
|
=
Int
(
0b10
);
assert_eq!
(
x
,
Int
(
0b11
));
x
^=
Int
(
0b01
);
assert_eq!
(
x
,
Int
(
0b10
));
x
/=
Int
(
2
);
assert_eq!
(
x
,
Int
(
1
));
x
*=
Int
(
3
);
assert_eq!
(
x
,
Int
(
3
));
x
%=
Int
(
2
);
assert_eq!
(
x
,
Int
(
1
));
// overloaded RHS
x
<<=
1u8
;
assert_eq!
(
x
,
Int
(
2
));
x
<<=
1u16
;
assert_eq!
(
x
,
Int
(
4
));
x
>>=
1u8
;
assert_eq!
(
x
,
Int
(
2
));
x
>>=
1u16
;
assert_eq!
(
x
,
Int
(
1
));
x
-=
Int
(
1
);
assert_eq!
(
x
,
Int
(
0
));
// indexed LHS
let
mut
v
=
vec!
[
Int
(
1
),
Int
(
2
)];
v
[
0
]
+=
Int
(
2
);
assert_eq!
(
v
[
0
],
Int
(
3
));
// unsized RHS
let
mut
array
=
[
0
,
1
,
2
];
*
Slice
::
new
(
&
mut
array
)
+=
1
;
assert_eq!
(
array
[
0
],
1
);
assert_eq!
(
array
[
1
],
2
);
assert_eq!
(
array
[
2
],
3
);
}
impl
AddAssign
for
Int
{
fn
add_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
+=
rhs
.0
;
}
}
impl
BitAndAssign
for
Int
{
fn
bitand_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
&=
rhs
.0
;
}
}
impl
BitOrAssign
for
Int
{
fn
bitor_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
|
=
rhs
.0
;
}
}
impl
BitXorAssign
for
Int
{
fn
bitxor_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
^=
rhs
.0
;
}
}
impl
DivAssign
for
Int
{
fn
div_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
/=
rhs
.0
;
}
}
impl
MulAssign
for
Int
{
fn
mul_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
*=
rhs
.0
;
}
}
impl
RemAssign
for
Int
{
fn
rem_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
%=
rhs
.0
;
}
}
impl
ShlAssign
<
u8
>
for
Int
{
fn
shl_assign
(
&
mut
self
,
rhs
:
u8
)
{
self
.0
<<=
rhs
;
}
}
impl
ShlAssign
<
u16
>
for
Int
{
fn
shl_assign
(
&
mut
self
,
rhs
:
u16
)
{
self
.0
<<=
rhs
;
}
}
impl
ShrAssign
<
u8
>
for
Int
{
fn
shr_assign
(
&
mut
self
,
rhs
:
u8
)
{
self
.0
>>=
rhs
;
}
}
impl
ShrAssign
<
u16
>
for
Int
{
fn
shr_assign
(
&
mut
self
,
rhs
:
u16
)
{
self
.0
>>=
rhs
;
}
}
impl
SubAssign
for
Int
{
fn
sub_assign
(
&
mut
self
,
rhs
:
Int
)
{
self
.0
-=
rhs
.0
;
}
}
impl
AddAssign
<
i32
>
for
Slice
{
fn
add_assign
(
&
mut
self
,
rhs
:
i32
)
{
for
lhs
in
&
mut
self
.0
{
*
lhs
+=
rhs
;
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录