about summary refs log tree commit diff
path: root/compiler/rustc_ast_lowering/src
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-08-31 04:03:24 +0000
committerMichael Goulet <michael@errs.io>2022-09-09 01:31:44 +0000
commitd34cb98fb0bbaf86860b4ad5ff0c3d79b077f565 (patch)
tree31f9a2b56052f3bfed4ee797ffca15678c985cb6 /compiler/rustc_ast_lowering/src
parent78b962a4f348c0b901d2eae9e5852cb3675b1233 (diff)
downloadrust-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.rs47
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")