Value type unknown with boxed slice?


#1

I’m trying to test out a simple couple functions which convert line endings in ASCII data from/to LF/CR. Despite what I’m trying my best to figure out, rustc gives me errors that leave me scratching my head.

const LF: u8 = 10;
const CR: u8 = 13;

fn lf_to_cr(s: &[u8]) -> Box<[u8]>
{
	let mut outbytes = Box::from(s);
	for i in 0..outbytes.len() { if outbytes[i] == LF { outbytes[i] = CR; } }
	outbytes
}

fn cr_to_lf(s: &[u8]) -> Box<[u8]>
{
	let mut outbytes = Box::from(s);
	for i in 0..outbytes.len() { if outbytes[i] == CR { outbytes[i] = LF; } }
	outbytes
}

The two errors I get seem odd, because len() should tell Rust the returned value is usize. However:

rustc 1.19.0-beta.2 (a175ee509 2017-06-15)
error: the type of this value must be known in this context
  |
7 | for i in 0..outbytes.len() { if outbytes[i] == LF { outbytes[i] = CR; } }
  |                      ^^^
error: the type of this value must be known in this context
   |
14 | for i in 0..outbytes.len() { if outbytes[i] == CR { outbytes[i] = LF; } }
   |                      ^^^

I did initially deref and parenthesize my array as (*outbytes)[i] but I got the above error with CR and LF instead.


#2

Looks like type inference is “short circuited” there and the compiler doesn’t know the exact type of the Box. If you put explicit type annotations or use the turbofish operator, it works:

let outbytes: Box<[u8]> = ...
let outbytes = Box::<[u8]>::from(...);

#3

Independent of the inference, your loop should be

for ch in outbytes.iter_mut() {
    if *ch == CR { *ch = LF; }
}

#4

I was under the impression iterators were immutable. At least, C++11, C#, and Nim would complain, but thanks. I guess I learned something new.


#5

Iterators usually require traversal state, so they are not stateless and usually not immutable. But this is something else: it’s about making the iterator provide mutable references to the items, which allows you to modify the elements during traversal. This is also possible in C++, expect that this one doesn’t track the borrow of the iterating collection. :slight_smile: