diff options
| author | bors <bors@rust-lang.org> | 2024-12-14 10:22:43 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-12-14 10:22:43 +0000 |
| commit | f5079d00e63718235f95353df38ebb0891bab5b4 (patch) | |
| tree | a6900feb1a5792511b8ec4573d8e391b122410ee /src/librustdoc | |
| parent | ed141926048597e3649bb238ca3dc417904cd56c (diff) | |
| parent | d714a22e7bc38b158d09ee6294d1716acd1a727d (diff) | |
Auto merge of #134185 - compiler-errors:impl-trait-in-bindings, r=oli-obk
(Re-)Implement `impl_trait_in_bindings`
This reimplements the `impl_trait_in_bindings` feature for local bindings.
"`impl Trait` in bindings" serve as a form of *trait* ascription, where the type basically functions as an infer var but additionally registering the `impl Trait`'s trait bounds for the infer type. These trait bounds can be used to enforce that predicates hold, and can guide inference (e.g. for closure signature inference):
```rust
let _: impl Fn(&u8) -> &u8 = |x| x;
```
They are implemented as an additional set of bounds that are registered when the type is lowered during typeck, and then these bounds are tied to a given `CanonicalUserTypeAscription` for borrowck. We enforce these `CanonicalUserTypeAscription` bounds during borrowck to make sure that the `impl Trait` types are sensitive to lifetimes:
```rust
trait Static: 'static {}
impl<T> Static for T where T: 'static {}
let local = 1;
let x: impl Static = &local;
//~^ ERROR `local` does not live long enough
```
r? oli-obk
cc #63065
---
Why can't we just use TAIT inference or something? Well, TAITs in bodies have the problem that they cannot reference lifetimes local to a body. For example:
```rust
type TAIT = impl Display;
let local = 0;
let x: TAIT = &local;
//~^ ERROR `local` does not live long enough
```
That's because TAITs requires us to do *opaque type inference* which is pretty strict, since we need to remap all of the lifetimes of the hidden type to universal regions. This is simply not possible here.
---
I consider this part of the "impl trait everywhere" experiment. I'm not certain if this needs yet another lang team experiment.
Diffstat (limited to 'src/librustdoc')
| -rw-r--r-- | src/librustdoc/clean/mod.rs | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index a201a9bbfed..25f88c8797f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1839,11 +1839,15 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T DynTrait(bounds, lifetime) } TyKind::BareFn(barefn) => BareFunction(Box::new(clean_bare_fn_ty(barefn, cx))), - // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. - TyKind::Infer | TyKind::Err(_) | TyKind::Typeof(..) | TyKind::InferDelegation(..) => Infer, TyKind::UnsafeBinder(..) => { unimplemented!("unsafe binders are not supported yet") } + // Rustdoc handles `TyKind::Err`s by turning them into `Type::Infer`s. + TyKind::Infer + | TyKind::Err(_) + | TyKind::Typeof(..) + | TyKind::InferDelegation(..) + | TyKind::TraitAscription(_) => Infer, } } |
