diff options
| author | bors <bors@rust-lang.org> | 2024-04-16 11:22:35 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-16 11:22:35 +0000 |
| commit | 4e1f5d90bca45207605a88e39b1f76abcdb85d2f (patch) | |
| tree | c927952718135627a6c5e5bc68886e81b9f38f60 /compiler/rustc_hir | |
| parent | ad18fe08de03fbb459c05475bddee22707b4f0ec (diff) | |
| parent | 8ddd2805de6ad8200868befc6ae703243fac3a46 (diff) | |
| download | rust-4e1f5d90bca45207605a88e39b1f76abcdb85d2f.tar.gz rust-4e1f5d90bca45207605a88e39b1f76abcdb85d2f.zip | |
Auto merge of #123468 - compiler-errors:precise-capturing, r=oli-obk
Implement syntax for `impl Trait` to specify its captures explicitly (`feature(precise_capturing)`) Implements `impl use<'a, 'b, T, U> Sized` syntax that allows users to explicitly list the captured parameters for an opaque, rather than inferring it from the opaque's bounds (or capturing *all* lifetimes under 2024-edition capture rules). This allows us to exclude some implicit captures, so this syntax may be used as a migration strategy for changes due to #117587. We represent this list of captured params as `PreciseCapturingArg` in AST and HIR, resolving them between `rustc_resolve` and `resolve_bound_vars`. Later on, we validate that the opaques only capture the parameters in this list. We artificially limit the feature to *require* mentioning all type and const parameters, since we don't currently have support for non-lifetime bivariant generics. This can be relaxed in the future. We also may need to limit this to require naming *all* lifetime parameters for RPITIT, since GATs have no variance. I have to investigate this. This can also be relaxed in the future. r? `@oli-obk` Tracking issue: - https://github.com/rust-lang/rust/issues/123432
Diffstat (limited to 'compiler/rustc_hir')
| -rw-r--r-- | compiler/rustc_hir/src/hir.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_hir/src/intravisit.rs | 20 |
2 files changed, 42 insertions, 1 deletions
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c6e3ad31f01..b39056d8690 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2557,6 +2557,27 @@ pub struct OpaqueTy<'hir> { /// originating from a trait method. This makes it so that the opaque is /// lowered as an associated type. pub in_trait: bool, + /// List of arguments captured via `impl use<'a, P, ...> Trait` syntax. + pub precise_capturing_args: Option<&'hir [PreciseCapturingArg<'hir>]>, +} + +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub enum PreciseCapturingArg<'hir> { + Lifetime(&'hir Lifetime), + /// Non-lifetime argument (type or const) + Param(PreciseCapturingNonLifetimeArg), +} + +/// We need to have a [`Node`] for the [`HirId`] that we attach the type/const param +/// resolution to. Lifetimes don't have this problem, and for them, it's actually +/// kind of detrimental to use a custom node type versus just using [`Lifetime`], +/// since resolve_bound_vars operates on `Lifetime`s. +// FIXME(precise_capturing): Investigate storing this as a path instead? +#[derive(Debug, Clone, Copy, HashStable_Generic)] +pub struct PreciseCapturingNonLifetimeArg { + pub hir_id: HirId, + pub ident: Ident, + pub res: Res, } /// From whence the opaque type came. @@ -3535,6 +3556,7 @@ pub enum Node<'hir> { WhereBoundPredicate(&'hir WhereBoundPredicate<'hir>), // FIXME: Merge into `Node::Infer`. ArrayLenInfer(&'hir InferArg), + PreciseCapturingNonLifetimeArg(&'hir PreciseCapturingNonLifetimeArg), // Created by query feeding Synthetic, // Span by reference to minimize `Node`'s size @@ -3571,6 +3593,7 @@ impl<'hir> Node<'hir> { Node::TypeBinding(b) => Some(b.ident), Node::PatField(f) => Some(f.ident), Node::ExprField(f) => Some(f.ident), + Node::PreciseCapturingNonLifetimeArg(a) => Some(a.ident), Node::Param(..) | Node::AnonConst(..) | Node::ConstBlock(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 5da9d4444da..cd9f9ff9109 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -413,6 +413,9 @@ pub trait Visitor<'v>: Sized { fn visit_param_bound(&mut self, bounds: &'v GenericBound<'v>) -> Self::Result { walk_param_bound(self, bounds) } + fn visit_precise_capturing_arg(&mut self, arg: &'v PreciseCapturingArg<'v>) -> Self::Result { + walk_precise_capturing_arg(self, arg) + } fn visit_poly_trait_ref(&mut self, t: &'v PolyTraitRef<'v>) -> Self::Result { walk_poly_trait_ref(self, t) } @@ -526,10 +529,15 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_ty(ty)); try_visit!(visitor.visit_generics(generics)); } - ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => { + ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, precise_capturing_args, .. }) => { try_visit!(visitor.visit_id(item.hir_id())); try_visit!(walk_generics(visitor, generics)); walk_list!(visitor, visit_param_bound, bounds); + if let Some(precise_capturing_args) = precise_capturing_args { + for arg in precise_capturing_args { + try_visit!(visitor.visit_precise_capturing_arg(arg)); + } + } } ItemKind::Enum(ref enum_definition, ref generics) => { try_visit!(visitor.visit_generics(generics)); @@ -1137,6 +1145,16 @@ pub fn walk_param_bound<'v, V: Visitor<'v>>( } } +pub fn walk_precise_capturing_arg<'v, V: Visitor<'v>>( + visitor: &mut V, + arg: &'v PreciseCapturingArg<'v>, +) -> V::Result { + match *arg { + PreciseCapturingArg::Lifetime(lt) => visitor.visit_lifetime(lt), + PreciseCapturingArg::Param(param) => visitor.visit_id(param.hir_id), + } +} + pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>( visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>, |
