0

I couldn't understand anything wrong with the following function.

fn percuss<'a>(a: &'a mut str, b: &str, val: usize) -> &'a mut str {
    a.to_string().insert_str(val, b)
}

However, I get the following error:

error[E0308]: mismatched types
 --> src/lib.rs:2:5
  |
2 |     a.to_string().insert_str(val, b)
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&mut str`, found `()`

I do not or I am failing to see any reason for a.to_string().insert_str(val, b) to return a (). Could someone shed some light what I am missing to notice/understand?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Bussller
  • 1,961
  • 6
  • 36
  • 50
  • 1
    See also [What does “mismatched types: expected `()`” mean when using an if expression?](https://stackoverflow.com/q/24579756/155423); [Reason of the error expected (), found struct `std::vec::Vec` in Rust?](https://stackoverflow.com/q/60772160/155423); [Why does removing return give me an error: expected type `()` but found type](https://stackoverflow.com/q/24502282/155423) – Shepmaster Jun 24 '20 at 16:49
  • *I am failing to see any reason for `a.to_string().insert_str(val, b)` to return a `()`* — What did you believe it returned? – Shepmaster Jun 24 '20 at 16:50

1 Answers1

5

The signature of String::insert_str is

pub fn insert_str(&mut self, idx: usize, string: &str)

which means that it returns () (a function without an explicit return type returns () in Rust). Indeed, it mutates the string passed to it rather than creating a new one.

You should fix this as

fn percuss<'a>(a: &'a mut str, b: &str, val: usize) -> &'a mut str {
    let mut a = a.to_string();
    a.insert_str(val, b);
    &mut a
}

which now causes another error:

error[E0515]: cannot return reference to local variable `a`
 --> src/lib.rs:4:5
  |
4 |     &mut a
  |     ^^^^^^ returns a reference to data owned by the current function

indeed, insert_str requires a String rather than a &str as it will likely need to reallocate it. This means you need to return an owned value rather than a reference:

fn percuss(a: &str, b: &str, val: usize) -> String {
    let mut a = a.to_string();
    a.insert_str(val, b);
    a
}

or take a &mut String parameter and modify it in-place, without returning anything:

fn percuss(a: &mut String, b: &str, val: usize) {
    a.insert_str(val, b);
}

See also:

mcarton
  • 27,633
  • 5
  • 85
  • 95
  • second-to-last: `'a` is redundant. Last: that's the same as `insert_str`, really. – Shepmaster Jun 24 '20 at 16:48
  • It is, but the original question had some more stuff before the `insert_str` which were not relevant to the lifetime problem. – mcarton Jun 25 '20 at 20:14