Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

librustc (RFC #34): Implement the new Index and IndexMut traits. #15394

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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};
Copy link
Member

Choose a reason for hiding this comment

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

I'd have thought you need a #[cfg(stage0)] here (instead of removing), but I guess if the tests are OK, then you don't.

#[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