Skip to content

Commit f5079d0

Browse files
committedDec 14, 2024
Auto merge of rust-lang#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 rust-lang#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.
2 parents ed14192 + d714a22 commit f5079d0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+442
-52
lines changed
 

‎compiler/rustc_ast_lowering/src/block.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind};
22
use rustc_hir as hir;
3+
use rustc_span::sym;
34
use smallvec::SmallVec;
45

56
use crate::{ImplTraitContext, ImplTraitPosition, LoweringContext};
@@ -82,11 +83,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
8283
(self.arena.alloc_from_iter(stmts), expr)
8384
}
8485

86+
/// Return an `ImplTraitContext` that allows impl trait in bindings if
87+
/// the feature gate is enabled, or issues a feature error if it is not.
88+
fn impl_trait_in_bindings_ctxt(&self, position: ImplTraitPosition) -> ImplTraitContext {
89+
if self.tcx.features().impl_trait_in_bindings() {
90+
ImplTraitContext::InBinding
91+
} else {
92+
ImplTraitContext::FeatureGated(position, sym::impl_trait_in_bindings)
93+
}
94+
}
95+
8596
fn lower_local(&mut self, l: &Local) -> &'hir hir::LetStmt<'hir> {
86-
let ty = l
87-
.ty
88-
.as_ref()
89-
.map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Variable)));
97+
// Let statements are allowed to have impl trait in bindings.
98+
let ty = l.ty.as_ref().map(|t| {
99+
self.lower_ty(t, self.impl_trait_in_bindings_ctxt(ImplTraitPosition::Variable))
100+
});
90101
let init = l.kind.init().map(|init| self.lower_expr(init));
91102
let hir_id = self.lower_node_id(l.id);
92103
let pat = self.lower_pat(&l.pat);

‎compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,13 @@ enum ImplTraitContext {
260260
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
261261
///
262262
OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> },
263+
264+
/// Treat `impl Trait` as a "trait ascription", which is like a type
265+
/// variable but that also enforces that a set of trait goals hold.
266+
///
267+
/// This is useful to guide inference for unnameable types.
268+
InBinding,
269+
263270
/// `impl Trait` is unstably accepted in this position.
264271
FeatureGated(ImplTraitPosition, Symbol),
265272
/// `impl Trait` is not accepted in this position.
@@ -1327,6 +1334,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13271334
}
13281335
path
13291336
}
1337+
ImplTraitContext::InBinding => {
1338+
hir::TyKind::TraitAscription(self.lower_param_bounds(bounds, itctx))
1339+
}
13301340
ImplTraitContext::FeatureGated(position, feature) => {
13311341
let guar = self
13321342
.tcx

0 commit comments

Comments
 (0)
Please sign in to comment.