1
Fork 0

Lower RPITIT to ImplTraitPlaceholder item

This commit is contained in:
Michael Goulet 2022-08-31 04:03:24 +00:00
parent 78b962a4f3
commit d34cb98fb0
11 changed files with 99 additions and 8 deletions

View file

@ -255,6 +255,8 @@ enum ImplTraitContext {
},
/// Impl trait in type aliases.
TypeAliasesOpaqueTy,
/// Return-position `impl Trait` in trait definition
InTrait,
/// `impl Trait` is not accepted in this position.
Disallowed(ImplTraitPosition),
}
@ -323,9 +325,17 @@ enum FnDeclKind {
}
impl FnDeclKind {
fn impl_trait_return_allowed(&self) -> bool {
fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Fn | FnDeclKind::Inherent => true,
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
_ => false,
}
}
fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
match self {
FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
_ => false,
}
}
@ -1346,6 +1356,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
&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)
}
ImplTraitContext::Universal => {
let span = t.span;
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
@ -1532,6 +1546,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
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 })
}
/// Registers a new opaque type with the proper `NodeId`s and
/// returns the lowered node-ID for the opaque type.
fn generate_opaque_type(
@ -1690,12 +1730,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
match decl.output {
FnRetTy::Ty(ref ty) => {
let mut context = match fn_node_id {
Some(fn_node_id) if kind.impl_trait_return_allowed() => {
Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => {
let fn_def_id = self.local_def_id(fn_node_id);
ImplTraitContext::ReturnPositionOpaqueTy {
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
}
}
Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => {
ImplTraitContext::InTrait
}
_ => ImplTraitContext::Disallowed(match kind {
FnDeclKind::Fn | FnDeclKind::Inherent => {
unreachable!("fn should allow in-band lifetimes")