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, bounds)
- }
+ *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)
- }
-
- #[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 })
+ 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
}));
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(
+ &decl.output,
+ fn_node_id.expect("`make_ret_async` but no `fn_def_id`"),
+ ret_id,
+ true,
+ )
+ }
+ _ => {
+ 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,
+ false,
+ )
+ }
}
-
- 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) => {
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))
}
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, &[])),
};