about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-12-14 10:22:43 +0000
committerbors <bors@rust-lang.org>2024-12-14 10:22:43 +0000
commit25d004d28915b1a5cbb6386afdecef4b5e23266d (patch)
treedbfb524c25f30c5f6ae38510a1fe30174a8b26cc
parent37f79d5a85fe2ebe11be3e2c711fe635383e2ebc (diff)
parentc9c62c432903dd286ca81edde1cc19721b231632 (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.
-rw-r--r--clippy_lints/src/dereference.rs1
-rw-r--r--clippy_utils/src/hir_utils.rs3
2 files changed, 3 insertions, 1 deletions
diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs
index bd4ce7ab922..e3959903fdd 100644
--- a/clippy_lints/src/dereference.rs
+++ b/clippy_lints/src/dereference.rs
@@ -814,6 +814,7 @@ impl TyCoercionStability {
                 | TyKind::Tup(_)
                 | TyKind::Path(_) => Self::Deref,
                 TyKind::OpaqueDef(..)
+                | TyKind::TraitAscription(..)
                 | TyKind::Infer
                 | TyKind::Typeof(..)
                 | TyKind::TraitObject(..)
diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs
index 279025b9bf9..4b604f658b8 100644
--- a/clippy_utils/src/hir_utils.rs
+++ b/clippy_utils/src/hir_utils.rs
@@ -1260,7 +1260,8 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             | TyKind::Infer
             | TyKind::Never
             | TyKind::InferDelegation(..)
-            | TyKind::OpaqueDef(_) => {},
+            | TyKind::OpaqueDef(_)
+            | TyKind::TraitAscription(_) => {},
         }
     }