1
Fork 0

Address rebase issues, make async fn in trait work

This commit is contained in:
Michael Goulet 2022-09-02 16:45:30 +00:00
parent 5be30f9d79
commit 249ede4195
3 changed files with 89 additions and 19 deletions

View file

@ -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), .. }) => {

View file

@ -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<generics_from_parent_fn> = impl Future<Output = T>;
//
// `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<Output = T>`.
fn lower_async_fn_output_type_to_future_bound(
&mut self,