Preserving 'static across AsRef

I'm writing a function that needs to be able to take either a string literal or a bytes literal as an argument, and this argument will be passed to a function from a third-party library that takes a &'static [u8]. The best code I can come up with is of the form:

fn static_taker(_bytes: &'static [u8]) {
    todo!()
}

fn call_static_taker<S: AsRef<[u8]> + 'static>(bs: S) {
    static_taker(bs.as_ref());
}

fn call_1() {
    call_static_taker("This is a &'static str.");
}

fn call_2() {
    call_static_taker(&b"This is a &'static [u8]."[..]);
}

(Playground)

but this fails to compile with:

   Compiling playground v0.0.1 (/playground)
error[E0597]: `bs` does not live long enough
 --> src/lib.rs:6:18
  |
6 |     static_taker(bs.as_ref());
  |     -------------^^^^^^^^^^^-
  |     |            |
  |     |            borrowed value does not live long enough
  |     argument requires that `bs` is borrowed for `'static`
7 | }
  | - `bs` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.
error: could not compile `playground` due to previous error

How do I get this to compile?

See if this signature works for you:

fn call_static_taker<S: ?Sized + AsRef<[u8]>>(bs: &'static S) {
2 Likes

One way is to write a new trait that specifically encodes that the borrow has 'static lifetime:

trait AsStaticRef {
  fn as_static_ref(&self) -> &'static [u8];
} 

And then just implement that for &' static str and &'static [u8].

Here's a link to the playground that compiles.

See misconception #2 for why S: 'static was not what you needed.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.