I have the code simplified version of which looks like the following:
fn main() {
method1(true);
}
fn method1(cond: bool) -> (&[u8], String) {
let ret1 = if cond {
let a = "a string in base64".as_bytes().from_base64();
a.unwrap().as_slice()
} else {
[] // how can I return an empty array? Should I return vector instead?
};
(ret1, "aaa".to_string())
}
The error:
error: missing lifetime specifier [E0106]
test1.rs:7 fn method1(cond: bool) -> (&[u8], String) {
^~~~~
test1.rs:7:28: 7:33 help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
test1.rs:7 fn method1(cond: bool) -> (&[u8], String) {
^~~~~
test1.rs:7:28: 7:33 help: consider giving it a 'static lifetime
test1.rs:7 fn method1(cond: bool) -> (&[u8], String) {
^~~~~
error: aborting due to previous error
The bottom line is, I want to return a tuple of an array and a string (String or &str) from a method, how can I do that?
You can't.
You can do this:
But you can't return a reference to data which isn't owned by something outside the function. If the data isn't statically known, then yes, you'll have to return a
Vec<u8>
in order to pass ownership out.Revision to address question in comments.
Other things that don't work:
fn method1<'a>...
- firstly, this doesn't change the fact that to pass a reference out, you have to be referring to something which will still exist after the function exits. Outside of globals (which you should almost never use, especially in a case like this), there's no way to summnon a long-lived value into existence outside your function. You have to return a value that owns its contents, and that can never be a borrow.Declaring a generic lifetime parameter doesn't change that.
&([u8], String)
- this isn't valid. First, it has the exact same problem as originally: you can't return a borrow to something you've created. Secondly, it contains[u8]
, which is a dynamically sized type. You cannot have a dynamically sized type in a tuple; the only position (that I'm aware of) in which they are valid is at the very end of a struct, and that causes the struct itself to become dynamically sized. You cannot pass, return or store dynamically sized values.(&[u8], &str)
- this has the same problem as originally, except now the second tuple value is also borrowed. There are cases where the compiler can guess the lifetime for you, but this is not one of them (and I don't want to get into a description of the lifetime elision rules here).