Skip to content

Commit

Permalink
librustc (RFC rust-lang#34): Implement the new Index and IndexMut
Browse files Browse the repository at this point in the history
… traits.

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 rust-lang#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

1 comment on commit 7e4e991

@nrc
Copy link

@nrc nrc 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.

r+

Please sign in to comment.