From e157fa326ffb34a53e6a0e7a05438b8713dee344 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sun, 24 Jan 2016 22:08:56 -0500 Subject: [PATCH 1/6] move RangeArgument to ops --- src/libcollections/lib.rs | 2 +- src/libcollections/range.rs | 60 ------------------------------ src/libcollections/string.rs | 3 +- src/libcollections/vec.rs | 4 +- src/libcollections/vec_deque.rs | 4 +- src/libcore/ops.rs | 65 ++++++++++++++++++++++++++++++++- 6 files changed, 68 insertions(+), 70 deletions(-) delete mode 100644 src/libcollections/range.rs diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index 6077a4c01045b..f50f68030c86c 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -32,6 +32,7 @@ #![feature(alloc)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(collections_range)] #![feature(core_intrinsics)] #![feature(decode_utf16)] #![feature(drop_in_place)] @@ -89,7 +90,6 @@ pub mod borrow; pub mod enum_set; pub mod fmt; pub mod linked_list; -pub mod range; pub mod slice; pub mod str; pub mod string; diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs deleted file mode 100644 index afcd779ddf19f..0000000000000 --- a/src/libcollections/range.rs +++ /dev/null @@ -1,60 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![unstable(feature = "collections_range", - reason = "waiting for dust to settle on inclusive ranges", - issue = "30877")] - -//! Range syntax. - -use core::option::Option::{self, None, Some}; -use core::ops::{RangeFull, Range, RangeTo, RangeFrom}; - -/// **RangeArgument** is implemented by Rust's built-in range types, produced -/// by range syntax like `..`, `a..`, `..b` or `c..d`. -pub trait RangeArgument { - /// Start index (inclusive) - /// - /// Return start value if present, else `None`. - fn start(&self) -> Option<&T> { - None - } - - /// End index (exclusive) - /// - /// Return end value if present, else `None`. - fn end(&self) -> Option<&T> { - None - } -} - - -impl RangeArgument for RangeFull {} - -impl RangeArgument for RangeFrom { - fn start(&self) -> Option<&T> { - Some(&self.start) - } -} - -impl RangeArgument for RangeTo { - fn end(&self) -> Option<&T> { - Some(&self.end) - } -} - -impl RangeArgument for Range { - fn start(&self) -> Option<&T> { - Some(&self.start) - } - fn end(&self) -> Option<&T> { - Some(&self.end) - } -} diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index d9cbc4488fca7..b8d338ac0efe7 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -59,7 +59,7 @@ use core::fmt; use core::hash; use core::iter::FromIterator; use core::mem; -use core::ops::{self, Add}; +use core::ops::{self, Add, RangeArgument}; use core::ptr; use core::slice; use core::str::pattern::Pattern; @@ -68,7 +68,6 @@ use rustc_unicode::str as unicode_str; #[allow(deprecated)] use borrow::{Cow, IntoCow}; -use range::RangeArgument; use str::{self, FromStr, Utf8Error, Chars}; use vec::Vec; use boxed::Box; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index a49b7304643cc..453f5aaf0cdf7 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -68,7 +68,7 @@ use core::hash::{self, Hash}; use core::intrinsics::{arith_offset, assume, needs_drop}; use core::iter::FromIterator; use core::mem; -use core::ops::{Index, IndexMut}; +use core::ops::{Index, IndexMut, RangeArgument}; use core::ops; use core::ptr; use core::slice; @@ -76,8 +76,6 @@ use core::slice; #[allow(deprecated)] use borrow::{Cow, IntoCow}; -use super::range::RangeArgument; - /// A growable list type, written `Vec` but pronounced 'vector.' /// /// # Examples diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 394f7a975989a..845259f23a8b6 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -22,7 +22,7 @@ use core::cmp::Ordering; use core::fmt; use core::iter::{repeat, FromIterator}; use core::mem; -use core::ops::{Index, IndexMut}; +use core::ops::{Index, IndexMut, RangeArgument}; use core::ptr; use core::slice; @@ -31,8 +31,6 @@ use core::cmp; use alloc::raw_vec::RawVec; -use super::range::RangeArgument; - const INITIAL_CAPACITY: usize = 7; // 2^3 - 1 const MINIMUM_CAPACITY: usize = 1; // 2 - 1 #[cfg(target_pointer_width = "32")] diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index d1c5b175bb034..9f56547a2313a 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -67,8 +67,10 @@ #![stable(feature = "rust1", since = "1.0.0")] -use marker::{Sized, Unsize}; use fmt; +use marker::{Sized, Unsize}; +use option::Option; +use option::Option::{Some, None}; /// The `Drop` trait is used to run some code when a value goes out of scope. /// This is sometimes called a 'destructor'. @@ -1885,3 +1887,64 @@ pub trait BoxPlace : Place { /// Creates a globally fresh place. fn make_place() -> Self; } + + + + +/// **RangeArgument** is implemented by Rust's built-in range types, produced +/// by range syntax like `..`, `a..`, `..b` or `c..d`. +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +pub trait RangeArgument { + /// Start index (inclusive) + /// + /// Return start value if present, else `None`. + fn start(&self) -> Option<&T> { + None + } + + /// End index (exclusive) + /// + /// Return end value if present, else `None`. + fn end(&self) -> Option<&T> { + None + } +} + + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for RangeFull {} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for RangeFrom { + fn start(&self) -> Option<&T> { + Some(&self.start) + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for RangeTo { + fn end(&self) -> Option<&T> { + Some(&self.end) + } +} + +#[unstable(feature = "collections_range", + reason = "waiting for dust to settle on inclusive ranges", + issue = "30877")] +impl RangeArgument for Range { + fn start(&self) -> Option<&T> { + Some(&self.start) + } + fn end(&self) -> Option<&T> { + Some(&self.end) + } +} + From ae907df06121b62677912f409ae245e9107a1a6e Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 25 Jan 2016 15:40:43 -0500 Subject: [PATCH 2/6] make RangeArgument #[fundamental] This is necessary so that crates outside of libcore (e.g. libcollections) are allowed to write both `impl Index for _` and `impl> Index for _` without getting overlap errors (essentially, to assume that `usize: !RangeArgument`). --- src/libcore/ops.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 9f56547a2313a..d7ef07971d326 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1896,6 +1896,7 @@ pub trait BoxPlace : Place { #[unstable(feature = "collections_range", reason = "waiting for dust to settle on inclusive ranges", issue = "30877")] +#[fundamental] pub trait RangeArgument { /// Start index (inclusive) /// From 8c41c3ead87f117d02f8fb58be6135b7315bc465 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 25 Jan 2016 15:40:55 -0500 Subject: [PATCH 3/6] use RangeArgument for indexing --- src/libcollections/string.rs | 60 ++--------------- src/libcollections/vec.rs | 56 ++-------------- src/libcore/slice.rs | 90 +++++++------------------ src/libcore/str/mod.rs | 123 +++++----------------------------- src/libstd/lib.rs | 1 + src/libstd/sys/common/wtf8.rs | 65 +++--------------- 6 files changed, 61 insertions(+), 334 deletions(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index b8d338ac0efe7..4aa5bbaf29616 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1569,68 +1569,20 @@ impl<'a> Add<&'a str> for String { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { +impl> ops::Index for String { type Output = str; #[inline] - fn index(&self, index: ops::Range) -> &str { - &self[..][index] - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeTo) -> &str { - &self[..][index] - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for String { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeFrom) -> &str { - &self[..][index] - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for String { - type Output = str; - - #[inline] - fn index(&self, _index: ops::RangeFull) -> &str { - unsafe { str::from_utf8_unchecked(&self.vec) } + fn index(&self, index: R) -> &str { + &(**self)[index] } } #[stable(feature = "derefmut_for_string", since = "1.2.0")] -impl ops::IndexMut> for String { - #[inline] - fn index_mut(&mut self, index: ops::Range) -> &mut str { - &mut self[..][index] - } -} -#[stable(feature = "derefmut_for_string", since = "1.2.0")] -impl ops::IndexMut> for String { - #[inline] - fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { - &mut self[..][index] - } -} -#[stable(feature = "derefmut_for_string", since = "1.2.0")] -impl ops::IndexMut> for String { - #[inline] - fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { - &mut self[..][index] - } -} -#[stable(feature = "derefmut_for_string", since = "1.2.0")] -impl ops::IndexMut for String { +impl> ops::IndexMut for String { #[inline] - fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str { - unsafe { mem::transmute(&mut *self.vec) } + fn index_mut(&mut self, index: R) -> &mut str { + &mut (**self)[index] } } diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 453f5aaf0cdf7..e60cb1012f142 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1144,70 +1144,22 @@ impl IndexMut for Vec { #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for Vec { +impl> ops::Index for Vec { type Output = [T]; #[inline] - fn index(&self, index: ops::Range) -> &[T] { + fn index(&self, index: R) -> &[T] { Index::index(&**self, index) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::RangeTo) -> &[T] { - Index::index(&**self, index) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for Vec { - type Output = [T]; - - #[inline] - fn index(&self, index: ops::RangeFrom) -> &[T] { - Index::index(&**self, index) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for Vec { - type Output = [T]; - - #[inline] - fn index(&self, _index: ops::RangeFull) -> &[T] { - self - } -} #[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::Range) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut> for Vec { - #[inline] - fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { - IndexMut::index_mut(&mut **self, index) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut> for Vec { +impl> ops::IndexMut for Vec { #[inline] - fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { + fn index_mut(&mut self, index: R) -> &mut [T] { IndexMut::index_mut(&mut **self, index) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for Vec { - #[inline] - fn index_mut(&mut self, _index: ops::RangeFull) -> &mut [T] { - self - } -} #[stable(feature = "rust1", since = "1.0.0")] impl ops::Deref for Vec { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 40041c748e7ff..b06d9d0210dc3 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -40,8 +40,7 @@ use cmp; use default::Default; use intrinsics::assume; use iter::*; -use ops::{FnMut, self, Index}; -use ops::RangeFull; +use ops::{FnMut, self}; use option::Option; use option::Option::{None, Some}; use result::Result; @@ -522,91 +521,48 @@ fn slice_index_order_fail(index: usize, end: usize) -> ! { } #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for [T] { +impl> ops::Index for [T] { type Output = [T]; #[inline] - fn index(&self, index: ops::Range) -> &[T] { - if index.start > index.end { - slice_index_order_fail(index.start, index.end); - } else if index.end > self.len() { - slice_index_len_fail(index.end, self.len()); + fn index(&self, index: R) -> &[T] { + let len = self.len(); + let start = *index.start().unwrap_or(&0); + let end = *index.end().unwrap_or(&len); + if start > end { + slice_index_order_fail(start, end); + } else if end > len { + slice_index_len_fail(end, len); } unsafe { from_raw_parts ( - self.as_ptr().offset(index.start as isize), - index.end - index.start + self.as_ptr().offset(start as isize), + end - start ) } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for [T] { - type Output = [T]; - #[inline] - fn index(&self, index: ops::RangeTo) -> &[T] { - self.index(ops::Range{ start: 0, end: index.end }) - } -} #[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index> for [T] { - type Output = [T]; - +impl> ops::IndexMut for [T] { #[inline] - fn index(&self, index: ops::RangeFrom) -> &[T] { - self.index(ops::Range{ start: index.start, end: self.len() }) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::Index for [T] { - type Output = [T]; - - #[inline] - fn index(&self, _index: RangeFull) -> &[T] { - self - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut> for [T] { - #[inline] - fn index_mut(&mut self, index: ops::Range) -> &mut [T] { - if index.start > index.end { - slice_index_order_fail(index.start, index.end); - } else if index.end > self.len() { - slice_index_len_fail(index.end, self.len()); + fn index_mut(&mut self, index: R) -> &mut [T] { + let len = self.len(); + let start = *index.start().unwrap_or(&0); + let end = *index.end().unwrap_or(&len); + if start > end { + slice_index_order_fail(start, end); + } else if end > len { + slice_index_len_fail(end, len); } unsafe { from_raw_parts_mut( - self.as_mut_ptr().offset(index.start as isize), - index.end - index.start + self.as_mut_ptr().offset(start as isize), + end - start ) } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut> for [T] { - #[inline] - fn index_mut(&mut self, index: ops::RangeTo) -> &mut [T] { - self.index_mut(ops::Range{ start: 0, end: index.end }) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut> for [T] { - #[inline] - fn index_mut(&mut self, index: ops::RangeFrom) -> &mut [T] { - let len = self.len(); - self.index_mut(ops::Range{ start: index.start, end: len }) - } -} -#[stable(feature = "rust1", since = "1.0.0")] -impl ops::IndexMut for [T] { - #[inline] - fn index_mut(&mut self, _index: RangeFull) -> &mut [T] { - self - } -} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 3892455395f76..0451f3fd0b7a3 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1340,17 +1340,19 @@ mod traits { /// // &s[3 .. 100]; /// ``` #[stable(feature = "rust1", since = "1.0.0")] - impl ops::Index> for str { + impl> ops::Index for str { type Output = str; #[inline] - fn index(&self, index: ops::Range) -> &str { + fn index(&self, index: R) -> &str { + let start = *index.start().unwrap_or(&0); + let end = *index.end().unwrap_or(&self.len()); // is_char_boundary checks that the index is in [0, .len()] - if index.start <= index.end && - self.is_char_boundary(index.start) && - self.is_char_boundary(index.end) { - unsafe { self.slice_unchecked(index.start, index.end) } + if start <= end && + self.is_char_boundary(start) && + self.is_char_boundary(end) { + unsafe { self.slice_unchecked(start, end) } } else { - super::slice_error_fail(self, index.start, index.end) + super::slice_error_fail(self, start, end) } } } @@ -1358,110 +1360,21 @@ mod traits { /// Returns a mutable slice of the given string from the byte range /// [`begin`..`end`). #[stable(feature = "derefmut_for_string", since = "1.2.0")] - impl ops::IndexMut> for str { + impl> ops::IndexMut for str { #[inline] - fn index_mut(&mut self, index: ops::Range) -> &mut str { + fn index_mut(&mut self, index: R) -> &mut str { + let start = *index.start().unwrap_or(&0); + let end = *index.end().unwrap_or(&self.len()); // is_char_boundary checks that the index is in [0, .len()] - if index.start <= index.end && - self.is_char_boundary(index.start) && - self.is_char_boundary(index.end) { - unsafe { self.slice_mut_unchecked(index.start, index.end) } + if start <= end && + self.is_char_boundary(start) && + self.is_char_boundary(end) { + unsafe { self.slice_mut_unchecked(start, end) } } else { - super::slice_error_fail(self, index.start, index.end) + super::slice_error_fail(self, start, end) } } } - - /// Returns a slice of the string from the beginning to byte - /// `end`. - /// - /// Equivalent to `self[0 .. end]`. - /// - /// Panics when `end` does not point to a valid character, or is - /// out of bounds. - #[stable(feature = "rust1", since = "1.0.0")] - impl ops::Index> for str { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeTo) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } - } - } - - /// Returns a mutable slice of the string from the beginning to byte - /// `end`. - #[stable(feature = "derefmut_for_string", since = "1.2.0")] - impl ops::IndexMut> for str { - #[inline] - fn index_mut(&mut self, index: ops::RangeTo) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.end) { - unsafe { self.slice_mut_unchecked(0, index.end) } - } else { - super::slice_error_fail(self, 0, index.end) - } - } - } - - /// Returns a slice of the string from `begin` to its end. - /// - /// Equivalent to `self[begin .. self.len()]`. - /// - /// Panics when `begin` does not point to a valid character, or is - /// out of bounds. - #[stable(feature = "rust1", since = "1.0.0")] - impl ops::Index> for str { - type Output = str; - - #[inline] - fn index(&self, index: ops::RangeFrom) -> &str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - unsafe { self.slice_unchecked(index.start, self.len()) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } - } - } - - /// Returns a slice of the string from `begin` to its end. - #[stable(feature = "derefmut_for_string", since = "1.2.0")] - impl ops::IndexMut> for str { - #[inline] - fn index_mut(&mut self, index: ops::RangeFrom) -> &mut str { - // is_char_boundary checks that the index is in [0, .len()] - if self.is_char_boundary(index.start) { - let len = self.len(); - unsafe { self.slice_mut_unchecked(index.start, len) } - } else { - super::slice_error_fail(self, index.start, self.len()) - } - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl ops::Index for str { - type Output = str; - - #[inline] - fn index(&self, _index: ops::RangeFull) -> &str { - self - } - } - - #[stable(feature = "derefmut_for_string", since = "1.2.0")] - impl ops::IndexMut for str { - #[inline] - fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str { - self - } - } } /// Methods for string slices diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9adea351e3d0e..b8c9df690c667 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -221,6 +221,7 @@ #![feature(char_internals)] #![feature(collections)] #![feature(collections_bound)] +#![feature(collections_range)] #![feature(const_fn)] #![feature(core_float)] #![feature(core_intrinsics)] diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index bc997af3a27e4..d674f9926d313 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -585,71 +585,24 @@ impl Wtf8 { /// /// Panics when `begin` and `end` do not point to code point boundaries, /// or point beyond the end of the string. -impl ops::Index> for Wtf8 { +impl> ops::Index for Wtf8 { type Output = Wtf8; #[inline] - fn index(&self, range: ops::Range) -> &Wtf8 { + fn index(&self, index: R) -> &Wtf8 { + let start = *index.start().unwrap_or(&0); + let end = *index.end().unwrap_or(&self.len()); // is_code_point_boundary checks that the index is in [0, .len()] - if range.start <= range.end && - is_code_point_boundary(self, range.start) && - is_code_point_boundary(self, range.end) { - unsafe { slice_unchecked(self, range.start, range.end) } + if start <= end && + is_code_point_boundary(self, start) && + is_code_point_boundary(self, end) { + unsafe { slice_unchecked(self, start, end) } } else { - slice_error_fail(self, range.start, range.end) + slice_error_fail(self, start, end) } } } -/// Return a slice of the given string from byte `begin` to its end. -/// -/// # Panics -/// -/// Panics when `begin` is not at a code point boundary, -/// or is beyond the end of the string. -impl ops::Index> for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, range: ops::RangeFrom) -> &Wtf8 { - // is_code_point_boundary checks that the index is in [0, .len()] - if is_code_point_boundary(self, range.start) { - unsafe { slice_unchecked(self, range.start, self.len()) } - } else { - slice_error_fail(self, range.start, self.len()) - } - } -} - -/// Return a slice of the given string from its beginning to byte `end`. -/// -/// # Panics -/// -/// Panics when `end` is not at a code point boundary, -/// or is beyond the end of the string. -impl ops::Index> for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, range: ops::RangeTo) -> &Wtf8 { - // is_code_point_boundary checks that the index is in [0, .len()] - if is_code_point_boundary(self, range.end) { - unsafe { slice_unchecked(self, 0, range.end) } - } else { - slice_error_fail(self, 0, range.end) - } - } -} - -impl ops::Index for Wtf8 { - type Output = Wtf8; - - #[inline] - fn index(&self, _range: ops::RangeFull) -> &Wtf8 { - self - } -} - #[inline] fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 { // The first byte is assumed to be 0xED From 3cfb58705da4bbc95db99c40fcc0819fcaa9f33a Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Mon, 25 Jan 2016 15:56:29 -0500 Subject: [PATCH 4/6] test RangeArgument indexing --- src/test/run-pass/crazy-indexing.rs | 64 +++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 src/test/run-pass/crazy-indexing.rs diff --git a/src/test/run-pass/crazy-indexing.rs b/src/test/run-pass/crazy-indexing.rs new file mode 100644 index 0000000000000..365c07b656cc1 --- /dev/null +++ b/src/test/run-pass/crazy-indexing.rs @@ -0,0 +1,64 @@ +// Copyright 201&6 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(collections_range)] + +use std::ops::RangeArgument; + +struct Idx<'a>(Option<&'a usize>, Option<&'a usize>); + +impl<'a> RangeArgument for Idx<'a> { + fn start(&self) -> Option<&usize> { + self.0 + } + + fn end(&self) -> Option<&usize> { + self.1 + } +} + +#[cfg(not(windows))] +fn windows() {} + +#[cfg(windows)] +fn windows() { + use std::sys::common::wtf8::Wtf8Buf; + + let wtf = Wtf8Buf::from_str("hello world"); + + assert_eq!(&wtf[Idx(Some(&3), Some(&6))], &wtf[3..6]); + assert_eq!(&wtf[Idx(None , None )], &wtf[..]); + assert_eq!(&wtf[Idx(Some(&3), None )], &wtf[3..]); + assert_eq!(&wtf[Idx(None , Some(&6))], &wtf[..6]); +} + +fn main() { + let slice: &[_] = &*(0..10).collect::>(); + let string = String::from("hello world"); + let stir: &str = &*string; + + assert_eq!(&slice[Idx(Some(&3), Some(&6))], &slice[3..6]); + assert_eq!(&slice[Idx(None , None )], &slice[..]); + assert_eq!(&slice[Idx(Some(&3), None )], &slice[3..]); + assert_eq!(&slice[Idx(None , Some(&6))], &slice[..6]); + + assert_eq!(&string[Idx(Some(&3), Some(&6))], &string[3..6]); + assert_eq!(&string[Idx(None , None )], &string[..]); + assert_eq!(&string[Idx(Some(&3), None )], &string[3..]); + assert_eq!(&string[Idx(None , Some(&6))], &string[..6]); + + assert_eq!(&stir[Idx(Some(&3), Some(&6))], &stir[3..6]); + assert_eq!(&stir[Idx(None , None )], &stir[..]); + assert_eq!(&stir[Idx(Some(&3), None )], &stir[3..]); + assert_eq!(&stir[Idx(None , Some(&6))], &stir[..6]); + + windows(); +} + From cb72f3e1c1883507086ad59409d4fd74c5f6c54c Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 26 Jan 2016 01:18:56 -0500 Subject: [PATCH 5/6] fix test failures --- .../compile-fail/indexing-requires-a-uint.rs | 2 +- src/test/compile-fail/integral-indexing.rs | 16 ++++++++-------- src/test/compile-fail/str-idx.rs | 3 ++- src/test/compile-fail/str-mut-idx.rs | 4 ++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs index 3d3b7bc1bcb43..c1927279adf7e 100644 --- a/src/test/compile-fail/indexing-requires-a-uint.rs +++ b/src/test/compile-fail/indexing-requires-a-uint.rs @@ -13,7 +13,7 @@ fn main() { fn bar(_: T) {} - [0][0u8]; //~ ERROR: the trait `core::ops::Index` is not implemented + [0][0u8]; //~ ERROR: the trait `core::ops::RangeArgument` is not implemented for the type `u8` [0][0]; // should infer to be a usize diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index f78d677679bc8..51cb307c02246 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -13,14 +13,14 @@ pub fn main() { let s: String = "abcdef".to_string(); v[3_usize]; v[3]; - v[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - v[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - v[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - v[3i32]; //~ERROR the trait `core::ops::Index` is not implemented + v[3u8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u8` + v[3i8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i8` + v[3u32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u32` + v[3i32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i32` s.as_bytes()[3_usize]; s.as_bytes()[3]; - s.as_bytes()[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - s.as_bytes()[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - s.as_bytes()[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - s.as_bytes()[3i32]; //~ERROR the trait `core::ops::Index` is not implemented + s.as_bytes()[3u8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u8` + s.as_bytes()[3i8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i8` + s.as_bytes()[3u32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u32` + s.as_bytes()[3i32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i32` } diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs index 6e48ae20d09f3..0646abbac5d6b 100644 --- a/src/test/compile-fail/str-idx.rs +++ b/src/test/compile-fail/str-idx.rs @@ -10,5 +10,6 @@ pub fn main() { let s: &str = "hello"; - let c: u8 = s[4]; //~ ERROR the trait `core::ops::Index<_>` is not implemented + let c: u8 = s[4]; //~ ERROR the trait `core::ops::RangeArgument` is not implemented for the type `_` + //~| ERROR mismatched types } diff --git a/src/test/compile-fail/str-mut-idx.rs b/src/test/compile-fail/str-mut-idx.rs index ec6a14778a463..06a429047513a 100644 --- a/src/test/compile-fail/str-mut-idx.rs +++ b/src/test/compile-fail/str-mut-idx.rs @@ -15,8 +15,8 @@ fn mutate(s: &mut str) { //~^ ERROR `core::marker::Sized` is not implemented for the type `str` //~| ERROR `core::marker::Sized` is not implemented for the type `str` s[1usize] = bot(); - //~^ ERROR `core::ops::Index` is not implemented for the type `str` - //~| ERROR `core::ops::IndexMut` is not implemented for the type `str` + //~^ ERROR `core::ops::RangeArgument` is not implemented for the type `usize` + //~| ERROR `core::marker::Sized` is not implemented for the type `str` } pub fn main() {} From d5d920e0e4eebf3efced7c98509e9c3592469420 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Tue, 26 Jan 2016 02:20:56 -0500 Subject: [PATCH 6/6] fix tidy failures --- .../compile-fail/indexing-requires-a-uint.rs | 2 +- src/test/compile-fail/integral-indexing.rs | 16 ++++++++-------- src/test/compile-fail/str-idx.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs index c1927279adf7e..cb37f892c372e 100644 --- a/src/test/compile-fail/indexing-requires-a-uint.rs +++ b/src/test/compile-fail/indexing-requires-a-uint.rs @@ -13,7 +13,7 @@ fn main() { fn bar(_: T) {} - [0][0u8]; //~ ERROR: the trait `core::ops::RangeArgument` is not implemented for the type `u8` + [0][0u8]; //~ ERROR: `core::ops::RangeArgument` is not implemented for the type `u8` [0][0]; // should infer to be a usize diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index 51cb307c02246..de55c9824bd7f 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -13,14 +13,14 @@ pub fn main() { let s: String = "abcdef".to_string(); v[3_usize]; v[3]; - v[3u8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u8` - v[3i8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i8` - v[3u32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u32` - v[3i32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i32` + v[3u8]; //~ERROR `core::ops::RangeArgument` is not implemented for the type `u8` + v[3i8]; //~ERROR `core::ops::RangeArgument` is not implemented for the type `i8` + v[3u32]; //~ERROR `core::ops::RangeArgument` is not implemented for the type `u32` + v[3i32]; //~ERROR `core::ops::RangeArgument` is not implemented for the type `i32` s.as_bytes()[3_usize]; s.as_bytes()[3]; - s.as_bytes()[3u8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u8` - s.as_bytes()[3i8]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i8` - s.as_bytes()[3u32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `u32` - s.as_bytes()[3i32]; //~ERROR the trait `core::ops::RangeArgument` is not implemented for the type `i32` + s.as_bytes()[3u8]; //~ERROR RangeArgument` is not implemented for the type `u8` + s.as_bytes()[3i8]; //~ERROR RangeArgument` is not implemented for the type `i8` + s.as_bytes()[3u32]; //~ERROR RangeArgument` is not implemented for the type `u32` + s.as_bytes()[3i32]; //~ERROR RangeArgument` is not implemented for the type `i32` } diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs index 0646abbac5d6b..2aaaafad1353c 100644 --- a/src/test/compile-fail/str-idx.rs +++ b/src/test/compile-fail/str-idx.rs @@ -10,6 +10,6 @@ pub fn main() { let s: &str = "hello"; - let c: u8 = s[4]; //~ ERROR the trait `core::ops::RangeArgument` is not implemented for the type `_` + let c: u8 = s[4]; //~ ERROR ops::RangeArgument` is not implemented for the type `_` //~| ERROR mismatched types }