Skip to content

Commit d34cb98

Browse files
Lower RPITIT to ImplTraitPlaceholder item
1 parent 78b962a commit d34cb98

File tree

11 files changed

+99
-8
lines changed

11 files changed

+99
-8
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+45-2
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ enum ImplTraitContext {
255255
},
256256
/// Impl trait in type aliases.
257257
TypeAliasesOpaqueTy,
258+
/// Return-position `impl Trait` in trait definition
259+
InTrait,
258260
/// `impl Trait` is not accepted in this position.
259261
Disallowed(ImplTraitPosition),
260262
}
@@ -323,9 +325,17 @@ enum FnDeclKind {
323325
}
324326

325327
impl FnDeclKind {
326-
fn impl_trait_return_allowed(&self) -> bool {
328+
fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool {
327329
match self {
328330
FnDeclKind::Fn | FnDeclKind::Inherent => true,
331+
FnDeclKind::Impl if tcx.features().return_position_impl_trait_in_trait => true,
332+
_ => false,
333+
}
334+
}
335+
336+
fn impl_trait_in_trait_allowed(&self, tcx: TyCtxt<'_>) -> bool {
337+
match self {
338+
FnDeclKind::Trait if tcx.features().return_position_impl_trait_in_trait => true,
329339
_ => false,
330340
}
331341
}
@@ -1346,6 +1356,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13461356
&mut nested_itctx,
13471357
)
13481358
}
1359+
ImplTraitContext::InTrait => {
1360+
// FIXME(RPITIT): Should we use def_node_id here?
1361+
self.lower_impl_trait_in_trait(span, def_node_id, bounds)
1362+
}
13491363
ImplTraitContext::Universal => {
13501364
let span = t.span;
13511365
let ident = Ident::from_str_and_span(&pprust::ty_to_string(t), span);
@@ -1532,6 +1546,32 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
15321546
hir::TyKind::OpaqueDef(hir::ItemId { def_id: opaque_ty_def_id }, lifetimes)
15331547
}
15341548

1549+
#[tracing::instrument(level = "debug", skip(self))]
1550+
fn lower_impl_trait_in_trait(
1551+
&mut self,
1552+
span: Span,
1553+
opaque_ty_node_id: NodeId,
1554+
bounds: &GenericBounds,
1555+
) -> hir::TyKind<'hir> {
1556+
let opaque_ty_def_id = self.local_def_id(opaque_ty_node_id);
1557+
self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
1558+
// FIXME(RPITIT): This should be a more descriptive ImplTraitPosition, i.e. nested RPITIT
1559+
// FIXME(RPITIT): We _also_ should support this eventually
1560+
let hir_bounds = lctx
1561+
.lower_param_bounds(bounds, ImplTraitContext::Disallowed(ImplTraitPosition::Trait));
1562+
let rpitit_placeholder = hir::ImplTraitPlaceholder { bounds: hir_bounds };
1563+
let rpitit_item = hir::Item {
1564+
def_id: opaque_ty_def_id,
1565+
ident: Ident::empty(),
1566+
kind: hir::ItemKind::ImplTraitPlaceholder(rpitit_placeholder),
1567+
span: lctx.lower_span(span),
1568+
vis_span: lctx.lower_span(span.shrink_to_lo()),
1569+
};
1570+
hir::OwnerNode::Item(lctx.arena.alloc(rpitit_item))
1571+
});
1572+
hir::TyKind::ImplTraitInTrait(hir::ItemId { def_id: opaque_ty_def_id })
1573+
}
1574+
15351575
/// Registers a new opaque type with the proper `NodeId`s and
15361576
/// returns the lowered node-ID for the opaque type.
15371577
fn generate_opaque_type(
@@ -1690,12 +1730,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
16901730
match decl.output {
16911731
FnRetTy::Ty(ref ty) => {
16921732
let mut context = match fn_node_id {
1693-
Some(fn_node_id) if kind.impl_trait_return_allowed() => {
1733+
Some(fn_node_id) if kind.impl_trait_return_allowed(self.tcx) => {
16941734
let fn_def_id = self.local_def_id(fn_node_id);
16951735
ImplTraitContext::ReturnPositionOpaqueTy {
16961736
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
16971737
}
16981738
}
1739+
Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => {
1740+
ImplTraitContext::InTrait
1741+
}
16991742
_ => ImplTraitContext::Disallowed(match kind {
17001743
FnDeclKind::Fn | FnDeclKind::Inherent => {
17011744
unreachable!("fn should allow in-band lifetimes")

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,8 @@ declare_features! (
487487
(incomplete, repr128, "1.16.0", Some(56071), None),
488488
/// Allows `repr(simd)` and importing the various simd intrinsics.
489489
(active, repr_simd, "1.4.0", Some(27731), None),
490+
/// Allows return-position `impl Trait` in traits.
491+
(incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None),
490492
/// Allows `extern "rust-cold"`.
491493
(active, rust_cold_cc, "1.63.0", Some(97544), None),
492494
/// Allows the use of SIMD types in functions declared in `extern` blocks.

compiler/rustc_hir/src/target.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ impl Target {
105105
DefKind::GlobalAsm => Target::GlobalAsm,
106106
DefKind::TyAlias => Target::TyAlias,
107107
DefKind::OpaqueTy => Target::OpaqueTy,
108+
DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder,
108109
DefKind::Enum => Target::Enum,
109110
DefKind::Struct => Target::Struct,
110111
DefKind::Union => Target::Union,

compiler/rustc_middle/src/ty/error.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
22
use crate::ty::diagnostics::suggest_constraining_type_param;
33
use crate::ty::print::{FmtPrinter, Printer};
44
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
5+
use hir::def::DefKind;
56
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
67
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
78
use rustc_hir as hir;
@@ -538,7 +539,7 @@ impl<T> Trait<T> for X {
538539
diag.span_label(p_span, "this type parameter");
539540
}
540541
}
541-
(ty::Projection(proj_ty), _) => {
542+
(ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
542543
self.expected_projection(
543544
diag,
544545
proj_ty,
@@ -547,7 +548,7 @@ impl<T> Trait<T> for X {
547548
cause.code(),
548549
);
549550
}
550-
(_, ty::Projection(proj_ty)) => {
551+
(_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
551552
let msg = format!(
552553
"consider constraining the associated type `{}` to `{}`",
553554
values.found, values.expected,

compiler/rustc_middle/src/ty/sty.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::ty::{
1111
TypeVisitor,
1212
};
1313
use crate::ty::{List, ParamEnv};
14+
use hir::def::DefKind;
1415
use polonius_engine::Atom;
1516
use rustc_data_structures::captures::Captures;
1617
use rustc_data_structures::intern::Interned;
@@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> {
11961197

11971198
impl<'tcx> ProjectionTy<'tcx> {
11981199
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
1199-
tcx.parent(self.item_def_id)
1200+
let parent = tcx.parent(self.item_def_id);
1201+
assert_eq!(tcx.def_kind(parent), DefKind::Trait);
1202+
parent
12001203
}
12011204

12021205
/// Extracts the underlying trait reference and own substs from this projection.

compiler/rustc_resolve/src/late/lifetimes.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
597597
}
598598
}
599599
hir::ItemKind::ImplTraitPlaceholder(..) => {
600-
// FIXME(RPITIT): We don't need to do anything here, right?
600+
// FIXME(RPITIT): We don't need to do anything special here, right?
601+
intravisit::walk_item(self, item);
601602
}
602603
hir::ItemKind::TyAlias(_, ref generics)
603604
| hir::ItemKind::Enum(_, ref generics)

compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1183,6 +1183,7 @@ symbols! {
11831183
require,
11841184
residual,
11851185
result,
1186+
return_position_impl_trait_in_trait,
11861187
rhs,
11871188
rintf32,
11881189
rintf64,

compiler/rustc_trait_selection/src/traits/project.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1465,6 +1465,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
14651465
obligation: &ProjectionTyObligation<'tcx>,
14661466
candidate_set: &mut ProjectionCandidateSet<'tcx>,
14671467
) {
1468+
// Can't assemble candidate from impl for RPITIT
1469+
if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
1470+
return;
1471+
}
1472+
14681473
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
14691474
// start out by selecting the predicate `T as TraitRef<...>`:
14701475
let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));

compiler/rustc_typeck/src/astconv/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -2638,8 +2638,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
26382638
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
26392639
}
26402640
}
2641-
hir::TyKind::ImplTraitInTrait(..) => {
2642-
span_bug!(ast_ty.span, "not yet implemented")
2641+
hir::TyKind::ImplTraitInTrait(item_id) => {
2642+
let def_id = item_id.def_id.to_def_id();
2643+
tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id))
26432644
}
26442645
hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
26452646
debug!(?qself, ?segment);

compiler/rustc_typeck/src/collect.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
16001600
// inherit the generics of the item.
16011601
Some(parent_id.to_def_id())
16021602
}
1603+
ItemKind::ImplTraitPlaceholder(_) => {
1604+
let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id();
1605+
assert_eq!(tcx.def_kind(parent_id), DefKind::AssocFn);
1606+
Some(parent_id)
1607+
}
16031608
_ => None,
16041609
},
16051610
_ => None,

compiler/rustc_typeck/src/collect/item_bounds.rs

+28
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,29 @@ fn opaque_type_bounds<'tcx>(
7474
})
7575
}
7676

77+
/// Opaque types don't inherit bounds from their parent: for return position
78+
/// impl trait it isn't possible to write a suitable predicate on the
79+
/// containing function and for type-alias impl trait we don't have a backwards
80+
/// compatibility issue.
81+
fn impl_trait_in_trait_item_bounds<'tcx>(
82+
tcx: TyCtxt<'tcx>,
83+
opaque_def_id: DefId,
84+
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
85+
span: Span,
86+
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
87+
ty::print::with_no_queries!({
88+
// FIXME(RPITIT): DRY-er code please
89+
let item_ty =
90+
tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
91+
92+
let icx = ItemCtxt::new(tcx, opaque_def_id);
93+
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
94+
// RPITITs are implicitly sized unless a `?Sized` bound is found
95+
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
96+
tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
97+
})
98+
}
99+
77100
pub(super) fn explicit_item_bounds(
78101
tcx: TyCtxt<'_>,
79102
def_id: DefId,
@@ -90,6 +113,11 @@ pub(super) fn explicit_item_bounds(
90113
span,
91114
..
92115
}) => opaque_type_bounds(tcx, def_id, bounds, *span),
116+
hir::Node::Item(hir::Item {
117+
kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }),
118+
span,
119+
..
120+
}) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span),
93121
_ => bug!("item_bounds called on {:?}", def_id),
94122
}
95123
}

0 commit comments

Comments
 (0)