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

Non-uint array indexing #18878

Closed
Yamakaky opened this issue Nov 11, 2014 · 13 comments
Closed

Non-uint array indexing #18878

Yamakaky opened this issue Nov 11, 2014 · 13 comments

Comments

@Yamakaky
Copy link
Contributor

Hi

Currently, rust doesn't seem to accept non uint types as index for an array. As an example, this code doesn't compile :

let array = [1, 2, 3, 4];
let index: u16 = 1;
let item = array[index];

I have to do

let item = array[index as uint];

Couldn't rustc automate this conversion ?

@Grieverheart
Copy link

I was also asking around irc about this, but got no answers. Here is the current implementation for [T],

impl<T> ops::Index<uint, T> for [T] {
    fn index(&self, &index: &uint) -> &T {
    assert!(index < self.len());
    unsafe { mem::transmute(self.repr().data.offset(index as int)) }
}
}

Notice that the index is actually being converted to int! It would be nice if we instead had something like,

impl<K: Unsigned, T> ops::Index<K, T> for [T] {
    fn index(&self, &index: &K) -> &T {
    assert!(index < self.len());
    unsafe { mem::transmute(self.repr().data.offset(index as int)) }
}
}

@lifthrasiir
Copy link
Contributor

See #10453 and #13257. It is intentional as far as I know (do not implicitly coerce between primitive types).

@Yamakaky
Copy link
Contributor Author

@Grieverheart : yes, that would be cool.
@lifthrasiir : I understand the point for signed numbers, but u16 (in my example) are smaller than uint, so I don't see what problem it could do.

@gamazeps
Copy link
Contributor

@Yamakaky it might be done in order to avoid overflows

@Yamakaky
Copy link
Contributor Author

Here, it is not a problem as u16 < uint.

@gamazeps
Copy link
Contributor

yes, u16 would overflow before uint does.

But why would you need u16 as indexes ? As the sole point of int and uint are for size/indexes and pointers.

@Grieverheart
Copy link

@gamazeps The primary issue, at least for me, is that is is annoying to explicitly cast each index. If you're programming e.g. an emulator, the code ends up being too terse. The same basically applies to other operations such as std::ops::Shl too.

@mahkoh
Copy link
Contributor

mahkoh commented Nov 12, 2014

            self.freqs[FREQ[(CLASS[buf[0] as uint] << 3 | CLASS[buf[1] as uint]) as uint] as uint] += 1;
            self.freqs[FREQ[(CLASS[buf[1] as uint] << 3 | CLASS[buf[2] as uint]) as uint] as uint] += 1;
            self.freqs[FREQ[(CLASS[buf[2] as uint] << 3 | CLASS[buf[3] as uint]) as uint] as uint] += 1;
            self.freqs[FREQ[(CLASS[buf[3] as uint] << 3 | CLASS[buf[4] as uint]) as uint] as uint] += 1;
            self.freqs[FREQ[(CLASS[buf[4] as uint] << 3 | CLASS[buf[5] as uint]) as uint] as uint] += 1;
            self.freqs[FREQ[(CLASS[buf[5] as uint] << 3 | CLASS[buf[6] as uint]) as uint] as uint] += 1;
            self.freqs[FREQ[(CLASS[buf[6] as uint] << 3 | CLASS[buf[7] as uint]) as uint] as uint] += 1;

Sounds like a good idea.

@ftxqxd
Copy link
Contributor

ftxqxd commented Nov 12, 2014

The real issue here is that integral coercions that never overflow should be implicit. That’s rust-lang/rfcs#225, so I think all discussion should be moved there (or at least to the rfcs repo) because this is discussing a language feature, not a bug, and all language feature requests belong as issues or pull requests in the rfcs repo.

@Yamakaky
Copy link
Contributor Author

@gamazeps I'm working on an emulator, with a [u16, 0x10000] memory array, and I would like to do something like memory[memory[x]]; to dereference a pointer.

@P1start ok

@nodakai
Copy link
Contributor

nodakai commented Nov 13, 2014

@Yamakaky Can you use a custom struct with operator overloading for now?

use std::ops::Index;

struct Mem {
    mem: [u16, .. 0x10000]
}

impl Mem {
    fn new() -> Mem {
        Mem { mem: [0, .. 0x10000] }
    }
}

impl Index<u16, u16> for Mem {
    fn index<'a> (&'a self, index: &u16) -> &'a u16 {
        &self.mem[*index as uint]
    }
}

fn main() {
    let mem = Mem::new();
    println!("{}", mem[mem[0]]);
}

@Yamakaky
Copy link
Contributor Author

That's not perfect, but it will play it role, thanks !

@steveklabnik
Copy link
Member

Yes, closing in favor of the RFC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants