Address rebase issues, make async fn in trait work
This commit is contained in:
parent
5be30f9d79
commit
249ede4195
3 changed files with 89 additions and 19 deletions
|
@ -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), .. }) => {
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue