From f1679f7dd6330535cd2dbd0dd18ded0dc8a7e6d9 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 29 Aug 2023 23:47:01 +0000 Subject: [PATCH] Capture lifetimes for associated type bounds destined to be lowered to opaques --- compiler/rustc_ast_lowering/src/lib.rs | 11 +++++++++++ compiler/rustc_resolve/src/late.rs | 1 + .../lifetime-in-associated-trait-bound.rs | 19 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 tests/ui/impl-trait/in-trait/lifetime-in-associated-trait-bound.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index a4ba1a5c9bf48..a6d1ef33f4069 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -153,6 +153,7 @@ trait ResolverAstLoweringExt { fn get_label_res(&self, id: NodeId) -> Option; fn get_lifetime_res(&self, id: NodeId) -> Option; fn take_extra_lifetime_params(&mut self, id: NodeId) -> Vec<(Ident, NodeId, LifetimeRes)>; + fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId); fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind; } @@ -213,6 +214,11 @@ impl ResolverAstLoweringExt for ResolverAstLowering { self.extra_lifetime_params_map.remove(&id).unwrap_or_default() } + fn remap_extra_lifetime_params(&mut self, from: NodeId, to: NodeId) { + let lifetimes = self.extra_lifetime_params_map.remove(&from).unwrap_or_default(); + self.extra_lifetime_params_map.insert(to, lifetimes); + } + fn decl_macro_kind(&self, def_id: LocalDefId) -> MacroKind { self.builtin_macro_kinds.get(&def_id).copied().unwrap_or(MacroKind::Bang) } @@ -1089,6 +1095,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // constructing the HIR for `impl bounds...` and then lowering that. let impl_trait_node_id = self.next_node_id(); + // Shift `impl Trait` lifetime captures from the associated type bound's + // node id to the opaque node id, so that the opaque can actually use + // these lifetime bounds. + self.resolver + .remap_extra_lifetime_params(constraint.id, impl_trait_node_id); self.with_dyn_type_scope(false, |this| { let node_id = this.next_node_id(); diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 500004269c927..fa04a59455518 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1109,6 +1109,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast, } }, AssocConstraintKind::Bound { ref bounds } => { + self.record_lifetime_params_for_impl_trait(constraint.id); walk_list!(self, visit_param_bound, bounds, BoundKind::Bound); } } diff --git a/tests/ui/impl-trait/in-trait/lifetime-in-associated-trait-bound.rs b/tests/ui/impl-trait/in-trait/lifetime-in-associated-trait-bound.rs new file mode 100644 index 0000000000000..49d36d6c99c9a --- /dev/null +++ b/tests/ui/impl-trait/in-trait/lifetime-in-associated-trait-bound.rs @@ -0,0 +1,19 @@ +// check-pass + +#![feature(associated_type_bounds, return_position_impl_trait_in_trait)] + +trait Trait { + type Type; + + fn method(&self) -> impl Trait; +} + +impl Trait for () { + type Type = (); + + fn method(&self) -> impl Trait { + () + } +} + +fn main() {}