diff options
| author | Michael Goulet <michael@errs.io> | 2022-08-31 04:03:24 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2022-09-09 01:31:44 +0000 |
| commit | d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565 (patch) | |
| tree | 31f9a2b56052f3bfed4ee797ffca15678c985cb6 /compiler/rustc_ast_lowering/src | |
| parent | 78b962a4f348c0b901d2eae9e5852cb3675b1233 (diff) | |
| download | rust-d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565.tar.gz rust-d34cb98fb0bbaf86860b4ad5ff0c3d79b077f565.zip | |
Lower RPITIT to ImplTraitPlaceholder item
Diffstat (limited to 'compiler/rustc_ast_lowering/src')
| -rw-r--r-- | compiler/rustc_ast_lowering/src/lib.rs | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f57c92fd70c..2e8fcd7dca4 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -255,6 +255,8 @@ enum ImplTraitContext { }, /// Impl trait in type aliases. TypeAliasesOpaqueTy, + /// Return-position `impl Trait` in trait definition + InTrait, /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), } @@ -323,9 +325,17 @@ enum FnDeclKind { } impl FnDeclKind { - fn impl_trait_return_allowed(&self) -> bool { + fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool { match self { FnDeclKind::Fn | FnDeclKind::Inherent => true, + FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true, + _ => false, + } + } + + fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool { + match self { + FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true, _ => false, } } @@ -1346,6 +1356,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut nested_itctx, ) } + ImplTraitContext::InTrait => { + // FIXME(RPITIT): Should we use def_node_id here? + self.lower_impl_trait_in_trait(span, def_node_id, bounds) + } ImplTraitContext::Universal => { let span = t.span; let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span); @@ -1532,6 +1546,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } + #[tracing::instrument(level = "debug", skip(self))] + fn lower_impl_trait_in_trait( + &mut self, + span: Span, + opaque_ty_node_id: NodeId, + bounds: &GenericBounds, + ) -> hir::TyKind<'hir> { + let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id); + self.with_hir_id_owner(opaque_ty_node_id, |lctx| { + // FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT + // FIXME(RPITIT): We _also_ should support this eventually + let hir_bounds = lctx + .lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait)); + let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; + let rpitit_item = hir::Item { + def_id: opaque_ty_def_id, + ident: Ident::empty(), + kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder), + span: lctx.lower_span(span), + vis_span: lctx.lower_span(span.shrink_to_lo()), + }; + hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item)) + }); + hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id }) + } + /// Registers a new opaque type with the proper `NodeId`s and /// returns the lowered node-ID for the opaque type. fn generate_opaque_type( @@ -1690,12 +1730,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match decl.output { FnRetTy::Ty(ref ty) => { let mut context = match fn_node_id { - Some(fn_node_id) if kind.impl_trait_return_allowed() => { + Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => { let fn_def_id = self.local_def_id(fn_node_id); ImplTraitContext::ReturnPositionOpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id), } } + Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => { + ImplTraitContext::InTrait + } _ => ImplTraitContext::Disallowed(match kind { FnDeclKind::Fn | FnDeclKind::Inherent => { unreachable!("fn should allow in-band lifetimes") |
