Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The type `&[u8]` cannot be indexed by `usize`?

Tags:

rust

The following is the test code:

pub fn reverse_complement_seq_u8<T>(seq: T, len: usize) -> Vec<u8> 
    where T: std::ops::Index<usize, Output = u8>
{
    (0..len).rev().map(|i| match seq[i] {
            65 | 97  => 84, // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99  => 71, // 'C' | 'c' => 'G'
            n => n,
        } 
    ).collect()
}


fn main() {
    let seqs = "ACGATGCTACGA".as_bytes();//generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}

Because call seqs.to_owend() is expensive, so I just want to pass its reference to reverse_complement_seq_u8, however this cause the following errors:

error[E0277]: the type `&[u8]` cannot be indexed by `usize`
  --> src/main.rs:17:48
   |
17 |     let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
   |                      ------------------------- ^^^^ `&[u8]` cannot be indexed by `usize`
   |                      |
   |                      required by a bound introduced by this call
   |
   = help: the trait `Index<usize>` is not implemented for `&[u8]`
   = help: the following other types implement trait `Index<Idx>`:
             [T; N]
             [T]
note: required by a bound in `reverse_complement_seq_u8`
like image 906
Moold Avatar asked Mar 13 '26 09:03

Moold


1 Answers

The problem is that while the slice itself [u8] can be indexed, a reference to the slice &[u8] can't. Most of the time indexing a slice reference works because Rust automatically dereferences as needed, but when using generics you need to be more strict in what you tell the compiler.

One possible fix is to use seq: &T in the arguments so that T will be [u8] which can be indexed. This requires an extra + ?Sized bound, otherwise the compiler adds an implicit Sized bound which slices don't implement:

pub fn reverse_complement_seq_u8<T>(seq: &T, len: usize) -> Vec<u8>
where
    T: std::ops::Index<usize, Output = u8> + ?Sized,
{
    (0..len)
        .rev()
        .map(|i| match seq[i] {
            65 | 97 => 84,  // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99 => 71,  // 'C' | 'c' => 'G'
            n => n,
        })
        .collect()
}

fn main() {
    let seqs = "ACGATGCTACGA".as_bytes(); //generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}

Playground

Another option that will also work with boxed slices is to specify that T must deref to some indexable type:

use std::ops::Deref;
pub fn reverse_complement_seq_u8<T, U>(seq: T, len: usize) -> Vec<u8>
where
    T: Deref<Target = U>,
    U: std::ops::Index<usize, Output = u8> + ?Sized,
{
    (0..len)
        .rev()
        .map(|i| match seq[i] {
            65 | 97 => 84,  // 'A' | 'a' => 'T'
            84 | 116 => 65, // 'T' | 't' => 'A'
            71 | 103 => 67, // 'G' | 'g' => 'C'
            67 | 99 => 71,  // 'C' | 'c' => 'G'
            n => n,
        })
        .collect()
}

fn main() {
    let seqs = "ACGATGCTACGA".as_bytes(); //generated by another function
    let revcom_seq = reverse_complement_seq_u8(seqs, seqs.len());
    println!("{:?}", revcom_seq);
}

Playground

like image 83
Jmb Avatar answered Mar 15 '26 00:03

Jmb