but there is no value for it to be borrowed from

陌路散爱 提交于 2020-01-14 05:44:07

问题


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?


回答1:


You can't.

You can do this:

fn main() {
  method1(true);
}

fn method1(cond: bool) -> (&'static [u8], String) {
  // ' <-- un-confuse SO syntax highlighting...
  let ret1 = if cond {
    b"some hard-coded data"
  } else {
    b""
  };

  (ret1, "aaa".to_string())
}

Note: b"..." is just a short-hand syntax for creating &'static [u8] values.

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).



来源:https://stackoverflow.com/questions/27247142/but-there-is-no-value-for-it-to-be-borrowed-from

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!