ReturnPositionOpaqueTy {
/// Origin: Either OpaqueTyOrigin::FnReturn or OpaqueTyOrigin::AsyncFn,
origin: hir::OpaqueTyOrigin,
+ in_trait: bool,
},
/// Impl trait in type aliases.
TypeAliasesOpaqueTy,
- /// Return-position `impl Trait` in trait definition
- InTrait,
/// `impl Trait` is not accepted in this position.
Disallowed(ImplTraitPosition),
}
}
}
-#[derive(Debug)]
+#[derive(Debug, PartialEq, Eq)]
enum FnDeclKind {
Fn,
Inherent,
return self.lower_path_ty(t, qself, path, ParamMode::Explicit, itctx);
}
TyKind::ImplicitSelf => {
- let hir_id = self.lower_node_id(t.id);
+ let hir_id = self.next_id();
let res = self.expect_full_res(t.id);
let res = self.lower_res(res);
hir::TyKind::Path(hir::QPath::Resolved(
TyKind::ImplTrait(def_node_id, ref bounds) => {
let span = t.span;
match itctx {
- ImplTraitContext::ReturnPositionOpaqueTy { origin } => {
- self.lower_opaque_impl_trait(span, *origin, def_node_id, bounds, itctx)
- }
- ImplTraitContext::TypeAliasesOpaqueTy => {
- let mut nested_itctx = ImplTraitContext::TypeAliasesOpaqueTy;
- self.lower_opaque_impl_trait(
+ ImplTraitContext::ReturnPositionOpaqueTy { origin, in_trait } => self
+ .lower_opaque_impl_trait(
span,
- hir::OpaqueTyOrigin::TyAlias,
+ *origin,
def_node_id,
bounds,
- &mut nested_itctx,
- )
- }
- ImplTraitContext::InTrait => {
- // FIXME(RPITIT): Should we use def_node_id here?
- self.lower_impl_trait_in_trait(span, def_node_id, |lctx| {
- lctx.lower_param_bounds(
- bounds,
- ImplTraitContext::Disallowed(ImplTraitPosition::Trait),
- )
- })
- }
+ *in_trait,
+ itctx,
+ ),
+ ImplTraitContext::TypeAliasesOpaqueTy => self.lower_opaque_impl_trait(
+ span,
+ hir::OpaqueTyOrigin::TyAlias,
+ def_node_id,
+ bounds,
+ false,
+ &mut ImplTraitContext::TypeAliasesOpaqueTy,
+ ),
ImplTraitContext::Universal => {
let span = t.span;
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
}
path
}
+ ImplTraitContext::Disallowed(
+ position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
+ ) => {
+ self.tcx
+ .sess
+ .create_feature_err(
+ MisplacedImplTrait {
+ span: t.span,
+ position: DiagnosticArgFromDisplay(&position),
+ },
+ sym::return_position_impl_trait_in_trait,
+ )
+ .emit();
+ hir::TyKind::Err
+ }
ImplTraitContext::Disallowed(position) => {
self.tcx.sess.emit_err(MisplacedImplTrait {
span: t.span,
origin: hir::OpaqueTyOrigin,
opaque_ty_node_id: NodeId,
bounds: &GenericBounds,
+ in_trait: bool,
itctx: &mut ImplTraitContext,
) -> hir::TyKind<'hir> {
// Make sure we know that some funky desugaring has been going on here.
}),
bounds: hir_bounds,
origin,
+ in_trait,
};
debug!(?opaque_ty_item);
debug!(?lifetimes);
// `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
- hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
- }
-
- #[instrument(level = "debug", skip(self, lower_bounds))]
- fn lower_impl_trait_in_trait(
- &mut self,
- span: Span,
- opaque_ty_node_id: NodeId,
- 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 = lower_bounds(lctx);
- 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 })
+ hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes, in_trait)
}
/// Registers a new opaque type with the proper `NodeId`s and
)
.emit();
}
- self.lower_async_fn_ret_ty_in_trait(
+ self.lower_async_fn_ret_ty(
&decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
ret_id,
+ true,
)
}
_ => {
&decl.output,
fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
ret_id,
+ false,
)
}
}
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+ in_trait: false,
}
}
- Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => {
- ImplTraitContext::InTrait
+ Some(fn_node_id) if kind.impl_trait_in_trait_allowed(self.tcx) => {
+ let fn_def_id = self.local_def_id(fn_node_id);
+ ImplTraitContext::ReturnPositionOpaqueTy {
+ origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+ in_trait: true,
+ }
}
_ => ImplTraitContext::Disallowed(match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
output: &FnRetTy,
fn_node_id: NodeId,
opaque_ty_node_id: NodeId,
+ in_trait: bool,
) -> hir::FnRetTy<'hir> {
let span = output.span();
//
// Then, we will create `fn foo(..) -> Foo<'_, '_>`, and
// hence the elision takes place at the fn site.
- let future_bound =
- this.lower_async_fn_output_type_to_future_bound(output, fn_def_id, span);
+ let future_bound = this.lower_async_fn_output_type_to_future_bound(
+ output,
+ span,
+ ImplTraitContext::ReturnPositionOpaqueTy {
+ origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
+ in_trait,
+ },
+ );
let generic_params = this.arena.alloc_from_iter(collected_lifetimes.iter().map(
|&(new_node_id, lifetime, _)| {
}),
bounds: arena_vec![this; future_bound],
origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+ in_trait,
};
trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id);
// Foo = impl Trait` is, internally, created as a child of the
// async fn, so the *type parameters* are inherited. It's
// only the lifetime parameters that we must supply.
- let opaque_ty_ref =
- hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, generic_args);
+ let opaque_ty_ref = hir::TyKind::OpaqueDef(
+ hir::ItemId { def_id: opaque_ty_def_id },
+ generic_args,
+ in_trait,
+ );
let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref);
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,
output: &FnRetTy,
- fn_def_id: LocalDefId,
span: Span,
+ mut nested_impl_trait_context: ImplTraitContext,
) -> hir::GenericBound<'hir> {
// Compute the `T` in `Future<Output = T>` from the return type.
let output_ty = match output {
// Not `OpaqueTyOrigin::AsyncFn`: that's only used for the
// `impl Future` opaque type that `async fn` implicitly
// generates.
- let mut context = ImplTraitContext::ReturnPositionOpaqueTy {
- origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
- };
- self.lower_ty(ty, &mut context)
+ self.lower_ty(ty, &mut nested_impl_trait_context)
}
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
};