From 249ede4195a40147c45411f1fa27e376d40f4f95 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 2 Sep 2022 16:45:30 +0000 Subject: [PATCH] Address rebase issues, make async fn in trait work --- compiler/rustc_ast_lowering/src/item.rs | 10 ++- compiler/rustc_ast_lowering/src/lib.rs | 92 ++++++++++++++++---- compiler/rustc_metadata/src/rmeta/encoder.rs | 6 +- 3 files changed, 89 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 96e281ca5c8..52273778dcc 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -777,9 +777,15 @@ impl<'hir> LoweringContext<'_, 'hir> { (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some()) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: None, .. }) => { + let asyncness = sig.header.asyncness; let names = self.lower_fn_params_to_names(&sig.decl); - let (generics, sig) = - self.lower_method_sig(generics, sig, i.id, FnDeclKind::Trait, None); + let (generics, sig) = self.lower_method_sig( + generics, + sig, + i.id, + FnDeclKind::Trait, + asyncness.opt_return_id(), + ); (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false) } AssocItemKind::Fn(box Fn { ref sig, ref generics, body: Some(ref body), .. }) => { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index de7e64351b9..8814d184c55 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1358,7 +1358,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::InTrait => { // FIXME(RPITIT): Should we use def_node_id here? - self.lower_impl_trait_in_trait(span, def_node_id, bounds) + self.lower_impl_trait_in_trait(span, def_node_id, |lctx| { + lctx.lower_param_bounds( + bounds, + ImplTraitContext::Disallowed(ImplTraitPosition::Trait), + ) + }) } ImplTraitContext::Universal => { let span = t.span; @@ -1546,19 +1551,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes) } - #[tracing::instrument(level = "debug", skip(self))] + #[instrument(level = "debug", skip(self, lower_bounds))] fn lower_impl_trait_in_trait( &mut self, span: Span, opaque_ty_node_id: NodeId, - bounds: &GenericBounds, + lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, ) -> 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 hir_bounds = lower_bounds(lctx); let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds }; let rpitit_item = hir::Item { def_id: opaque_ty_def_id, @@ -1719,18 +1723,44 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { })); let output = if let Some((ret_id, span)) = make_ret_async { - if !self.tcx.features().return_position_impl_trait_in_trait { - self.tcx.sess.emit_feature_err( - TraitFnAsync { fn_span, span }, - sym::return_position_impl_trait_in_trait, - ); + match kind { + FnDeclKind::Trait => { + if !kind.impl_trait_in_trait_allowed(self.tcx) { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } + self.lower_async_fn_ret_ty_in_trait( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + ) + } + _ => { + if !kind.impl_trait_return_allowed(self.tcx) { + if kind == FnDeclKind::Impl { + self.tcx + .sess + .create_feature_err( + TraitFnAsync { fn_span, span }, + sym::return_position_impl_trait_in_trait, + ) + .emit(); + } else { + self.tcx.sess.emit_err(TraitFnAsync { fn_span, span }); + } + } + self.lower_async_fn_ret_ty( + &decl.output, + fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), + ret_id, + ) + } } - - self.lower_async_fn_ret_ty( - &decl.output, - fn_node_id.expect("`make_ret_async` but no `fn_def_id`"), - ret_id, - ) } else { match decl.output { FnRetTy::Ty(ref ty) => { @@ -2020,6 +2050,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } + // Transforms `-> T` for `async fn` into `-> OpaqueTy { .. }` + // combined with the following definition of `OpaqueTy`: + // + // type OpaqueTy = impl Future; + // + // `output`: unlowered output type (`T` in `-> T`) + // `fn_def_id`: `DefId` of the parent function (used to create child impl trait definition) + // `opaque_ty_node_id`: `NodeId` of the opaque `impl Trait` type that should be created + #[instrument(level = "debug", skip(self))] + fn lower_async_fn_ret_ty_in_trait( + &mut self, + output: &FnRetTy, + fn_node_id: NodeId, + opaque_ty_node_id: NodeId, + ) -> hir::FnRetTy<'hir> { + let span = output.span(); + + let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); + + let fn_def_id = self.local_def_id(fn_node_id); + + let kind = self.lower_impl_trait_in_trait(output.span(), opaque_ty_node_id, |lctx| { + let bound = + lctx.lower_async_fn_output_type_to_future_bound(output, fn_def_id, output.span()); + arena_vec![lctx; bound] + }); + let opaque_ty = self.ty(opaque_ty_span, kind); + hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) + } + /// Transforms `-> T` into `Future`. fn lower_async_fn_output_type_to_future_bound( &mut self, diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 02ca34181cd..d45d814c3b0 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1036,6 +1036,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1085,6 +1086,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Static(..) | DefKind::TyAlias | DefKind::OpaqueTy + | DefKind::ImplTraitPlaceholder | DefKind::ForeignTy | DefKind::Impl | DefKind::AssocFn @@ -1497,7 +1499,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } hir::ItemKind::OpaqueTy(..) => { self.encode_explicit_item_bounds(def_id); - EntryKind::OpaqueTy + } + hir::ItemKind::ImplTraitPlaceholder(..) => { + self.encode_explicit_item_bounds(def_id); } hir::ItemKind::Enum(..) => { let adt_def = self.tcx.adt_def(def_id);