Why does it show `dropped here while still borrowed`

fn test(){
    let mut m: HashMap<&str, &[u8]> = HashMap::new();
    let s = "s";
    let sb = s.as_bytes();
    m.insert("s", sb);
    let pa = 11i32.to_be_bytes();
    m.insert("a", pa.as_slice());

I could insert sb into map, but I can not insert another &[u8] into map? pa.as_slice() and sb have same data type, why is it?

The code compiles and runs on playground at least.

let s = "s";

Is a static allocation with "s" in it such that "s" lives for the entire life of the program. As a result:

let sb = s.as_bytes();

produces a reference to a slice with a 'static lifetime (meaning that the reference is valid for the entire life of the program). Conversely,

let pa = 11i32.to_be_bytes();

Creates a stack-allocated array of bytes. So,


Create an &[u8] reference that only has a lifetime until pa is dropped, which happens at the end of the function. Therefore, you are attempting to insert a reference to something that will not exist after the end of the function into the HashMap.


:+1: :+1: :+1:

That's somewhat misleading. "s" may be a &'static str, but the signature of str::as_bytes is (elaborated)

pub const fn as_bytes<'a>(&'a self /* = &'a str */) -> &'a [u8]

That is, it by no means has to produce a &'static [u8], and the compiler will generally infer a shorter lifetime as needed. Which is part of why the given code does indeed run, as @jdahlstrom noted. (And even if as_bytes did work that way, sb could be coerced to a shorter lifetime upon insertion to the HashMap instead, for another part.)

Something else must be going on to cause the mismatch, for example a m: HashMap<&str, &'static [u8]> annotation.

&'a [u8] and &'b [u8] are different types if 'a is not the same as 'b. However, the one with a longer lifetime can coerce to the shorter lifetime (or they could both coerce to some lifetime 'c which is shorter than both). What you cannot do is coerce either one to a longer lifetime (or your borrow might outlive the data it points to).