Lifetime of struct returned from function


#1

Hi, i have 2 structs as such:
struct HCICommand<'a>
{
ogf: u8,
ocf: u16,
command: &'a [u8],
}

struct HCIResponse<'a>
{
eventcode: u8,
length: u8,
params: &'a [u8],
}

And a function:
fn bt_send_hci_command(cmd: &HCICommand) -> HCIResponse
{
let mut ret = HCIResponse{eventcode: 0, length: 0, params: &[0 as u8]};
ret
}

Which gets me an error on “-> HCIResponse” in the function
missing lifetime specifier [E0106]:
this function’s return type contains a borrowed value, but the signature does not say which one of cmd's 2 elided lifetimes it is borrowed from
expected lifetime parameter

which says there is a problem with the lifetimes in HCICommand?


#2

You need to define an explicit lifetime for bt_send_hci_command(), like so:

fn bt_send_hci_command<'a>(cmd: &'a HCICommand) -> HCIResponse<'a> {}

But your code still won’t build because of this line:

params: &[0 as u8],

The struct doesn’t own the array, only a reference to it. So once you return from the function, the array is freed from the stack and you end up pointing to garbage.


#3

The problem is that cmd argument has two lifetime parameters, and Rust doesn’t know what you want in '?:

fn send<'a, 'b>(cmd: &'a HCICommand<'b>) -> HCIResponse<'?>

If you want to return params that are a part of cmd.command (or just cmd.command), then the valid annotation would be:

fn bt_send_hci_command<'a>(cmd: &HCICommand<'a>) -> HCIResponse<'a>
{
    HCIResponse { eventcode: 0, length: 0, params: &cmd.command[1..5] }
}

If you want to create params from scratch, as in your example, you need to change the params field from &[u8] to just Vec<u8> and return a vector.