1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-04-02 09:44:11 +02:00
comprehensive-rust/src/traits/impl-trait.md

45 lines
1.6 KiB
Markdown
Raw Normal View History

2022-12-21 16:36:30 +01:00
# `impl Trait`
Similar to trait bounds, an `impl Trait` syntax can be used in function
arguments and return values:
```rust,editable
use std::fmt::Display;
fn get_x(name: impl Display) -> impl Display {
format!("Hello {name}")
}
fn main() {
let x = get_x("foo");
println!("{x}");
}
```
* `impl Trait` allows you to work with types which you cannot name.
2023-01-16 14:15:00 +00:00
<details>
The meaning of `impl Trait` is a bit different in the different positions.
* For a parameter, `impl Trait` is like an anonymous generic parameter with a trait bound.
2023-01-16 14:15:00 +00:00
* For a return type, it means that the return type is some concrete type that implements the trait,
without naming the type. This can be useful when you don't want to expose the concrete type in a
public API.
Inference is hard in return position. A function returning `impl Foo` picks
the concrete type it returns, without writing it out in the source. A function
returning a generic type like `collect<B>() -> B` can return any type
satisfying `B`, and the caller may need to choose one, such as with `let x:
Vec<_> = foo.collect()` or with the turbofish, `foo.collect::<Vec<_>>()`.
This example is great, because it uses `impl Display` twice. It helps to explain that
nothing here enforces that it is _the same_ `impl Display` type. If we used a single
`T: Display`, it would enforce the constraint that input `T` and return `T` type are the same type.
It would not work for this particular function, as the type we expect as input is likely not
what `format!` returns. If we wanted to do the same via `: Display` syntax, we'd need two
independent generic parameters.
2023-01-16 14:15:00 +00:00
</details>