mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-28 02:57:37 +00:00
Lower RPITIT to ImplTraitPlaceholder item
This commit is contained in:
parent
78b962a4f3
commit
d34cb98fb0
@ -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")
|
||||
|
@ -487,6 +487,8 @@ declare_features! (
|
||||
(incomplete, repr128, "1.16.0", Some(56071), None),
|
||||
/// Allows `repr(simd)` and importing the various simd intrinsics.
|
||||
(active, repr_simd, "1.4.0", Some(27731), None),
|
||||
/// Allows return-position `impl Trait` in traits.
|
||||
(incomplete, return_position_impl_trait_in_trait, "CURRENT_RUSTC_VERSION", Some(91611), None),
|
||||
/// Allows `extern "rust-cold"`.
|
||||
(active, rust_cold_cc, "1.63.0", Some(97544), None),
|
||||
/// Allows the use of SIMD types in functions declared in `extern` blocks.
|
||||
|
@ -105,6 +105,7 @@ impl Target {
|
||||
DefKind::GlobalAsm => Target::GlobalAsm,
|
||||
DefKind::TyAlias => Target::TyAlias,
|
||||
DefKind::OpaqueTy => Target::OpaqueTy,
|
||||
DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder,
|
||||
DefKind::Enum => Target::Enum,
|
||||
DefKind::Struct => Target::Struct,
|
||||
DefKind::Union => Target::Union,
|
||||
|
@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||
use crate::ty::diagnostics::suggest_constraining_type_param;
|
||||
use crate::ty::print::{FmtPrinter, Printer};
|
||||
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
|
||||
use hir::def::DefKind;
|
||||
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
|
||||
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
@ -538,7 +539,7 @@ impl<T> Trait<T> for X {
|
||||
diag.span_label(p_span, "this type parameter");
|
||||
}
|
||||
}
|
||||
(ty::Projection(proj_ty), _) => {
|
||||
(ty::Projection(proj_ty), _) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
|
||||
self.expected_projection(
|
||||
diag,
|
||||
proj_ty,
|
||||
@ -547,7 +548,7 @@ impl<T> Trait<T> for X {
|
||||
cause.code(),
|
||||
);
|
||||
}
|
||||
(_, ty::Projection(proj_ty)) => {
|
||||
(_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
|
||||
let msg = format!(
|
||||
"consider constraining the associated type `{}` to `{}`",
|
||||
values.found, values.expected,
|
||||
|
@ -11,6 +11,7 @@ use crate::ty::{
|
||||
TypeVisitor,
|
||||
};
|
||||
use crate::ty::{List, ParamEnv};
|
||||
use hir::def::DefKind;
|
||||
use polonius_engine::Atom;
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> {
|
||||
|
||||
impl<'tcx> ProjectionTy<'tcx> {
|
||||
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
tcx.parent(self.item_def_id)
|
||||
let parent = tcx.parent(self.item_def_id);
|
||||
assert_eq!(tcx.def_kind(parent), DefKind::Trait);
|
||||
parent
|
||||
}
|
||||
|
||||
/// Extracts the underlying trait reference and own substs from this projection.
|
||||
|
@ -597,7 +597,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
hir::ItemKind::ImplTraitPlaceholder(..) => {
|
||||
// FIXME(RPITIT): We don't need to do anything here, right?
|
||||
// FIXME(RPITIT): We don't need to do anything special here, right?
|
||||
intravisit::walk_item(self, item);
|
||||
}
|
||||
hir::ItemKind::TyAlias(_, ref generics)
|
||||
| hir::ItemKind::Enum(_, ref generics)
|
||||
|
@ -1183,6 +1183,7 @@ symbols! {
|
||||
require,
|
||||
residual,
|
||||
result,
|
||||
return_position_impl_trait_in_trait,
|
||||
rhs,
|
||||
rintf32,
|
||||
rintf64,
|
||||
|
@ -1465,6 +1465,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||
obligation: &ProjectionTyObligation<'tcx>,
|
||||
candidate_set: &mut ProjectionCandidateSet<'tcx>,
|
||||
) {
|
||||
// Can't assemble candidate from impl for RPITIT
|
||||
if selcx.tcx().def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
||||
// start out by selecting the predicate `T as TraitRef<...>`:
|
||||
let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
|
||||
|
@ -2638,8 +2638,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
||||
}
|
||||
}
|
||||
hir::TyKind::ImplTraitInTrait(..) => {
|
||||
span_bug!(ast_ty.span, "not yet implemented")
|
||||
hir::TyKind::ImplTraitInTrait(item_id) => {
|
||||
let def_id = item_id.def_id.to_def_id();
|
||||
tcx.mk_projection(def_id, InternalSubsts::identity_for_item(tcx, def_id))
|
||||
}
|
||||
hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
|
||||
debug!(?qself, ?segment);
|
||||
|
@ -1600,6 +1600,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||
// inherit the generics of the item.
|
||||
Some(parent_id.to_def_id())
|
||||
}
|
||||
ItemKind::ImplTraitPlaceholder(_) => {
|
||||
let parent_id = tcx.hir().get_parent_item(hir_id).to_def_id();
|
||||
assert_eq!(tcx.def_kind(parent_id), DefKind::AssocFn);
|
||||
Some(parent_id)
|
||||
}
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
|
@ -74,6 +74,29 @@ fn opaque_type_bounds<'tcx>(
|
||||
})
|
||||
}
|
||||
|
||||
/// Opaque types don't inherit bounds from their parent: for return position
|
||||
/// impl trait it isn't possible to write a suitable predicate on the
|
||||
/// containing function and for type-alias impl trait we don't have a backwards
|
||||
/// compatibility issue.
|
||||
fn impl_trait_in_trait_item_bounds<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
opaque_def_id: DefId,
|
||||
ast_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
span: Span,
|
||||
) -> &'tcx [(ty::Predicate<'tcx>, Span)] {
|
||||
ty::print::with_no_queries!({
|
||||
// FIXME(RPITIT): DRY-er code please
|
||||
let item_ty =
|
||||
tcx.mk_projection(opaque_def_id, InternalSubsts::identity_for_item(tcx, opaque_def_id));
|
||||
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = <dyn AstConv<'_>>::compute_bounds(&icx, item_ty, ast_bounds);
|
||||
// RPITITs are implicitly sized unless a `?Sized` bound is found
|
||||
<dyn AstConv<'_>>::add_implicitly_sized(&icx, &mut bounds, ast_bounds, None, span);
|
||||
tcx.arena.alloc_from_iter(bounds.predicates(tcx, item_ty))
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn explicit_item_bounds(
|
||||
tcx: TyCtxt<'_>,
|
||||
def_id: DefId,
|
||||
@ -90,6 +113,11 @@ pub(super) fn explicit_item_bounds(
|
||||
span,
|
||||
..
|
||||
}) => opaque_type_bounds(tcx, def_id, bounds, *span),
|
||||
hir::Node::Item(hir::Item {
|
||||
kind: hir::ItemKind::ImplTraitPlaceholder(hir::ImplTraitPlaceholder { bounds }),
|
||||
span,
|
||||
..
|
||||
}) => impl_trait_in_trait_item_bounds(tcx, def_id, bounds, *span),
|
||||
_ => bug!("item_bounds called on {:?}", def_id),
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user