rollup merge of #17318 : nick29581/slice
This commit is contained in:
commit
81ee3586b5
@ -20,6 +20,7 @@ use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::mem;
|
||||
use core::num;
|
||||
use core::ops;
|
||||
use core::ptr;
|
||||
use core::raw::Slice as RawSlice;
|
||||
use core::uint;
|
||||
@ -464,6 +465,47 @@ impl<T> Index<uint,T> for Vec<T> {
|
||||
}
|
||||
}*/
|
||||
|
||||
impl<T> ops::Slice<uint, [T]> for Vec<T> {
|
||||
#[inline]
|
||||
fn as_slice_<'a>(&'a self) -> &'a [T] {
|
||||
self.as_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
|
||||
self.as_slice().slice_from_(start)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
|
||||
self.as_slice().slice_to_(end)
|
||||
}
|
||||
#[inline]
|
||||
fn slice_<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
|
||||
self.as_slice().slice_(start, end)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::SliceMut<uint, [T]> for Vec<T> {
|
||||
#[inline]
|
||||
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
|
||||
self.as_mut_slice()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_from_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
|
||||
self.as_mut_slice().slice_from_mut_(start)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
|
||||
self.as_mut_slice().slice_to_mut_(end)
|
||||
}
|
||||
#[inline]
|
||||
fn slice_mut_<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
|
||||
self.as_mut_slice().slice_mut_(start, end)
|
||||
}
|
||||
}
|
||||
impl<T> FromIterator<T> for Vec<T> {
|
||||
#[inline]
|
||||
fn from_iter<I:Iterator<T>>(mut iterator: I) -> Vec<T> {
|
||||
@ -2327,6 +2369,44 @@ mod tests {
|
||||
let _ = vec[3];
|
||||
}
|
||||
|
||||
// NOTE uncomment after snapshot
|
||||
/*
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_slice_out_of_bounds_1() {
|
||||
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
x[-1..];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_slice_out_of_bounds_2() {
|
||||
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
x[..6];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_slice_out_of_bounds_3() {
|
||||
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
x[-1..4];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_slice_out_of_bounds_4() {
|
||||
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
x[1..6];
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_slice_out_of_bounds_5() {
|
||||
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
x[3..2];
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn test_swap_remove_empty() {
|
||||
let mut vec: Vec<uint> = vec!();
|
||||
|
@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
|
||||
* ```
|
||||
*/
|
||||
#[lang="index"]
|
||||
pub trait Index<Index,Result> {
|
||||
pub trait Index<Index, Result> {
|
||||
/// The method for the indexing (`Foo[Bar]`) operation
|
||||
fn index<'a>(&'a self, index: &Index) -> &'a Result;
|
||||
}
|
||||
@ -651,7 +651,7 @@ pub trait Index<Index,Result> {
|
||||
* # Example
|
||||
*
|
||||
* A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
|
||||
* calling `index`, and therefore, `main` prints `Indexing!`.
|
||||
* calling `index_mut`, and therefore, `main` prints `Indexing!`.
|
||||
*
|
||||
* ```
|
||||
* struct Foo;
|
||||
@ -669,11 +669,110 @@ pub trait Index<Index,Result> {
|
||||
* ```
|
||||
*/
|
||||
#[lang="index_mut"]
|
||||
pub trait IndexMut<Index,Result> {
|
||||
pub trait IndexMut<Index, Result> {
|
||||
/// The method for the indexing (`Foo[Bar]`) operation
|
||||
fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The `Slice` trait is used to specify the functionality of slicing operations
|
||||
* like `arr[from..to]` when used in an immutable context.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* A trivial implementation of `Slice`. When `Foo[..Foo]` happens, it ends up
|
||||
* calling `slice_to`, and therefore, `main` prints `Slicing!`.
|
||||
*
|
||||
* ```
|
||||
* struct Foo;
|
||||
*
|
||||
* impl ::core::ops::Slice<Foo, Foo> for Foo {
|
||||
* fn as_slice_<'a>(&'a self) -> &'a Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* fn slice_from_<'a>(&'a self, from: &Foo) -> &'a Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* fn slice_to_<'a>(&'a self, to: &Foo) -> &'a Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* fn slice_<'a>(&'a self, from: &Foo, to: &Foo) -> &'a Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* fn main() {
|
||||
* Foo[..Foo];
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
// FIXME(#17273) remove the postscript _s
|
||||
#[lang="slice"]
|
||||
pub trait Slice<Idx, Sized? Result> for Sized? {
|
||||
/// The method for the slicing operation foo[]
|
||||
fn as_slice_<'a>(&'a self) -> &'a Result;
|
||||
/// The method for the slicing operation foo[from..]
|
||||
fn slice_from_<'a>(&'a self, from: &Idx) -> &'a Result;
|
||||
/// The method for the slicing operation foo[..to]
|
||||
fn slice_to_<'a>(&'a self, to: &Idx) -> &'a Result;
|
||||
/// The method for the slicing operation foo[from..to]
|
||||
fn slice_<'a>(&'a self, from: &Idx, to: &Idx) -> &'a Result;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* The `SliceMut` trait is used to specify the functionality of slicing
|
||||
* operations like `arr[from..to]`, when used in a mutable context.
|
||||
*
|
||||
* # Example
|
||||
*
|
||||
* A trivial implementation of `SliceMut`. When `Foo[Foo..]` happens, it ends up
|
||||
* calling `slice_from_mut`, and therefore, `main` prints `Slicing!`.
|
||||
*
|
||||
* ```
|
||||
* struct Foo;
|
||||
*
|
||||
* impl ::core::ops::SliceMut<Foo, Foo> for Foo {
|
||||
* fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* fn slice_from_mut_<'a>(&'a mut self, from: &Foo) -> &'a mut Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* fn slice_to_mut_<'a>(&'a mut self, to: &Foo) -> &'a mut Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* fn slice_mut_<'a>(&'a mut self, from: &Foo, to: &Foo) -> &'a mut Foo {
|
||||
* println!("Slicing!");
|
||||
* self
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* fn main() {
|
||||
* Foo[mut Foo..];
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
// FIXME(#17273) remove the postscript _s
|
||||
#[lang="slice_mut"]
|
||||
pub trait SliceMut<Idx, Sized? Result> for Sized? {
|
||||
/// The method for the slicing operation foo[]
|
||||
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Result;
|
||||
/// The method for the slicing operation foo[from..]
|
||||
fn slice_from_mut_<'a>(&'a mut self, from: &Idx) -> &'a mut Result;
|
||||
/// The method for the slicing operation foo[..to]
|
||||
fn slice_to_mut_<'a>(&'a mut self, to: &Idx) -> &'a mut Result;
|
||||
/// The method for the slicing operation foo[from..to]
|
||||
fn slice_mut_<'a>(&'a mut self, from: &Idx, to: &Idx) -> &'a mut Result;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* The `Deref` trait is used to specify the functionality of dereferencing
|
||||
|
@ -42,6 +42,7 @@ use cmp;
|
||||
use default::Default;
|
||||
use iter::*;
|
||||
use num::{CheckedAdd, Saturating, div_rem};
|
||||
use ops;
|
||||
use option::{None, Option, Some};
|
||||
use ptr;
|
||||
use ptr::RawPtr;
|
||||
@ -475,6 +476,63 @@ impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::Slice<uint, [T]> for [T] {
|
||||
#[inline]
|
||||
fn as_slice_<'a>(&'a self) -> &'a [T] {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_from_<'a>(&'a self, start: &uint) -> &'a [T] {
|
||||
self.slice_(start, &self.len())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_to_<'a>(&'a self, end: &uint) -> &'a [T] {
|
||||
self.slice_(&0, end)
|
||||
}
|
||||
#[inline]
|
||||
fn slice_<'a>(&'a self, start: &uint, end: &uint) -> &'a [T] {
|
||||
assert!(*start <= *end);
|
||||
assert!(*end <= self.len());
|
||||
unsafe {
|
||||
transmute(RawSlice {
|
||||
data: self.as_ptr().offset(*start as int),
|
||||
len: (*end - *start)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ops::SliceMut<uint, [T]> for [T] {
|
||||
#[inline]
|
||||
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut [T] {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_from_mut_<'a>(&'a mut self, start: &uint) -> &'a mut [T] {
|
||||
let len = &self.len();
|
||||
self.slice_mut_(start, len)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn slice_to_mut_<'a>(&'a mut self, end: &uint) -> &'a mut [T] {
|
||||
self.slice_mut_(&0, end)
|
||||
}
|
||||
#[inline]
|
||||
fn slice_mut_<'a>(&'a mut self, start: &uint, end: &uint) -> &'a mut [T] {
|
||||
assert!(*start <= *end);
|
||||
assert!(*end <= self.len());
|
||||
unsafe {
|
||||
transmute(RawSlice {
|
||||
data: self.as_ptr().offset(*start as int),
|
||||
len: (*end - *start)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension methods for vectors such that their elements are
|
||||
/// mutable.
|
||||
#[experimental = "may merge with other traits; may lose region param; needs review"]
|
||||
|
@ -424,6 +424,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
self.call(expr, pred, &**l, Some(&**r).into_iter())
|
||||
}
|
||||
|
||||
ast::ExprSlice(ref base, ref start, ref end, _) => {
|
||||
self.call(expr,
|
||||
pred,
|
||||
&**base,
|
||||
start.iter().chain(end.iter()).map(|x| &**x))
|
||||
}
|
||||
|
||||
ast::ExprUnary(_, ref e) if self.is_method_call(expr) => {
|
||||
self.call(expr, pred, &**e, None::<ast::Expr>.iter())
|
||||
}
|
||||
|
@ -316,7 +316,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
|
||||
ast::ExprPath(..) => { }
|
||||
|
||||
ast::ExprUnary(ast::UnDeref, ref base) => { // *base
|
||||
if !self.walk_overloaded_operator(expr, &**base, None) {
|
||||
if !self.walk_overloaded_operator(expr, &**base, Vec::new()) {
|
||||
self.select_from_expr(&**base);
|
||||
}
|
||||
}
|
||||
@ -330,12 +330,23 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
|
||||
}
|
||||
|
||||
ast::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
|
||||
if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
|
||||
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
|
||||
self.select_from_expr(&**lhs);
|
||||
self.consume_expr(&**rhs);
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprSlice(ref base, ref start, ref end, _) => { // base[start..end]
|
||||
let args = match (start, end) {
|
||||
(&Some(ref e1), &Some(ref e2)) => vec![&**e1, &**e2],
|
||||
(&Some(ref e), &None) => vec![&**e],
|
||||
(&None, &Some(ref e)) => vec![&**e],
|
||||
(&None, &None) => Vec::new()
|
||||
};
|
||||
let overloaded = self.walk_overloaded_operator(expr, &**base, args);
|
||||
assert!(overloaded);
|
||||
}
|
||||
|
||||
ast::ExprCall(ref callee, ref args) => { // callee(args)
|
||||
self.walk_callee(expr, &**callee);
|
||||
self.consume_exprs(args);
|
||||
@ -430,13 +441,13 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
|
||||
}
|
||||
|
||||
ast::ExprUnary(_, ref lhs) => {
|
||||
if !self.walk_overloaded_operator(expr, &**lhs, None) {
|
||||
if !self.walk_overloaded_operator(expr, &**lhs, Vec::new()) {
|
||||
self.consume_expr(&**lhs);
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprBinary(_, ref lhs, ref rhs) => {
|
||||
if !self.walk_overloaded_operator(expr, &**lhs, Some(&**rhs)) {
|
||||
if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs]) {
|
||||
self.consume_expr(&**lhs);
|
||||
self.consume_expr(&**rhs);
|
||||
}
|
||||
@ -774,7 +785,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
|
||||
fn walk_overloaded_operator(&mut self,
|
||||
expr: &ast::Expr,
|
||||
receiver: &ast::Expr,
|
||||
rhs: Option<&ast::Expr>)
|
||||
rhs: Vec<&ast::Expr>)
|
||||
-> bool
|
||||
{
|
||||
if !self.typer.is_method_call(expr.id) {
|
||||
|
@ -247,6 +247,8 @@ lets_do_this! {
|
||||
ShrTraitLangItem, "shr", shr_trait;
|
||||
IndexTraitLangItem, "index", index_trait;
|
||||
IndexMutTraitLangItem, "index_mut", index_mut_trait;
|
||||
SliceTraitLangItem, "slice", slice_trait;
|
||||
SliceMutTraitLangItem, "slice_mut", slice_mut_trait;
|
||||
|
||||
UnsafeTypeLangItem, "unsafe", unsafe_type;
|
||||
|
||||
|
@ -501,7 +501,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
||||
|
||||
// otherwise, live nodes are not required:
|
||||
ExprIndex(..) | ExprField(..) | ExprTupField(..) | ExprVec(..) |
|
||||
ExprCall(..) | ExprMethodCall(..) | ExprTup(..) |
|
||||
ExprCall(..) | ExprMethodCall(..) | ExprTup(..) | ExprSlice(..) |
|
||||
ExprBinary(..) | ExprAddrOf(..) |
|
||||
ExprCast(..) | ExprUnary(..) | ExprBreak(_) |
|
||||
ExprAgain(_) | ExprLit(_) | ExprRet(..) | ExprBlock(..) |
|
||||
@ -1174,6 +1174,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
self.propagate_through_expr(&**l, r_succ)
|
||||
}
|
||||
|
||||
ExprSlice(ref e1, ref e2, ref e3, _) => {
|
||||
let succ = e3.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
|
||||
let succ = e2.as_ref().map_or(succ, |e| self.propagate_through_expr(&**e, succ));
|
||||
self.propagate_through_expr(&**e1, succ)
|
||||
}
|
||||
|
||||
ExprAddrOf(_, ref e) |
|
||||
ExprCast(ref e, _) |
|
||||
ExprUnary(_, ref e) |
|
||||
@ -1457,7 +1463,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||
ExprWhile(..) | ExprLoop(..) | ExprIndex(..) | ExprField(..) |
|
||||
ExprTupField(..) | ExprVec(..) | ExprTup(..) | ExprBinary(..) |
|
||||
ExprCast(..) | ExprUnary(..) | ExprRet(..) | ExprBreak(..) |
|
||||
ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
|
||||
ExprAgain(..) | ExprLit(_) | ExprBlock(..) | ExprSlice(..) |
|
||||
ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
|
||||
ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprUnboxedFn(..) |
|
||||
ExprPath(..) | ExprBox(..) => {
|
||||
|
@ -494,7 +494,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
ast::ExprAssign(..) | ast::ExprAssignOp(..) |
|
||||
ast::ExprFnBlock(..) | ast::ExprProc(..) |
|
||||
ast::ExprUnboxedFn(..) | ast::ExprRet(..) |
|
||||
ast::ExprUnary(..) |
|
||||
ast::ExprUnary(..) | ast::ExprSlice(..) |
|
||||
ast::ExprMethodCall(..) | ast::ExprCast(..) |
|
||||
ast::ExprVec(..) | ast::ExprTup(..) | ast::ExprIf(..) |
|
||||
ast::ExprBinary(..) | ast::ExprWhile(..) |
|
||||
|
@ -858,10 +858,10 @@ pub enum CallArgs<'a> {
|
||||
// value.
|
||||
ArgVals(&'a [ValueRef]),
|
||||
|
||||
// For overloaded operators: `(lhs, Option(rhs, rhs_id))`. `lhs`
|
||||
// For overloaded operators: `(lhs, Vec(rhs, rhs_id))`. `lhs`
|
||||
// is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of
|
||||
// the right-hand-side (if any).
|
||||
ArgOverloadedOp(Datum<Expr>, Option<(Datum<Expr>, ast::NodeId)>),
|
||||
// the right-hand-side arguments (if any).
|
||||
ArgOverloadedOp(Datum<Expr>, Vec<(Datum<Expr>, ast::NodeId)>),
|
||||
|
||||
// Supply value of arguments as a list of expressions that must be
|
||||
// translated, for overloaded call operators.
|
||||
@ -1045,17 +1045,13 @@ pub fn trans_args<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
|
||||
DontAutorefArg)
|
||||
}));
|
||||
|
||||
match rhs {
|
||||
Some((rhs, rhs_id)) => {
|
||||
assert_eq!(arg_tys.len(), 2);
|
||||
|
||||
llargs.push(unpack_result!(bcx, {
|
||||
trans_arg_datum(bcx, *arg_tys.get(1), rhs,
|
||||
arg_cleanup_scope,
|
||||
DoAutorefArg(rhs_id))
|
||||
}));
|
||||
}
|
||||
None => assert_eq!(arg_tys.len(), 1)
|
||||
assert_eq!(arg_tys.len(), 1 + rhs.len());
|
||||
for (rhs, rhs_id) in rhs.move_iter() {
|
||||
llargs.push(unpack_result!(bcx, {
|
||||
trans_arg_datum(bcx, *arg_tys.get(1), rhs,
|
||||
arg_cleanup_scope,
|
||||
DoAutorefArg(rhs_id))
|
||||
}));
|
||||
}
|
||||
}
|
||||
ArgVals(vs) => {
|
||||
|
@ -3479,6 +3479,12 @@ fn populate_scope_map(cx: &CrateContext,
|
||||
walk_expr(cx, &**rhs, scope_stack, scope_map);
|
||||
}
|
||||
|
||||
ast::ExprSlice(ref base, ref start, ref end, _) => {
|
||||
walk_expr(cx, &**base, scope_stack, scope_map);
|
||||
start.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map));
|
||||
end.as_ref().map(|x| walk_expr(cx, &**x, scope_stack, scope_map));
|
||||
}
|
||||
|
||||
ast::ExprVec(ref init_expressions) |
|
||||
ast::ExprTup(ref init_expressions) => {
|
||||
for ie in init_expressions.iter() {
|
||||
|
@ -589,6 +589,34 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
ast::ExprIndex(ref base, ref idx) => {
|
||||
trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id))
|
||||
}
|
||||
ast::ExprSlice(ref base, ref start, ref end, _) => {
|
||||
let _icx = push_ctxt("trans_slice");
|
||||
let ccx = bcx.ccx();
|
||||
|
||||
let method_call = MethodCall::expr(expr.id);
|
||||
let method_ty = ccx.tcx()
|
||||
.method_map
|
||||
.borrow()
|
||||
.find(&method_call)
|
||||
.map(|method| method.ty);
|
||||
let base_datum = unpack_datum!(bcx, trans(bcx, &**base));
|
||||
|
||||
let mut args = vec![];
|
||||
start.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
|
||||
end.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
|
||||
|
||||
let result_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty.unwrap()));
|
||||
let scratch = rvalue_scratch_datum(bcx, result_ty, "trans_slice");
|
||||
|
||||
unpack_result!(bcx,
|
||||
trans_overloaded_op(bcx,
|
||||
expr,
|
||||
method_call,
|
||||
base_datum,
|
||||
args,
|
||||
Some(SaveIn(scratch.val))));
|
||||
DatumBlock::new(bcx, scratch.to_expr_datum())
|
||||
}
|
||||
ast::ExprBox(_, ref contents) => {
|
||||
// Special case for `Box<T>` and `Gc<T>`
|
||||
let box_ty = expr_ty(bcx, expr);
|
||||
@ -724,7 +752,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
index_expr,
|
||||
method_call,
|
||||
base_datum,
|
||||
Some((ix_datum, idx.id)),
|
||||
vec![(ix_datum, idx.id)],
|
||||
None));
|
||||
let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
|
||||
let elt_ty = match ty::deref(ref_ty, true) {
|
||||
@ -1043,20 +1071,20 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let lhs = unpack_datum!(bcx, trans(bcx, &**lhs));
|
||||
let rhs_datum = unpack_datum!(bcx, trans(bcx, &**rhs));
|
||||
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), lhs,
|
||||
Some((rhs_datum, rhs.id)), Some(dest)).bcx
|
||||
vec![(rhs_datum, rhs.id)], Some(dest)).bcx
|
||||
}
|
||||
ast::ExprUnary(_, ref subexpr) => {
|
||||
// if not overloaded, would be RvalueDatumExpr
|
||||
let arg = unpack_datum!(bcx, trans(bcx, &**subexpr));
|
||||
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id),
|
||||
arg, None, Some(dest)).bcx
|
||||
arg, Vec::new(), Some(dest)).bcx
|
||||
}
|
||||
ast::ExprIndex(ref base, ref idx) => {
|
||||
// if not overloaded, would be RvalueDatumExpr
|
||||
let base = unpack_datum!(bcx, trans(bcx, &**base));
|
||||
let idx_datum = unpack_datum!(bcx, trans(bcx, &**idx));
|
||||
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base,
|
||||
Some((idx_datum, idx.id)), Some(dest)).bcx
|
||||
vec![(idx_datum, idx.id)], Some(dest)).bcx
|
||||
}
|
||||
ast::ExprCast(ref val, _) => {
|
||||
// DPS output mode means this is a trait cast:
|
||||
@ -1740,7 +1768,7 @@ fn trans_overloaded_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
expr: &ast::Expr,
|
||||
method_call: MethodCall,
|
||||
lhs: Datum<Expr>,
|
||||
rhs: Option<(Datum<Expr>, ast::NodeId)>,
|
||||
rhs: Vec<(Datum<Expr>, ast::NodeId)>,
|
||||
dest: Option<Dest>)
|
||||
-> Result<'blk, 'tcx> {
|
||||
let method_ty = bcx.tcx().method_map.borrow().get(&method_call).ty;
|
||||
@ -2063,7 +2091,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_deref");
|
||||
|
||||
unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call,
|
||||
datum, None, Some(SaveIn(scratch.val))));
|
||||
datum, Vec::new(), Some(SaveIn(scratch.val))));
|
||||
scratch.to_expr_datum()
|
||||
}
|
||||
None => {
|
||||
|
@ -3646,6 +3646,9 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
||||
// the index method invoked for `a[i]` always yields an `&T`
|
||||
ast::ExprIndex(..) => LvalueExpr,
|
||||
|
||||
// the slice method invoked for `a[..]` always yields an `&T`
|
||||
ast::ExprSlice(..) => LvalueExpr,
|
||||
|
||||
// `for` loops are statements
|
||||
ast::ExprForLoop(..) => RvalueStmtExpr,
|
||||
|
||||
@ -3698,7 +3701,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
||||
ast::ExprUnary(ast::UnDeref, _) |
|
||||
ast::ExprField(..) |
|
||||
ast::ExprTupField(..) |
|
||||
ast::ExprIndex(..) => {
|
||||
ast::ExprIndex(..) |
|
||||
ast::ExprSlice(..) => {
|
||||
LvalueExpr
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ use middle::typeck::rscope::RegionScope;
|
||||
use middle::typeck::{lookup_def_ccx};
|
||||
use middle::typeck::no_params;
|
||||
use middle::typeck::{require_same_types};
|
||||
use middle::typeck::{MethodCall, MethodMap, ObjectCastMap};
|
||||
use middle::typeck::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
|
||||
use middle::typeck::{TypeAndSubsts};
|
||||
use middle::typeck;
|
||||
use middle::lang_items::TypeIdLangItem;
|
||||
@ -123,7 +123,6 @@ use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::mem::replace;
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use syntax::abi;
|
||||
use syntax::ast::{ProvidedMethod, RequiredMethod, TypeTraitItem};
|
||||
use syntax::ast;
|
||||
@ -2187,12 +2186,12 @@ pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
|
||||
}
|
||||
|
||||
/// Attempts to resolve a call expression as an overloaded call.
|
||||
fn try_overloaded_call(fcx: &FnCtxt,
|
||||
call_expression: &ast::Expr,
|
||||
callee: &ast::Expr,
|
||||
callee_type: ty::t,
|
||||
args: &[P<ast::Expr>])
|
||||
-> bool {
|
||||
fn try_overloaded_call<'a>(fcx: &FnCtxt,
|
||||
call_expression: &ast::Expr,
|
||||
callee: &ast::Expr,
|
||||
callee_type: ty::t,
|
||||
args: &[&'a P<ast::Expr>])
|
||||
-> bool {
|
||||
// Bail out if the callee is a bare function or a closure. We check those
|
||||
// manually.
|
||||
match *structure_of(fcx, callee.span, callee_type) {
|
||||
@ -2275,18 +2274,125 @@ fn try_overloaded_deref(fcx: &FnCtxt,
|
||||
(method, _) => method
|
||||
};
|
||||
|
||||
make_return_type(fcx, method_call, method)
|
||||
}
|
||||
|
||||
fn get_method_ty(method: &Option<MethodCallee>) -> ty::t {
|
||||
match method {
|
||||
&Some(ref method) => method.ty,
|
||||
&None => ty::mk_err()
|
||||
}
|
||||
}
|
||||
|
||||
fn make_return_type(fcx: &FnCtxt,
|
||||
method_call: Option<MethodCall>,
|
||||
method: Option<MethodCallee>)
|
||||
-> Option<ty::mt> {
|
||||
match method {
|
||||
Some(method) => {
|
||||
let ref_ty = ty::ty_fn_ret(method.ty);
|
||||
match method_call {
|
||||
Some(method_call) => {
|
||||
fcx.inh.method_map.borrow_mut().insert(method_call, method);
|
||||
fcx.inh.method_map.borrow_mut().insert(method_call,
|
||||
method);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
ty::deref(ref_ty, true)
|
||||
}
|
||||
None => None
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn try_overloaded_slice(fcx: &FnCtxt,
|
||||
method_call: Option<MethodCall>,
|
||||
expr: &ast::Expr,
|
||||
base_expr: &ast::Expr,
|
||||
base_ty: ty::t,
|
||||
start_expr: &Option<P<ast::Expr>>,
|
||||
end_expr: &Option<P<ast::Expr>>,
|
||||
mutbl: &ast::Mutability)
|
||||
-> Option<ty::mt> {
|
||||
let method = if mutbl == &ast::MutMutable {
|
||||
// Try `SliceMut` first, if preferred.
|
||||
match fcx.tcx().lang_items.slice_mut_trait() {
|
||||
Some(trait_did) => {
|
||||
let method_name = match (start_expr, end_expr) {
|
||||
(&Some(_), &Some(_)) => "slice_mut_",
|
||||
(&Some(_), &None) => "slice_from_mut_",
|
||||
(&None, &Some(_)) => "slice_to_mut_",
|
||||
(&None, &None) => "as_mut_slice_",
|
||||
};
|
||||
|
||||
method::lookup_in_trait(fcx,
|
||||
expr.span,
|
||||
Some(&*base_expr),
|
||||
token::intern(method_name),
|
||||
trait_did,
|
||||
base_ty,
|
||||
[],
|
||||
DontAutoderefReceiver,
|
||||
IgnoreStaticMethods)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
// Otherwise, fall back to `Slice`.
|
||||
// FIXME(#17293) this will not coerce base_expr, so we miss the Slice
|
||||
// trait for `&mut [T]`.
|
||||
match fcx.tcx().lang_items.slice_trait() {
|
||||
Some(trait_did) => {
|
||||
let method_name = match (start_expr, end_expr) {
|
||||
(&Some(_), &Some(_)) => "slice_",
|
||||
(&Some(_), &None) => "slice_from_",
|
||||
(&None, &Some(_)) => "slice_to_",
|
||||
(&None, &None) => "as_slice_",
|
||||
};
|
||||
|
||||
method::lookup_in_trait(fcx,
|
||||
expr.span,
|
||||
Some(&*base_expr),
|
||||
token::intern(method_name),
|
||||
trait_did,
|
||||
base_ty,
|
||||
[],
|
||||
DontAutoderefReceiver,
|
||||
IgnoreStaticMethods)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Regardless of whether the lookup succeeds, check the method arguments
|
||||
// so that we have *some* type for each argument.
|
||||
let method_type = get_method_ty(&method);
|
||||
|
||||
let mut args = vec![];
|
||||
start_expr.as_ref().map(|x| args.push(x));
|
||||
end_expr.as_ref().map(|x| args.push(x));
|
||||
|
||||
check_method_argument_types(fcx,
|
||||
expr.span,
|
||||
method_type,
|
||||
expr,
|
||||
args.as_slice(),
|
||||
DoDerefArgs,
|
||||
DontTupleArguments);
|
||||
|
||||
match method {
|
||||
Some(method) => {
|
||||
let result_ty = ty::ty_fn_ret(method.ty);
|
||||
match method_call {
|
||||
Some(method_call) => {
|
||||
fcx.inh.method_map.borrow_mut().insert(method_call,
|
||||
method);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
Some(ty::mt { ty: result_ty, mutbl: ast::MutImmutable })
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -2332,32 +2438,16 @@ fn try_overloaded_index(fcx: &FnCtxt,
|
||||
|
||||
// Regardless of whether the lookup succeeds, check the method arguments
|
||||
// so that we have *some* type for each argument.
|
||||
let method_type = match method {
|
||||
Some(ref method) => method.ty,
|
||||
None => ty::mk_err()
|
||||
};
|
||||
let method_type = get_method_ty(&method);
|
||||
check_method_argument_types(fcx,
|
||||
expr.span,
|
||||
method_type,
|
||||
expr,
|
||||
slice::ref_slice(index_expr),
|
||||
&[index_expr],
|
||||
DoDerefArgs,
|
||||
DontTupleArguments);
|
||||
|
||||
match method {
|
||||
Some(method) => {
|
||||
let ref_ty = ty::ty_fn_ret(method.ty);
|
||||
match method_call {
|
||||
Some(method_call) => {
|
||||
fcx.inh.method_map.borrow_mut().insert(method_call,
|
||||
method);
|
||||
}
|
||||
None => {}
|
||||
}
|
||||
ty::deref(ref_ty, true)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
make_return_type(fcx, method_call, method)
|
||||
}
|
||||
|
||||
/// Given the head of a `for` expression, looks up the `next` method in the
|
||||
@ -2441,14 +2531,14 @@ fn lookup_method_for_for_loop(fcx: &FnCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_method_argument_types(fcx: &FnCtxt,
|
||||
sp: Span,
|
||||
method_fn_ty: ty::t,
|
||||
callee_expr: &ast::Expr,
|
||||
args_no_rcvr: &[P<ast::Expr>],
|
||||
deref_args: DerefArgs,
|
||||
tuple_arguments: TupleArgumentsFlag)
|
||||
-> ty::t {
|
||||
fn check_method_argument_types<'a>(fcx: &FnCtxt,
|
||||
sp: Span,
|
||||
method_fn_ty: ty::t,
|
||||
callee_expr: &ast::Expr,
|
||||
args_no_rcvr: &[&'a P<ast::Expr>],
|
||||
deref_args: DerefArgs,
|
||||
tuple_arguments: TupleArgumentsFlag)
|
||||
-> ty::t {
|
||||
if ty::type_is_error(method_fn_ty) {
|
||||
let err_inputs = err_args(args_no_rcvr.len());
|
||||
check_argument_types(fcx,
|
||||
@ -2482,14 +2572,14 @@ fn check_method_argument_types(fcx: &FnCtxt,
|
||||
}
|
||||
}
|
||||
|
||||
fn check_argument_types(fcx: &FnCtxt,
|
||||
sp: Span,
|
||||
fn_inputs: &[ty::t],
|
||||
_callee_expr: &ast::Expr,
|
||||
args: &[P<ast::Expr>],
|
||||
deref_args: DerefArgs,
|
||||
variadic: bool,
|
||||
tuple_arguments: TupleArgumentsFlag) {
|
||||
fn check_argument_types<'a>(fcx: &FnCtxt,
|
||||
sp: Span,
|
||||
fn_inputs: &[ty::t],
|
||||
_callee_expr: &ast::Expr,
|
||||
args: &[&'a P<ast::Expr>],
|
||||
deref_args: DerefArgs,
|
||||
variadic: bool,
|
||||
tuple_arguments: TupleArgumentsFlag) {
|
||||
/*!
|
||||
*
|
||||
* Generic function that factors out common logic from
|
||||
@ -2626,7 +2716,7 @@ fn check_argument_types(fcx: &FnCtxt,
|
||||
DontDerefArgs => {}
|
||||
}
|
||||
|
||||
check_expr_coercable_to_type(fcx, &**arg, formal_ty);
|
||||
check_expr_coercable_to_type(fcx, &***arg, formal_ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2635,12 +2725,12 @@ fn check_argument_types(fcx: &FnCtxt,
|
||||
// arguments which we skipped above.
|
||||
if variadic {
|
||||
for arg in args.iter().skip(expected_arg_count) {
|
||||
check_expr(fcx, &**arg);
|
||||
check_expr(fcx, &***arg);
|
||||
|
||||
// There are a few types which get autopromoted when passed via varargs
|
||||
// in C but we just error out instead and require explicit casts.
|
||||
let arg_ty = structurally_resolved_type(fcx, arg.span,
|
||||
fcx.expr_ty(&**arg));
|
||||
fcx.expr_ty(&***arg));
|
||||
match ty::get(arg_ty).sty {
|
||||
ty::ty_float(ast::TyF32) => {
|
||||
fcx.type_error_message(arg.span,
|
||||
@ -2876,10 +2966,10 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
|
||||
|
||||
// A generic function for doing all of the checking for call expressions
|
||||
fn check_call(fcx: &FnCtxt,
|
||||
call_expr: &ast::Expr,
|
||||
f: &ast::Expr,
|
||||
args: &[P<ast::Expr>]) {
|
||||
fn check_call<'a>(fcx: &FnCtxt,
|
||||
call_expr: &ast::Expr,
|
||||
f: &ast::Expr,
|
||||
args: &[&'a P<ast::Expr>]) {
|
||||
// Store the type of `f` as the type of the callee
|
||||
let fn_ty = fcx.expr_ty(f);
|
||||
|
||||
@ -2989,11 +3079,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
};
|
||||
|
||||
// Call the generic checker.
|
||||
let args: Vec<_> = args.slice_from(1).iter().map(|x| x).collect();
|
||||
let ret_ty = check_method_argument_types(fcx,
|
||||
method_name.span,
|
||||
fn_ty,
|
||||
expr,
|
||||
args.slice_from(1),
|
||||
args.as_slice(),
|
||||
DontDerefArgs,
|
||||
DontTupleArguments);
|
||||
|
||||
@ -3084,12 +3175,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
None => None
|
||||
};
|
||||
let args = match rhs {
|
||||
Some(rhs) => slice::ref_slice(rhs),
|
||||
None => {
|
||||
// Work around the lack of coercion.
|
||||
let empty: &[_] = &[];
|
||||
empty
|
||||
}
|
||||
Some(rhs) => vec![rhs],
|
||||
None => vec![]
|
||||
};
|
||||
match method {
|
||||
Some(method) => {
|
||||
@ -3101,7 +3188,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
op_ex.span,
|
||||
method_ty,
|
||||
op_ex,
|
||||
args,
|
||||
args.as_slice(),
|
||||
DoDerefArgs,
|
||||
DontTupleArguments)
|
||||
}
|
||||
@ -3114,7 +3201,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
op_ex.span,
|
||||
expected_ty,
|
||||
op_ex,
|
||||
args,
|
||||
args.as_slice(),
|
||||
DoDerefArgs,
|
||||
DontTupleArguments);
|
||||
ty::mk_err()
|
||||
@ -4135,12 +4222,13 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
check_expr(fcx, &**f);
|
||||
let f_ty = fcx.expr_ty(&**f);
|
||||
|
||||
let args: Vec<_> = args.iter().map(|x| x).collect();
|
||||
if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
|
||||
check_call(fcx, expr, &**f, args.as_slice());
|
||||
let (args_bot, args_err) = args.iter().fold((false, false),
|
||||
|(rest_bot, rest_err), a| {
|
||||
// is this not working?
|
||||
let a_ty = fcx.expr_ty(&**a);
|
||||
let a_ty = fcx.expr_ty(&***a);
|
||||
(rest_bot || ty::type_is_bot(a_ty),
|
||||
rest_err || ty::type_is_error(a_ty))});
|
||||
if ty::type_is_error(f_ty) || args_err {
|
||||
@ -4426,6 +4514,61 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
}
|
||||
}
|
||||
}
|
||||
ast::ExprSlice(ref base, ref start, ref end, ref mutbl) => {
|
||||
check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
|
||||
let raw_base_t = fcx.expr_ty(&**base);
|
||||
|
||||
let mut some_err = false;
|
||||
if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
|
||||
fcx.write_ty(id, raw_base_t);
|
||||
some_err = true;
|
||||
}
|
||||
|
||||
{
|
||||
let check_slice_idx = |e: &ast::Expr| {
|
||||
check_expr(fcx, e);
|
||||
let e_t = fcx.expr_ty(e);
|
||||
if ty::type_is_error(e_t) || ty::type_is_bot(e_t) {
|
||||
fcx.write_ty(id, e_t);
|
||||
some_err = true;
|
||||
}
|
||||
};
|
||||
start.as_ref().map(|e| check_slice_idx(&**e));
|
||||
end.as_ref().map(|e| check_slice_idx(&**e));
|
||||
}
|
||||
|
||||
if !some_err {
|
||||
let base_t = structurally_resolved_type(fcx,
|
||||
expr.span,
|
||||
raw_base_t);
|
||||
let method_call = MethodCall::expr(expr.id);
|
||||
match try_overloaded_slice(fcx,
|
||||
Some(method_call),
|
||||
expr,
|
||||
&**base,
|
||||
base_t,
|
||||
start,
|
||||
end,
|
||||
mutbl) {
|
||||
Some(mt) => fcx.write_ty(id, mt.ty),
|
||||
None => {
|
||||
fcx.type_error_message(expr.span,
|
||||
|actual| {
|
||||
format!("cannot take a {}slice of a value with type `{}`",
|
||||
if mutbl == &ast::MutMutable {
|
||||
"mutable "
|
||||
} else {
|
||||
""
|
||||
},
|
||||
actual)
|
||||
},
|
||||
base_t,
|
||||
None);
|
||||
fcx.write_ty(id, ty::mk_err())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("type of expr({}) {} is...", expr.id,
|
||||
|
@ -245,6 +245,7 @@ mod svh_visitor {
|
||||
SawExprAssign,
|
||||
SawExprAssignOp(ast::BinOp),
|
||||
SawExprIndex,
|
||||
SawExprSlice,
|
||||
SawExprPath,
|
||||
SawExprAddrOf(ast::Mutability),
|
||||
SawExprRet,
|
||||
@ -279,6 +280,7 @@ mod svh_visitor {
|
||||
ExprField(_, id, _) => SawExprField(content(id.node)),
|
||||
ExprTupField(_, id, _) => SawExprTupField(id.node),
|
||||
ExprIndex(..) => SawExprIndex,
|
||||
ExprSlice(..) => SawExprSlice,
|
||||
ExprPath(..) => SawExprPath,
|
||||
ExprAddrOf(m, _) => SawExprAddrOf(m),
|
||||
ExprBreak(id) => SawExprBreak(id.map(content)),
|
||||
|
@ -538,6 +538,7 @@ pub enum Expr_ {
|
||||
ExprField(P<Expr>, SpannedIdent, Vec<P<Ty>>),
|
||||
ExprTupField(P<Expr>, Spanned<uint>, Vec<P<Ty>>),
|
||||
ExprIndex(P<Expr>, P<Expr>),
|
||||
ExprSlice(P<Expr>, Option<P<Expr>>, Option<P<Expr>>, Mutability),
|
||||
|
||||
/// Variable reference, possibly containing `::` and/or
|
||||
/// type parameters, e.g. foo::bar::<baz>
|
||||
|
@ -1252,6 +1252,12 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
|
||||
ExprIndex(el, er) => {
|
||||
ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
|
||||
}
|
||||
ExprSlice(e, e1, e2, m) => {
|
||||
ExprSlice(folder.fold_expr(e),
|
||||
e1.map(|x| folder.fold_expr(x)),
|
||||
e2.map(|x| folder.fold_expr(x)),
|
||||
m)
|
||||
}
|
||||
ExprPath(pth) => ExprPath(folder.fold_path(pth)),
|
||||
ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
|
||||
ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
|
||||
|
@ -23,7 +23,7 @@ use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, EnumDef, Explicit
|
||||
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
|
||||
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
|
||||
use ast::{ExprBreak, ExprCall, ExprCast};
|
||||
use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex};
|
||||
use ast::{ExprField, ExprTupField, ExprFnBlock, ExprIf, ExprIndex, ExprSlice};
|
||||
use ast::{ExprLit, ExprLoop, ExprMac};
|
||||
use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc};
|
||||
use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn};
|
||||
@ -1987,6 +1987,14 @@ impl<'a> Parser<'a> {
|
||||
ExprIndex(expr, idx)
|
||||
}
|
||||
|
||||
pub fn mk_slice(&mut self, expr: P<Expr>,
|
||||
start: Option<P<Expr>>,
|
||||
end: Option<P<Expr>>,
|
||||
mutbl: Mutability)
|
||||
-> ast::Expr_ {
|
||||
ExprSlice(expr, start, end, mutbl)
|
||||
}
|
||||
|
||||
pub fn mk_field(&mut self, expr: P<Expr>, ident: ast::SpannedIdent,
|
||||
tys: Vec<P<Ty>>) -> ast::Expr_ {
|
||||
ExprField(expr, ident, tys)
|
||||
@ -2401,13 +2409,87 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
// expr[...]
|
||||
// Could be either an index expression or a slicing expression.
|
||||
// Any slicing non-terminal can have a mutable version with `mut`
|
||||
// after the opening square bracket.
|
||||
token::LBRACKET => {
|
||||
self.bump();
|
||||
let ix = self.parse_expr();
|
||||
hi = self.span.hi;
|
||||
self.commit_expr_expecting(&*ix, token::RBRACKET);
|
||||
let index = self.mk_index(e, ix);
|
||||
e = self.mk_expr(lo, hi, index)
|
||||
let mutbl = if self.eat_keyword(keywords::Mut) {
|
||||
MutMutable
|
||||
} else {
|
||||
MutImmutable
|
||||
};
|
||||
match self.token {
|
||||
// e[]
|
||||
token::RBRACKET => {
|
||||
self.bump();
|
||||
hi = self.span.hi;
|
||||
let slice = self.mk_slice(e, None, None, mutbl);
|
||||
e = self.mk_expr(lo, hi, slice)
|
||||
}
|
||||
// e[..e]
|
||||
token::DOTDOT => {
|
||||
self.bump();
|
||||
match self.token {
|
||||
// e[..]
|
||||
token::RBRACKET => {
|
||||
self.bump();
|
||||
hi = self.span.hi;
|
||||
let slice = self.mk_slice(e, None, None, mutbl);
|
||||
e = self.mk_expr(lo, hi, slice);
|
||||
|
||||
self.span_err(e.span, "incorrect slicing expression: `[..]`");
|
||||
self.span_note(e.span,
|
||||
"use `expr[]` to construct a slice of the whole of expr");
|
||||
}
|
||||
// e[..e]
|
||||
_ => {
|
||||
hi = self.span.hi;
|
||||
let e2 = self.parse_expr();
|
||||
self.commit_expr_expecting(&*e2, token::RBRACKET);
|
||||
let slice = self.mk_slice(e, None, Some(e2), mutbl);
|
||||
e = self.mk_expr(lo, hi, slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
// e[e] | e[e..] | e[e..e]
|
||||
_ => {
|
||||
let ix = self.parse_expr();
|
||||
match self.token {
|
||||
// e[e..] | e[e..e]
|
||||
token::DOTDOT => {
|
||||
self.bump();
|
||||
let e2 = match self.token {
|
||||
// e[e..]
|
||||
token::RBRACKET => {
|
||||
self.bump();
|
||||
None
|
||||
}
|
||||
// e[e..e]
|
||||
_ => {
|
||||
let e2 = self.parse_expr();
|
||||
self.commit_expr_expecting(&*e2, token::RBRACKET);
|
||||
Some(e2)
|
||||
}
|
||||
};
|
||||
hi = self.span.hi;
|
||||
let slice = self.mk_slice(e, Some(ix), e2, mutbl);
|
||||
e = self.mk_expr(lo, hi, slice)
|
||||
}
|
||||
// e[e]
|
||||
_ => {
|
||||
if mutbl == ast::MutMutable {
|
||||
self.span_err(e.span,
|
||||
"`mut` keyword is invalid in index expressions");
|
||||
}
|
||||
hi = self.span.hi;
|
||||
self.commit_expr_expecting(&*ix, token::RBRACKET);
|
||||
let index = self.mk_index(e, ix);
|
||||
e = self.mk_expr(lo, hi, index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => return e
|
||||
@ -3154,7 +3236,8 @@ impl<'a> Parser<'a> {
|
||||
// These expressions are limited to literals (possibly
|
||||
// preceded by unary-minus) or identifiers.
|
||||
let val = self.parse_literal_maybe_minus();
|
||||
if self.token == token::DOTDOT &&
|
||||
// FIXME(#17295) remove the DOTDOT option.
|
||||
if (self.token == token::DOTDOTDOT || self.token == token::DOTDOT) &&
|
||||
self.look_ahead(1, |t| {
|
||||
*t != token::COMMA && *t != token::RBRACKET
|
||||
}) {
|
||||
@ -3199,12 +3282,16 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
});
|
||||
|
||||
if self.look_ahead(1, |t| *t == token::DOTDOT) &&
|
||||
// FIXME(#17295) remove the DOTDOT option.
|
||||
if self.look_ahead(1, |t| *t == token::DOTDOTDOT || *t == token::DOTDOT) &&
|
||||
self.look_ahead(2, |t| {
|
||||
*t != token::COMMA && *t != token::RBRACKET
|
||||
}) {
|
||||
let start = self.parse_expr_res(RestrictionNoBarOp);
|
||||
self.eat(&token::DOTDOT);
|
||||
// FIXME(#17295) remove the DOTDOT option (self.eat(&token::DOTDOTDOT)).
|
||||
if self.token == token::DOTDOTDOT || self.token == token::DOTDOT {
|
||||
self.bump();
|
||||
}
|
||||
let end = self.parse_expr_res(RestrictionNoBarOp);
|
||||
pat = PatRange(start, end);
|
||||
} else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
|
||||
|
@ -1651,6 +1651,28 @@ impl<'a> State<'a> {
|
||||
try!(self.print_expr(&**index));
|
||||
try!(word(&mut self.s, "]"));
|
||||
}
|
||||
ast::ExprSlice(ref e, ref start, ref end, ref mutbl) => {
|
||||
try!(self.print_expr(&**e));
|
||||
try!(word(&mut self.s, "["));
|
||||
if mutbl == &ast::MutMutable {
|
||||
try!(word(&mut self.s, "mut"));
|
||||
if start.is_some() || end.is_some() {
|
||||
try!(space(&mut self.s));
|
||||
}
|
||||
}
|
||||
match start {
|
||||
&Some(ref e) => try!(self.print_expr(&**e)),
|
||||
_ => {}
|
||||
}
|
||||
if start.is_some() || end.is_some() {
|
||||
try!(word(&mut self.s, ".."));
|
||||
}
|
||||
match end {
|
||||
&Some(ref e) => try!(self.print_expr(&**e)),
|
||||
_ => {}
|
||||
}
|
||||
try!(word(&mut self.s, "]"));
|
||||
}
|
||||
ast::ExprPath(ref path) => try!(self.print_path(path, true)),
|
||||
ast::ExprBreak(opt_ident) => {
|
||||
try!(word(&mut self.s, "break"));
|
||||
@ -1944,7 +1966,7 @@ impl<'a> State<'a> {
|
||||
ast::PatRange(ref begin, ref end) => {
|
||||
try!(self.print_expr(&**begin));
|
||||
try!(space(&mut self.s));
|
||||
try!(word(&mut self.s, ".."));
|
||||
try!(word(&mut self.s, "..."));
|
||||
try!(self.print_expr(&**end));
|
||||
}
|
||||
ast::PatVec(ref before, ref slice, ref after) => {
|
||||
|
@ -785,6 +785,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
visitor.visit_expr(&**main_expression);
|
||||
visitor.visit_expr(&**index_expression)
|
||||
}
|
||||
ExprSlice(ref main_expression, ref start, ref end, _) => {
|
||||
visitor.visit_expr(&**main_expression);
|
||||
walk_expr_opt(visitor, start);
|
||||
walk_expr_opt(visitor, end)
|
||||
}
|
||||
ExprPath(ref path) => {
|
||||
visitor.visit_path(path, expression.id)
|
||||
}
|
||||
|
19
src/test/compile-fail/slice-1.rs
Normal file
19
src/test/compile-fail/slice-1.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test slicing expr[..] is an error and gives a helpful error message.
|
||||
|
||||
struct Foo;
|
||||
|
||||
fn main() {
|
||||
let x = Foo;
|
||||
x[..]; //~ ERROR incorrect slicing expression: `[..]`
|
||||
//~^ NOTE use `expr[]` to construct a slice of the whole of expr
|
||||
}
|
25
src/test/compile-fail/slice-2.rs
Normal file
25
src/test/compile-fail/slice-2.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test that slicing syntax gives errors if we have not implemented the trait.
|
||||
|
||||
struct Foo;
|
||||
|
||||
fn main() {
|
||||
let x = Foo;
|
||||
x[]; //~ ERROR cannot take a slice of a value with type `Foo`
|
||||
x[Foo..]; //~ ERROR cannot take a slice of a value with type `Foo`
|
||||
x[..Foo]; //~ ERROR cannot take a slice of a value with type `Foo`
|
||||
x[Foo..Foo]; //~ ERROR cannot take a slice of a value with type `Foo`
|
||||
x[mut]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
|
||||
x[mut Foo..]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
|
||||
x[mut ..Foo]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
|
||||
x[mut Foo..Foo]; //~ ERROR cannot take a mutable slice of a value with type `Foo`
|
||||
}
|
19
src/test/compile-fail/slice-borrow.rs
Normal file
19
src/test/compile-fail/slice-borrow.rs
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test slicing expressions doesn't defeat the borrow checker.
|
||||
|
||||
fn main() {
|
||||
let y;
|
||||
{
|
||||
let x: &[int] = &[1, 2, 3, 4, 5]; //~ ERROR borrowed value does not live long enough
|
||||
y = x[1..];
|
||||
}
|
||||
}
|
17
src/test/compile-fail/slice-mut-2.rs
Normal file
17
src/test/compile-fail/slice-mut-2.rs
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test mutability and slicing syntax.
|
||||
|
||||
fn main() {
|
||||
let x: &[int] = &[1, 2, 3, 4, 5];
|
||||
// Can't mutably slice an immutable slice
|
||||
let y = x[mut 2..4]; //~ ERROR cannot take a mutable slice of a value with type `&[int]`
|
||||
}
|
22
src/test/compile-fail/slice-mut.rs
Normal file
22
src/test/compile-fail/slice-mut.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test mutability and slicing syntax.
|
||||
|
||||
fn main() {
|
||||
let x: &[int] = &[1, 2, 3, 4, 5];
|
||||
// Immutable slices are not mutable.
|
||||
let y: &mut[_] = x[2..4]; //~ ERROR cannot borrow immutable dereference of `&`-pointer as mutabl
|
||||
|
||||
let x: &mut [int] = &mut [1, 2, 3, 4, 5];
|
||||
// Can't borrow mutably twice
|
||||
let y = x[mut 1..2];
|
||||
let y = x[mut 4..5]; //~ERROR cannot borrow
|
||||
}
|
@ -13,7 +13,7 @@ static e: int = 42;
|
||||
|
||||
pub fn main() {
|
||||
match 7 {
|
||||
s..e => (),
|
||||
s...e => (),
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
69
src/test/run-pass/slice-2.rs
Normal file
69
src/test/run-pass/slice-2.rs
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test slicing expressions on slices and Vecs.
|
||||
|
||||
fn main() {
|
||||
let x: &[int] = &[1, 2, 3, 4, 5];
|
||||
let cmp: &[int] = &[1, 2, 3, 4, 5];
|
||||
assert!(x[] == cmp)
|
||||
let cmp: &[int] = &[3, 4, 5];
|
||||
assert!(x[2..] == cmp)
|
||||
let cmp: &[int] = &[1, 2, 3];
|
||||
assert!(x[..3] == cmp)
|
||||
let cmp: &[int] = &[2, 3, 4];
|
||||
assert!(x[1..4] == cmp)
|
||||
|
||||
let x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
let cmp: &[int] = &[1, 2, 3, 4, 5];
|
||||
assert!(x[] == cmp)
|
||||
let cmp: &[int] = &[3, 4, 5];
|
||||
assert!(x[2..] == cmp)
|
||||
let cmp: &[int] = &[1, 2, 3];
|
||||
assert!(x[..3] == cmp)
|
||||
let cmp: &[int] = &[2, 3, 4];
|
||||
assert!(x[1..4] == cmp)
|
||||
|
||||
let x: &mut [int] = &mut [1, 2, 3, 4, 5];
|
||||
{
|
||||
let cmp: &mut [int] = &mut [1, 2, 3, 4, 5];
|
||||
assert!(x[mut] == cmp)
|
||||
}
|
||||
{
|
||||
let cmp: &mut [int] = &mut [3, 4, 5];
|
||||
assert!(x[mut 2..] == cmp)
|
||||
}
|
||||
{
|
||||
let cmp: &mut [int] = &mut [1, 2, 3];
|
||||
assert!(x[mut ..3] == cmp)
|
||||
}
|
||||
{
|
||||
let cmp: &mut [int] = &mut [2, 3, 4];
|
||||
assert!(x[mut 1..4] == cmp)
|
||||
}
|
||||
|
||||
let mut x: Vec<int> = vec![1, 2, 3, 4, 5];
|
||||
{
|
||||
let cmp: &mut [int] = &mut [1, 2, 3, 4, 5];
|
||||
assert!(x[mut] == cmp)
|
||||
}
|
||||
{
|
||||
let cmp: &mut [int] = &mut [3, 4, 5];
|
||||
assert!(x[mut 2..] == cmp)
|
||||
}
|
||||
{
|
||||
let cmp: &mut [int] = &mut [1, 2, 3];
|
||||
assert!(x[mut ..3] == cmp)
|
||||
}
|
||||
{
|
||||
let cmp: &mut [int] = &mut [2, 3, 4];
|
||||
assert!(x[mut 1..4] == cmp)
|
||||
}
|
||||
}
|
31
src/test/run-pass/slice-fail-1.rs
Normal file
31
src/test/run-pass/slice-fail-1.rs
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test that is a slicing expr[..] fails, the correct cleanups happen.
|
||||
|
||||
use std::task;
|
||||
|
||||
struct Foo;
|
||||
|
||||
static mut DTOR_COUNT: int = 0;
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } }
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let x: &[_] = &[Foo, Foo];
|
||||
x[3..4];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = task::try(proc() foo());
|
||||
unsafe { assert!(DTOR_COUNT == 2); }
|
||||
}
|
35
src/test/run-pass/slice-fail-2.rs
Normal file
35
src/test/run-pass/slice-fail-2.rs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test that is a slicing expr[..] fails, the correct cleanups happen.
|
||||
|
||||
use std::task;
|
||||
|
||||
struct Foo;
|
||||
|
||||
static mut DTOR_COUNT: int = 0;
|
||||
|
||||
impl Drop for Foo {
|
||||
fn drop(&mut self) { unsafe { DTOR_COUNT += 1; } }
|
||||
}
|
||||
|
||||
fn bar() -> uint {
|
||||
fail!();
|
||||
}
|
||||
|
||||
fn foo() {
|
||||
let x: &[_] = &[Foo, Foo];
|
||||
x[3..bar()];
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _ = task::try(proc() foo());
|
||||
unsafe { assert!(DTOR_COUNT == 2); }
|
||||
}
|
70
src/test/run-pass/slice.rs
Normal file
70
src/test/run-pass/slice.rs
Normal file
@ -0,0 +1,70 @@
|
||||
// Copyright 2014 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.
|
||||
|
||||
// Test slicing sugar.
|
||||
|
||||
extern crate core;
|
||||
use core::ops::{Slice,SliceMut};
|
||||
|
||||
static mut COUNT: uint = 0;
|
||||
|
||||
struct Foo;
|
||||
|
||||
impl Slice<Foo, Foo> for Foo {
|
||||
fn as_slice_<'a>(&'a self) -> &'a Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
fn slice_from_<'a>(&'a self, _from: &Foo) -> &'a Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
fn slice_to_<'a>(&'a self, _to: &Foo) -> &'a Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
fn slice_<'a>(&'a self, _from: &Foo, _to: &Foo) -> &'a Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl SliceMut<Foo, Foo> for Foo {
|
||||
fn as_mut_slice_<'a>(&'a mut self) -> &'a mut Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
fn slice_from_mut_<'a>(&'a mut self, _from: &Foo) -> &'a mut Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
fn slice_to_mut_<'a>(&'a mut self, _to: &Foo) -> &'a mut Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
fn slice_mut_<'a>(&'a mut self, _from: &Foo, _to: &Foo) -> &'a mut Foo {
|
||||
unsafe { COUNT += 1; }
|
||||
self
|
||||
}
|
||||
}
|
||||
fn main() {
|
||||
let mut x = Foo;
|
||||
x[];
|
||||
x[Foo..];
|
||||
x[..Foo];
|
||||
x[Foo..Foo];
|
||||
x[mut];
|
||||
x[mut Foo..];
|
||||
x[mut ..Foo];
|
||||
x[mut Foo..Foo];
|
||||
unsafe {
|
||||
assert!(COUNT == 8);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user