Skip to content

Commit

Permalink
auto merge of #15394 : pcwalton/rust/new-index-traits, r=nick29581
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]

r? @nick29581
  • Loading branch information
bors committed Jul 7, 2014
2 parents c175ed4 + 7e4e991 commit 00cdd63
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

0 comments on commit 00cdd63

Please sign in to comment.