[SOLVED] Problem with generics


#1

Hi everyone,

could anyone tell me what i did wrong?

fn  print_all<T: std::fmt::Display>(buf: &[T]) {
    for elem in buf {
        println!("{}",elem);
    }
}

fn change_item<T>(pos: usize, buf: &mut [T], new: T) -> Result<(), &'static str> {
    if pos >= buf.len() {
        return Err("invalid index");
    }

    buf[pos] = new;
    Ok(())
}

fn change_items<T>(buf: &mut [T]) -> Result<(), &'static str> {
    change_item::<T>(0, buf, "Value 1");
    change_item::<T>(1, buf, "Value 2");
    change_item::<T>(4, buf, "Value 3");
    change_item::<T>(6, buf, "Value 4");
    Ok(())
}

fn main() {
    let mut buf = ["..."; 20];

    match change_items::<&'static str>(&mut buf[..]) {
        Ok(_) => (),
        Err(ref msg) => println!("{}", msg),
    };

    print_all(&buf[..])
}

I get these errors

Compiling learnrust v0.1.0 (file:///home/daniel/Projects/learnrust)
error[E0308]: mismatched types
–> src/main.rs:17:30
|
17 | change_item::(0, buf, “Value 1”);
| ^^^^^^^^^ expected type parameter, found reference
|
= note: expected type T
= note: found type &'static str

error[E0308]: mismatched types
–> src/main.rs:18:30
|
18 | change_item::(1, buf, “Value 2”);
| ^^^^^^^^^ expected type parameter, found reference
|
= note: expected type T
= note: found type &'static str

error[E0308]: mismatched types
–> src/main.rs:19:30
|
19 | change_item::(4, buf, “Value 3”);
| ^^^^^^^^^ expected type parameter, found reference
|
= note: expected type T
= note: found type &'static str

error[E0308]: mismatched types
–> src/main.rs:20:30
|
20 | change_item::(6, buf, “Value 4”);
| ^^^^^^^^^ expected type parameter, found reference
|
= note: expected type T
= note: found type &'static str

error: aborting due to 4 previous errors

error: Could not compile learnrust.

To learn more, run the command again with --verbose.

Process finished with exit code 101

Thanks for taking the time to read this.


#3

Your change_item function expect that buf is a slice of elements with same type that the new argument.

But in your change_items function, you call change_item with buf still being a &mut [T] while new is now a &str. buf can be anything here, especially not a &mut [&str].

A solution would be to accept a new argument that is Into<T>:

fn change_item<T, U: Into<T>>(pos: usize, buf: &mut [T], new: U) -> Result<(), &'static str> {
    if pos >= buf.len() {
        return Err("invalid index");
    }

    buf[pos] = new.into();
    Ok(())
}

fn change_items<'a, T: From<&'a str>>(buf: &mut [T]) -> Result<(), &'static str> {
    change_item(0, buf, "Value 1")?;
    change_item(1, buf, "Value 2")?;
    change_item(4, buf, "Value 3")?;
    change_item(6, buf, "Value 4")?;
    Ok(())
}

I appended the ? operator in the change_items to propagate errors generated by the change_item, as you return a Result here as well.


#4

Great, now it works. Thank you very much.