Lower RPITIT to ImplTraitPlaceholder item
This commit is contained in:
parent
78b962a4f3
commit
d34cb98fb0
11 changed files with 99 additions and 8 deletions
|
@ -255,6 +255,8 @@ enum ImplTraitContext {
|
||||||
},
|
},
|
||||||
/// Impl trait in type aliases.
|
/// Impl trait in type aliases.
|
||||||
TypeAliasesOpaqueTy,
|
TypeAliasesOpaqueTy,
|
||||||
|
/// Return-position `impl Trait` in trait definition
|
||||||
|
InTrait,
|
||||||
/// `impl Trait` is not accepted in this position.
|
/// `impl Trait` is not accepted in this position.
|
||||||
Disallowed(ImplTraitPosition),
|
Disallowed(ImplTraitPosition),
|
||||||
}
|
}
|
||||||
|
@ -323,9 +325,17 @@ enum FnDeclKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FnDeclKind {
|
impl FnDeclKind {
|
||||||
fn impl_trait_return_allowed(&self) -> bool {
|
fn impl_trait_return_allowed(&self, tcx: TyCtxt<'_>) -> bool {
|
||||||
match self {
|
match self {
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => true,
|
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,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1346,6 +1356,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
&mut nested_itctx,
|
&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 => {
|
ImplTraitContext::Universal => {
|
||||||
let span = t.span;
|
let span = t.span;
|
||||||
let ident = Ident::from_str_and_span(&pprust::ty_to_string(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)
|
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
|
/// Registers a new opaque type with the proper `NodeId`s and
|
||||||
/// returns the lowered node-ID for the opaque type.
|
/// returns the lowered node-ID for the opaque type.
|
||||||
fn generate_opaque_type(
|
fn generate_opaque_type(
|
||||||
|
@ -1690,12 +1730,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
match decl.output {
|
match decl.output {
|
||||||
FnRetTy::Ty(ref ty) => {
|
FnRetTy::Ty(ref ty) => {
|
||||||
let mut context = match fn_node_id {
|
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);
|
let fn_def_id = self.local_def_id(fn_node_id);
|
||||||
ImplTraitContext::ReturnPositionOpaqueTy {
|
ImplTraitContext::ReturnPositionOpaqueTy {
|
||||||
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some(_) if kind.impl_trait_in_trait_allowed(self.tcx) => {
|
||||||
|
ImplTraitContext::InTrait
|
||||||
|
}
|
||||||
_ => ImplTraitContext::Disallowed(match kind {
|
_ => ImplTraitContext::Disallowed(match kind {
|
||||||
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
FnDeclKind::Fn | FnDeclKind::Inherent => {
|
||||||
unreachable!("fn should allow in-band lifetimes")
|
unreachable!("fn should allow in-band lifetimes")
|
||||||
|
|
|
@ -487,6 +487,8 @@ declare_features! (
|
||||||
(incomplete, repr128, "1.16.0", Some(56071), None),
|
(incomplete, repr128, "1.16.0", Some(56071), None),
|
||||||
/// Allows `repr(simd)` and importing the various simd intrinsics.
|
/// Allows `repr(simd)` and importing the various simd intrinsics.
|
||||||
(active, repr_simd, "1.4.0", Some(27731), None),
|
(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"`.
|
/// Allows `extern "rust-cold"`.
|
||||||
(active, rust_cold_cc, "1.63.0", Some(97544), None),
|
(active, rust_cold_cc, "1.63.0", Some(97544), None),
|
||||||
/// Allows the use of SIMD types in functions declared in `extern` blocks.
|
/// Allows the use of SIMD types in functions declared in `extern` blocks.
|
||||||
|
|
|
@ -105,6 +105,7 @@ impl Target {
|
||||||
DefKind::GlobalAsm => Target::GlobalAsm,
|
DefKind::GlobalAsm => Target::GlobalAsm,
|
||||||
DefKind::TyAlias => Target::TyAlias,
|
DefKind::TyAlias => Target::TyAlias,
|
||||||
DefKind::OpaqueTy => Target::OpaqueTy,
|
DefKind::OpaqueTy => Target::OpaqueTy,
|
||||||
|
DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder,
|
||||||
DefKind::Enum => Target::Enum,
|
DefKind::Enum => Target::Enum,
|
||||||
DefKind::Struct => Target::Struct,
|
DefKind::Struct => Target::Struct,
|
||||||
DefKind::Union => Target::Union,
|
DefKind::Union => Target::Union,
|
||||||
|
|
|
@ -2,6 +2,7 @@ use crate::traits::{ObligationCause, ObligationCauseCode};
|
||||||
use crate::ty::diagnostics::suggest_constraining_type_param;
|
use crate::ty::diagnostics::suggest_constraining_type_param;
|
||||||
use crate::ty::print::{FmtPrinter, Printer};
|
use crate::ty::print::{FmtPrinter, Printer};
|
||||||
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
|
use crate::ty::{self, BoundRegionKind, Region, Ty, TyCtxt};
|
||||||
|
use hir::def::DefKind;
|
||||||
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
|
use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
|
||||||
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
|
use rustc_errors::{pluralize, Diagnostic, MultiSpan};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
|
@ -538,7 +539,7 @@ impl<T> Trait<T> for X {
|
||||||
diag.span_label(p_span, "this type parameter");
|
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(
|
self.expected_projection(
|
||||||
diag,
|
diag,
|
||||||
proj_ty,
|
proj_ty,
|
||||||
|
@ -547,7 +548,7 @@ impl<T> Trait<T> for X {
|
||||||
cause.code(),
|
cause.code(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
(_, ty::Projection(proj_ty)) => {
|
(_, ty::Projection(proj_ty)) if self.def_kind(proj_ty.item_def_id) != DefKind::ImplTraitPlaceholder => {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"consider constraining the associated type `{}` to `{}`",
|
"consider constraining the associated type `{}` to `{}`",
|
||||||
values.found, values.expected,
|
values.found, values.expected,
|
||||||
|
|
|
@ -11,6 +11,7 @@ use crate::ty::{
|
||||||
TypeVisitor,
|
TypeVisitor,
|
||||||
};
|
};
|
||||||
use crate::ty::{List, ParamEnv};
|
use crate::ty::{List, ParamEnv};
|
||||||
|
use hir::def::DefKind;
|
||||||
use polonius_engine::Atom;
|
use polonius_engine::Atom;
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
|
@ -1196,7 +1197,9 @@ pub struct ProjectionTy<'tcx> {
|
||||||
|
|
||||||
impl<'tcx> ProjectionTy<'tcx> {
|
impl<'tcx> ProjectionTy<'tcx> {
|
||||||
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
|
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.
|
/// 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(..) => {
|
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::TyAlias(_, ref generics)
|
||||||
| hir::ItemKind::Enum(_, ref generics)
|
| hir::ItemKind::Enum(_, ref generics)
|
||||||
|
|
|
@ -1183,6 +1183,7 @@ symbols! {
|
||||||
require,
|
require,
|
||||||
residual,
|
residual,
|
||||||
result,
|
result,
|
||||||
|
return_position_impl_trait_in_trait,
|
||||||
rhs,
|
rhs,
|
||||||
rintf32,
|
rintf32,
|
||||||
rintf64,
|
rintf64,
|
||||||
|
|
|
@ -1465,6 +1465,11 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
obligation: &ProjectionTyObligation<'tcx>,
|
obligation: &ProjectionTyObligation<'tcx>,
|
||||||
candidate_set: &mut ProjectionCandidateSet<'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`,
|
// If we are resolving `<T as TraitRef<...>>::Item == Type`,
|
||||||
// start out by selecting the predicate `T as TraitRef<...>`:
|
// start out by selecting the predicate `T as TraitRef<...>`:
|
||||||
let poly_trait_ref = ty::Binder::dummy(obligation.predicate.trait_ref(selcx.tcx()));
|
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),
|
ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::TyKind::ImplTraitInTrait(..) => {
|
hir::TyKind::ImplTraitInTrait(item_id) => {
|
||||||
span_bug!(ast_ty.span, "not yet implemented")
|
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)) => {
|
hir::TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
|
||||||
debug!(?qself, ?segment);
|
debug!(?qself, ?segment);
|
||||||
|
|
|
@ -1600,6 +1600,11 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
|
||||||
// inherit the generics of the item.
|
// inherit the generics of the item.
|
||||||
Some(parent_id.to_def_id())
|
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,
|
||||||
},
|
},
|
||||||
_ => 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(
|
pub(super) fn explicit_item_bounds(
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -90,6 +113,11 @@ pub(super) fn explicit_item_bounds(
|
||||||
span,
|
span,
|
||||||
..
|
..
|
||||||
}) => opaque_type_bounds(tcx, def_id, 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),
|
_ => bug!("item_bounds called on {:?}", def_id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue