Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding &type + 'a syntax

Tags:

syntax

rust

I have started to learn Rust. Currently I'm trying to learn how to properly use lifetime annotations and think I have understood the basics quite well. However, I have on several occasions encountered the following structure:

fn<'a> foo(a: &'a str, ...) -> &str + 'a

The str is not relevant it can be any type really, my question is specifically what &str + 'a mean (I might not be using it correctly, which is why I'm asking about it) as opposed to &'a str. As a real world example I have encountered it in this tutorial for async rust where they write:

fn foo_expanded<'a>(x: &'a u8) -> impl Future<Output = u8> + 'a

I'm speculating that it might have to do with that Future is a trait and not a type, but I have been unable to verify it in any official documentation and have not found any source on what the syntax mean.

like image 974
user1690991 Avatar asked Sep 10 '25 14:09

user1690991


2 Answers

First of all, the syntax shown in your post is not allowed.

fn<'a> foo(a: &'a str, ...) -> &str + 'a

There are two reasons:

  1. lifetime generics must be specified after the function name.
  2. the displayed way of specifying return lifetimes is allowed only for traits, not complete types.

Otherwise you would get one of the two following errors:

error[E0178]: expected a path on the left-hand side of `+`, not `&str`
  --> ./ex_056.rs:11:43
   |
11 | fn _get<'a>(ms: &'a MyStruct, s: &str) -> &str + 'a {
   |                                           ^^^^^^^^^ help: try adding parentheses: `&(str + 'a)`

or

error[E0404]: expected trait, found builtin type `str`
  --> ./ex_056.rs:15:31
   |
15 | fn _get2<'a>(s: &'a str) -> &(str + 'a) {
   |                               ^^^ not a trait

Thus it's not valid.

As a crude guess, I imagine that you have been misled by not a complete type but just a trait object. Since such a notation was allowed in 2015 but now it is deprecated, as you can see in the following warning:

warning: trait objects without an explicit `dyn` are deprecated
  --> ./ex_056.rs:15:31
   |
15 | fn _get2<'a>(s: &'a str) -> &(str + 'a) {
   |                               ^^^^^^^^ help: use `dyn`: `dyn str + 'a`
   |
   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
like image 169
dronte7 Avatar answered Sep 13 '25 09:09

dronte7


Your first example (&str + 'a) is not valid. The + 'a notation can only be applied to a trait.

Your second example: impl Future<Output = u8> + 'a means that foo_expanded returns some unknown type that implements the trait Future<Output = u8> and that this unknown type may contain references with the 'a lifetime. Therefore you won't be able to use the returned value once the 'a lifetime expires.

like image 36
Jmb Avatar answered Sep 13 '25 07:09

Jmb