Skip to content

Commit

Permalink
librustc (RFC #34): Implement the new Index and IndexMut traits.
Browse files Browse the repository at this point in the history
This will break code that used the old `Index` trait. Change this code
to use the new `Index` traits. For reference, here are their signatures:

    pub trait Index<Index,Result> {
        fn index<'a>(&'a self, index: &Index) -> &'a Result;
    }
    pub trait IndexMut<Index,Result> {
        fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
    }

Closes #6515.

[breaking-change]
  • Loading branch information
pcwalton committed Jul 7, 2014
1 parent 4f120e6 commit 7e4e991
Show file tree
Hide file tree
Showing 18 changed files with 433 additions and 167 deletions.
2 changes: 1 addition & 1 deletion src/etc/vim/syntax/rust.vim
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ syn keyword rustTrait Copy Send Sized Share
syn keyword rustTrait Add Sub Mul Div Rem Neg Not
syn keyword rustTrait BitAnd BitOr BitXor
syn keyword rustTrait Drop Deref DerefMut
syn keyword rustTrait Shl Shr Index
syn keyword rustTrait Shl Shr Index IndexMut
syn keyword rustEnum Option
syn keyword rustEnumVariant Some None
syn keyword rustEnum Result
Expand Down
64 changes: 49 additions & 15 deletions src/libcollections/bitv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,36 @@ use core::cmp;
use core::default::Default;
use core::fmt;
use core::iter::Take;
use core::ops;
use core::slice;
use core::uint;
use std::hash;

use {Collection, Mutable, Set, MutableSet};
use vec::Vec;

#[cfg(not(stage0))]
use core::ops::Index;

#[cfg(not(stage0))]
static TRUE: bool = true;

#[cfg(not(stage0))]
static FALSE: bool = false;

#[deriving(Clone)]
struct SmallBitv {
/// only the lowest nbits of this value are used. the rest is undefined.
bits: uint
}

#[deriving(Clone)]
struct BigBitv {
storage: Vec<uint>
}

#[deriving(Clone)]
enum BitvVariant { Big(BigBitv), Small(SmallBitv) }

/// The bitvector type
///
/// # Example
Expand Down Expand Up @@ -58,6 +80,18 @@ pub struct Bitv {
nbits: uint
}

#[cfg(not(stage0))]
impl Index<uint,bool> for Bitv {
#[inline]
fn index<'a>(&'a self, i: &uint) -> &'a bool {
if self.get(*i) {
&TRUE
} else {
&FALSE
}
}
}

struct MaskWords<'a> {
iter: slice::Items<'a, uint>,
next_word: Option<&'a uint>,
Expand Down Expand Up @@ -268,7 +302,7 @@ impl Bitv {
if offset >= bitv.nbits {
0
} else {
bitv[offset] as u8 << (7 - bit)
bitv.get(offset) as u8 << (7 - bit)
}
}

Expand All @@ -286,6 +320,13 @@ impl Bitv {
)
}

/**
* Transform `self` into a `Vec<bool>` by turning each bit into a `bool`.
*/
pub fn to_bools(&self) -> Vec<bool> {
Vec::from_fn(self.nbits, |i| self.get(i))
}

/**
* Compare a bitvector to a vector of `bool`.
*
Expand Down Expand Up @@ -504,13 +545,6 @@ impl Clone for Bitv {
}
}

impl ops::Index<uint,bool> for Bitv {
#[inline]
fn index(&self, i: &uint) -> bool {
self.get(*i)
}
}

impl fmt::Show for Bitv {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
for bit in self.iter() {
Expand Down Expand Up @@ -1369,9 +1403,9 @@ mod tests {
b2.set(1, true);
b2.set(2, true);
assert!(b1.difference(&b2));
assert!(b1[0]);
assert!(!b1[1]);
assert!(!b1[2]);
assert!(b1.get(0));
assert!(!b1.get(1));
assert!(!b1.get(2));
}

#[test]
Expand All @@ -1383,9 +1417,9 @@ mod tests {
b2.set(40, true);
b2.set(80, true);
assert!(b1.difference(&b2));
assert!(b1[0]);
assert!(!b1[40]);
assert!(!b1[80]);
assert!(b1.get(0));
assert!(!b1.get(40));
assert!(!b1.get(80));
}

#[test]
Expand Down
41 changes: 37 additions & 4 deletions src/libcore/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
/**
*
* The `Index` trait is used to specify the functionality of indexing operations
* like `arr[idx]`.
* like `arr[idx]` when used in an immutable context.
*
* # Example
*
Expand All @@ -624,9 +624,9 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
* struct Foo;
*
* impl Index<Foo, Foo> for Foo {
* fn index(&self, _rhs: &Foo) -> Foo {
* fn index<'a>(&'a self, _rhs: &Foo) -> &'a Foo {
* println!("Indexing!");
* *self
* self
* }
* }
*
Expand All @@ -636,9 +636,42 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
* ```
*/
#[lang="index"]
#[cfg(not(stage0))]
pub trait Index<Index,Result> {
/// The method for the indexing (`Foo[Bar]`) operation
fn index(&self, index: &Index) -> Result;
fn index<'a>(&'a self, index: &Index) -> &'a Result;
}

/**
*
* The `IndexMut` trait is used to specify the functionality of indexing
* operations like `arr[idx]`, when used in a mutable context.
*
* # Example
*
* A trivial implementation of `IndexMut`. When `Foo[Foo]` happens, it ends up
* calling `index`, and therefore, `main` prints `Indexing!`.
*
* ```
* struct Foo;
*
* impl IndexMut<Foo, Foo> for Foo {
* fn index_mut<'a>(&'a mut self, _rhs: &Foo) -> &'a mut Foo {
* println!("Indexing!");
* self
* }
* }
*
* fn main() {
* &mut Foo[Foo];
* }
* ```
*/
#[lang="index_mut"]
#[cfg(not(stage0))]
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;
}

/**
Expand Down
4 changes: 3 additions & 1 deletion src/libcore/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ pub use kinds::{Copy, Send, Sized, Share};
pub use ops::{Add, Sub, Mul, Div, Rem, Neg, Not};
pub use ops::{BitAnd, BitOr, BitXor};
pub use ops::{Drop, Deref, DerefMut};
pub use ops::{Shl, Shr, Index};
pub use ops::{Shl, Shr};
#[cfg(not(stage0))]
pub use ops::{Index, IndexMut};
pub use option::{Option, Some, None};
pub use result::{Result, Ok, Err};

Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ lets_do_this! {
ShlTraitLangItem, "shl", shl_trait;
ShrTraitLangItem, "shr", shr_trait;
IndexTraitLangItem, "index", index_trait;
IndexMutTraitLangItem, "index_mut", index_mut_trait;

UnsafeTypeLangItem, "unsafe", unsafe_type;

Expand Down
34 changes: 21 additions & 13 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,6 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
}

ast::ExprIndex(ref base, _) => {
if self.typer.is_method_call(expr.id) {
return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
}

let base_cmt = if_ok!(self.cat_expr(&**base));
Ok(self.cat_index(expr, base_cmt, 0))
}
Expand Down Expand Up @@ -759,7 +755,7 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {

pub fn cat_index<N:ast_node>(&self,
elt: &N,
base_cmt: cmt,
mut base_cmt: cmt,
derefs: uint)
-> cmt {
//! Creates a cmt for an indexing operation (`[]`); this
Expand Down Expand Up @@ -793,14 +789,26 @@ impl<'t,TYPER:Typer> MemCategorizationContext<'t,TYPER> {
//! - `derefs`: the deref number to be used for
//! the implicit index deref, if any (see above)

let element_ty = match ty::array_element_ty(base_cmt.ty) {
Some(ref mt) => mt.ty,
None => {
self.tcx().sess.span_bug(
elt.span(),
format!("Explicit index of non-index type `{}`",
base_cmt.ty.repr(self.tcx())).as_slice());
}
let method_call = typeck::MethodCall::expr(elt.id());
let method_ty = self.typer.node_method_ty(method_call);

let element_ty = match method_ty {
Some(method_ty) => {
let ref_ty = ty::ty_fn_ret(method_ty);
base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
*ty::ty_fn_args(method_ty).get(0)
}
None => {
match ty::array_element_ty(base_cmt.ty) {
Some(ref mt) => mt.ty,
None => {
self.tcx().sess.span_bug(
elt.span(),
format!("Explicit index of non-index type `{}`",
base_cmt.ty.repr(self.tcx())).as_slice());
}
}
}
};

return match deref_kind(self.tcx(), base_cmt.ty) {
Expand Down
Loading

5 comments on commit 7e4e991

@bors
Copy link
Contributor

@bors bors commented on 7e4e991 Jul 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from nick29581
at pcwalton@7e4e991

@bors
Copy link
Contributor

@bors bors commented on 7e4e991 Jul 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging pcwalton/rust/new-index-traits = 7e4e991 into auto

@bors
Copy link
Contributor

@bors bors commented on 7e4e991 Jul 7, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pcwalton/rust/new-index-traits = 7e4e991 merged ok, testing candidate = 00cdd63

@bors
Copy link
Contributor

@bors bors commented on 7e4e991 Jul 8, 2014

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 00cdd63

Please sign in to comment.