mirror of https://github.com/rust-lang/rust.git
Uplift binder
This commit is contained in:
parent
e8fbd99128
commit
28ce588321
|
@ -118,6 +118,15 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::FnSig<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: rustc_type_ir::Interner, T> IntoDiagArg for rustc_type_ir::Binder<I, T>
|
||||
where
|
||||
T: IntoDiagArg,
|
||||
{
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.skip_binder().into_diag_arg()
|
||||
}
|
||||
}
|
||||
|
||||
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||
|
||||
impl IntoDiagArg for bool {
|
||||
|
|
|
@ -18,7 +18,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
|
|||
use rustc_infer::traits::FulfillmentError;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::query::Key;
|
||||
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
||||
use rustc_middle::ty::print::{PrintPolyTraitRefExt as _, PrintTraitRefExt as _};
|
||||
use rustc_middle::ty::GenericParamDefKind;
|
||||
use rustc_middle::ty::{self, suggest_constraining_type_param};
|
||||
use rustc_middle::ty::{AdtDef, Ty, TyCtxt, TypeVisitableExt};
|
||||
|
|
|
@ -40,6 +40,7 @@ use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
|
|||
use rustc_infer::traits::ObligationCause;
|
||||
use rustc_middle::middle::stability::AllowUnstable;
|
||||
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
|
||||
use rustc_middle::ty::print::PrintPolyTraitRefExt as _;
|
||||
use rustc_middle::ty::{
|
||||
self, Const, GenericArgKind, GenericArgsRef, GenericParamDefKind, ParamEnv, Ty, TyCtxt,
|
||||
TypeVisitableExt,
|
||||
|
|
|
@ -115,18 +115,11 @@ impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E>
|
||||
for ty::Binder<'tcx, ty::PredicateKind<'tcx>>
|
||||
{
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.bound_vars().encode(e);
|
||||
encode_with_shorthand(e, &self.skip_binder(), TyEncoder::predicate_shorthands);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Predicate<'tcx> {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.kind().encode(e);
|
||||
let kind = self.kind();
|
||||
kind.bound_vars().encode(e);
|
||||
encode_with_shorthand(e, &kind.skip_binder(), TyEncoder::predicate_shorthands);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,13 +226,11 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for Ty<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D>
|
||||
for ty::Binder<'tcx, ty::PredicateKind<'tcx>>
|
||||
{
|
||||
fn decode(decoder: &mut D) -> ty::Binder<'tcx, ty::PredicateKind<'tcx>> {
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> {
|
||||
fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
|
||||
let bound_vars = Decodable::decode(decoder);
|
||||
// Handle shorthands first, if we have a usize > 0x80.
|
||||
ty::Binder::bind_with_vars(
|
||||
let predicate_kind = ty::Binder::bind_with_vars(
|
||||
if decoder.positioned_at_shorthand() {
|
||||
let pos = decoder.read_usize();
|
||||
assert!(pos >= SHORTHAND_OFFSET);
|
||||
|
@ -250,13 +241,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D>
|
|||
<ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
|
||||
},
|
||||
bound_vars,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Predicate<'tcx> {
|
||||
fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
|
||||
let predicate_kind = Decodable::decode(decoder);
|
||||
);
|
||||
decoder.interner().mk_predicate(predicate_kind)
|
||||
}
|
||||
}
|
||||
|
@ -599,32 +584,3 @@ macro_rules! implement_ty_decoder {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_binder_encode_decode {
|
||||
($($t:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for ty::Binder<'tcx, $t> {
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.bound_vars().encode(e);
|
||||
self.as_ref().skip_binder().encode(e);
|
||||
}
|
||||
}
|
||||
impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for ty::Binder<'tcx, $t> {
|
||||
fn decode(decoder: &mut D) -> Self {
|
||||
let bound_vars = Decodable::decode(decoder);
|
||||
ty::Binder::bind_with_vars(Decodable::decode(decoder), bound_vars)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_binder_encode_decode! {
|
||||
&'tcx ty::List<Ty<'tcx>>,
|
||||
ty::FnSig<'tcx>,
|
||||
ty::Predicate<'tcx>,
|
||||
ty::TraitPredicate<'tcx>,
|
||||
ty::ExistentialPredicate<'tcx>,
|
||||
ty::TraitRef<'tcx>,
|
||||
ty::ExistentialTraitRef<'tcx>,
|
||||
}
|
||||
|
|
|
@ -31,8 +31,7 @@ use crate::ty::{
|
|||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
|
||||
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
|
||||
PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, PredicatePolarity,
|
||||
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, TypeVisitable,
|
||||
Visibility,
|
||||
Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, Visibility,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||
use rustc_ast::{self as ast, attr};
|
||||
|
@ -96,9 +95,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
type GenericArg = ty::GenericArg<'tcx>;
|
||||
type Term = ty::Term<'tcx>;
|
||||
|
||||
type Binder<T: TypeVisitable<TyCtxt<'tcx>>> = Binder<'tcx, T>;
|
||||
type BoundVars = &'tcx List<ty::BoundVariableKind>;
|
||||
type BoundVar = ty::BoundVariableKind;
|
||||
type BoundVarKinds = &'tcx List<ty::BoundVariableKind>;
|
||||
type BoundVarKind = ty::BoundVariableKind;
|
||||
|
||||
type CanonicalVars = CanonicalVarInfos<'tcx>;
|
||||
type PredefinedOpaques = solve::PredefinedOpaques<'tcx>;
|
||||
|
@ -138,6 +136,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
|||
|
||||
type ParamEnv = ty::ParamEnv<'tcx>;
|
||||
type Predicate = Predicate<'tcx>;
|
||||
type Clause = Clause<'tcx>;
|
||||
type TraitPredicate = ty::TraitPredicate<'tcx>;
|
||||
type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>;
|
||||
type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>;
|
||||
|
@ -245,6 +244,10 @@ impl<'tcx> rustc_type_ir::inherent::Abi<TyCtxt<'tcx>> for abi::Abi {
|
|||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Safety<TyCtxt<'tcx>> for hir::Safety {
|
||||
fn is_safe(self) -> bool {
|
||||
matches!(self, hir::Safety::Safe)
|
||||
}
|
||||
|
||||
fn prefix_str(self) -> &'static str {
|
||||
self.prefix_str()
|
||||
}
|
||||
|
|
|
@ -51,6 +51,14 @@ impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArg
|
|||
fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
|
||||
GenericArgs::identity_for_item(tcx, def_id)
|
||||
}
|
||||
|
||||
fn extend_with_error(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
def_id: DefId,
|
||||
original_args: &[ty::GenericArg<'tcx>],
|
||||
) -> ty::GenericArgsRef<'tcx> {
|
||||
ty::GenericArgs::extend_with_error(tcx, def_id, original_args)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> {
|
||||
|
|
|
@ -8,8 +8,8 @@ use rustc_type_ir as ir;
|
|||
use std::cmp::Ordering;
|
||||
|
||||
use crate::ty::{
|
||||
self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags,
|
||||
Upcast, UpcastFrom, WithCachedTypeInfo,
|
||||
self, DebruijnIndex, EarlyBinder, PredicatePolarity, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom,
|
||||
WithCachedTypeInfo,
|
||||
};
|
||||
|
||||
pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
|
||||
|
@ -155,6 +155,8 @@ pub struct Clause<'tcx>(
|
|||
pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
|
||||
);
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {}
|
||||
|
||||
impl<'tcx> Clause<'tcx> {
|
||||
pub fn as_predicate(self) -> Predicate<'tcx> {
|
||||
Predicate(self.0)
|
||||
|
@ -231,34 +233,6 @@ impl<'tcx> ExistentialPredicate<'tcx> {
|
|||
|
||||
pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyExistentialPredicate<'tcx> {
|
||||
/// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
|
||||
/// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
|
||||
/// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
|
||||
pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::Clause<'tcx> {
|
||||
match self.skip_binder() {
|
||||
ExistentialPredicate::Trait(tr) => {
|
||||
self.rebind(tr).with_self_ty(tcx, self_ty).upcast(tcx)
|
||||
}
|
||||
ExistentialPredicate::Projection(p) => {
|
||||
self.rebind(p.with_self_ty(tcx, self_ty)).upcast(tcx)
|
||||
}
|
||||
ExistentialPredicate::AutoTrait(did) => {
|
||||
let generics = tcx.generics_of(did);
|
||||
let trait_ref = if generics.own_params.len() == 1 {
|
||||
ty::TraitRef::new(tcx, did, [self_ty])
|
||||
} else {
|
||||
// If this is an ill-formed auto trait, then synthesize
|
||||
// new error args for the missing generics.
|
||||
let err_args = ty::GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]);
|
||||
ty::TraitRef::new(tcx, did, err_args)
|
||||
};
|
||||
self.rebind(trait_ref).upcast(tcx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
/// Returns the "principal `DefId`" of this set of existential predicates.
|
||||
///
|
||||
|
@ -322,49 +296,9 @@ impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
|||
}
|
||||
|
||||
pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyTraitRef<'tcx> {
|
||||
pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||
self.map_bound_ref(|tr| tr.self_ty())
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> DefId {
|
||||
self.skip_binder().def_id
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
||||
pub fn def_id(&self) -> DefId {
|
||||
self.skip_binder().def_id
|
||||
}
|
||||
|
||||
/// Object types don't have a self type specified. Therefore, when
|
||||
/// we convert the principal trait-ref into a normal trait-ref,
|
||||
/// you must give *some* self type. A common choice is `mk_err()`
|
||||
/// or some placeholder type.
|
||||
pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTraitRef<'tcx> {
|
||||
self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty))
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyExistentialProjection<'tcx> {
|
||||
pub fn with_self_ty(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
) -> ty::PolyProjectionPredicate<'tcx> {
|
||||
self.map_bound(|p| p.with_self_ty(tcx, self_ty))
|
||||
}
|
||||
|
||||
pub fn item_def_id(&self) -> DefId {
|
||||
self.skip_binder().def_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clause<'tcx> {
|
||||
/// Performs a instantiation suitable for going from a
|
||||
/// poly-trait-ref to supertraits that must hold if that
|
||||
|
@ -473,22 +407,6 @@ impl<'tcx> Clause<'tcx> {
|
|||
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
pub fn def_id(self) -> DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
self.skip_binder().def_id()
|
||||
}
|
||||
|
||||
pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||
self.map_bound(|trait_ref| trait_ref.self_ty())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn polarity(self) -> PredicatePolarity {
|
||||
self.skip_binder().polarity
|
||||
}
|
||||
}
|
||||
|
||||
/// `A: B`
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
|
@ -497,47 +415,10 @@ pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty:
|
|||
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
|
||||
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
|
||||
pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
|
||||
|
||||
pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
|
||||
|
||||
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
|
||||
|
||||
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
/// Returns the `DefId` of the trait of the associated item being projected.
|
||||
#[inline]
|
||||
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.skip_binder().projection_term.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
/// Get the [PolyTraitRef] required for this projection to be well formed.
|
||||
/// Note that for generic associated types the predicates of the associated
|
||||
/// type also need to be checked.
|
||||
#[inline]
|
||||
pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
|
||||
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
|
||||
// `self.0.trait_ref` is permitted to have escaping regions.
|
||||
// This is because here `self` has a `Binder` and so does our
|
||||
// return value, so we are preserving the number of binding
|
||||
// levels.
|
||||
self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx))
|
||||
}
|
||||
|
||||
pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
|
||||
self.map_bound(|predicate| predicate.term)
|
||||
}
|
||||
|
||||
/// The `DefId` of the `TraitItem` for the associated type.
|
||||
///
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
|
||||
pub fn projection_def_id(&self) -> DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
self.skip_binder().projection_term.def_id
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToPolyTraitRef<'tcx> {
|
||||
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
|
||||
}
|
||||
|
@ -554,8 +435,8 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
tcx.mk_predicate(from)
|
||||
}
|
||||
}
|
||||
|
@ -566,8 +447,8 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
|
||||
}
|
||||
}
|
||||
|
@ -580,12 +461,12 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
|
|||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
|
||||
fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(from))).expect_clause()
|
||||
tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
|
||||
fn upcast_from(from: Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
|
||||
fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
|
||||
}
|
||||
}
|
||||
|
@ -609,22 +490,22 @@ impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
|
||||
fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
|
||||
pred.upcast(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
|
||||
fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
|
||||
fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
|
||||
let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
|
||||
pred.upcast(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> {
|
||||
fn upcast_from(from: Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self {
|
||||
impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> {
|
||||
fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self {
|
||||
from.map_bound(|trait_ref| TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: PredicatePolarity::Positive,
|
||||
|
|
|
@ -2934,12 +2934,13 @@ impl<'tcx> ty::TraitRef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[extension(pub trait PrintPolyTraitRefExt<'tcx>)]
|
||||
impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
|
||||
pub fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
|
||||
fn print_only_trait_path(self) -> ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>> {
|
||||
self.map_bound(|tr| tr.print_only_trait_path())
|
||||
}
|
||||
|
||||
pub fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> {
|
||||
fn print_trait_sugared(self) -> ty::Binder<'tcx, TraitRefPrintSugared<'tcx>> {
|
||||
self.map_bound(|tr| tr.print_trait_sugared())
|
||||
}
|
||||
}
|
||||
|
@ -2960,8 +2961,9 @@ impl<'tcx> ty::TraitPredicate<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
#[extension(pub trait PrintPolyTraitPredicateExt<'tcx>)]
|
||||
impl<'tcx> ty::PolyTraitPredicate<'tcx> {
|
||||
pub fn print_modifiers_and_trait_path(
|
||||
fn print_modifiers_and_trait_path(
|
||||
self,
|
||||
) -> ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>> {
|
||||
self.map_bound(TraitPredPrintModifiersAndPath)
|
||||
|
@ -3016,17 +3018,6 @@ forward_display_to_print! {
|
|||
&'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
|
||||
ty::Const<'tcx>,
|
||||
|
||||
// HACK(eddyb) these are exhaustive instead of generic,
|
||||
// because `for<'tcx>` isn't possible yet.
|
||||
ty::PolyExistentialProjection<'tcx>,
|
||||
ty::PolyExistentialTraitRef<'tcx>,
|
||||
ty::Binder<'tcx, ty::TraitRef<'tcx>>,
|
||||
ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
|
||||
ty::Binder<'tcx, TraitRefPrintSugared<'tcx>>,
|
||||
ty::Binder<'tcx, ty::FnSig<'tcx>>,
|
||||
ty::Binder<'tcx, ty::TraitPredicate<'tcx>>,
|
||||
ty::Binder<'tcx, TraitPredPrintModifiersAndPath<'tcx>>,
|
||||
ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
|
||||
ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>,
|
||||
ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
|
||||
}
|
||||
|
|
|
@ -384,6 +384,10 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundRegion {
|
|||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
fn assert_eq(self, var: ty::BoundVariableKind) {
|
||||
assert_eq!(self.kind, var.expect_region())
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for BoundRegion {
|
||||
|
|
|
@ -387,38 +387,6 @@ impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
folder.try_fold_binder(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||
fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
visitor.visit_binder(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||
fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
self.try_map_bound(|ty| ty.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeSuperVisitable<TyCtxt<'tcx>>
|
||||
for ty::Binder<'tcx, T>
|
||||
{
|
||||
fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.as_ref().skip_binder().visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
|
||||
self,
|
||||
|
|
|
@ -3,17 +3,16 @@
|
|||
#![allow(rustc::usage_of_ty_tykind)]
|
||||
|
||||
use crate::infer::canonical::Canonical;
|
||||
use crate::ty::visit::ValidateBoundVars;
|
||||
use crate::ty::InferTy::*;
|
||||
use crate::ty::{
|
||||
self, AdtDef, BoundRegionKind, Discr, Region, Ty, TyCtxt, TypeFlags, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt, TypeVisitor,
|
||||
TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||
use crate::ty::{List, ParamEnv};
|
||||
use hir::def::{CtorKind, DefKind};
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan};
|
||||
use rustc_errors::{ErrorGuaranteed, MultiSpan};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::LangItem;
|
||||
|
@ -21,11 +20,11 @@ use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable};
|
|||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT};
|
||||
use rustc_target::spec::abi::{self, Abi};
|
||||
use rustc_target::spec::abi;
|
||||
use std::assert_matches::debug_assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::iter;
|
||||
use std::ops::{ControlFlow, Deref, Range};
|
||||
use std::ops::{ControlFlow, Range};
|
||||
use ty::util::IntTypeExt;
|
||||
|
||||
use rustc_type_ir::TyKind::*;
|
||||
|
@ -40,6 +39,7 @@ pub type TyKind<'tcx> = ir::TyKind<TyCtxt<'tcx>>;
|
|||
pub type TypeAndMut<'tcx> = ir::TypeAndMut<TyCtxt<'tcx>>;
|
||||
pub type AliasTy<'tcx> = ir::AliasTy<TyCtxt<'tcx>>;
|
||||
pub type FnSig<'tcx> = ir::FnSig<TyCtxt<'tcx>>;
|
||||
pub type Binder<'tcx, T> = ir::Binder<TyCtxt<'tcx>, T>;
|
||||
|
||||
pub trait Article {
|
||||
fn article(&self) -> &'static str;
|
||||
|
@ -373,7 +373,7 @@ impl<'tcx> CoroutineClosureArgs<'tcx> {
|
|||
self.split().signature_parts_ty
|
||||
}
|
||||
|
||||
pub fn coroutine_closure_sig(self) -> ty::Binder<'tcx, CoroutineClosureSignature<'tcx>> {
|
||||
pub fn coroutine_closure_sig(self) -> Binder<'tcx, CoroutineClosureSignature<'tcx>> {
|
||||
let interior = self.coroutine_witness_ty();
|
||||
let ty::FnPtr(sig) = self.signature_parts_ty().kind() else { bug!() };
|
||||
sig.map_bound(|sig| {
|
||||
|
@ -898,203 +898,6 @@ impl BoundVariableKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
|
||||
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
|
||||
/// (which would be represented by the type `PolyTraitRef ==
|
||||
/// Binder<'tcx, TraitRef>`). Note that when we instantiate,
|
||||
/// erase, or otherwise "discharge" these bound vars, we change the
|
||||
/// type from `Binder<'tcx, T>` to just `T` (see
|
||||
/// e.g., `liberate_late_bound_regions`).
|
||||
///
|
||||
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
#[derive(HashStable, Lift)]
|
||||
pub struct Binder<'tcx, T> {
|
||||
value: T,
|
||||
bound_vars: &'tcx List<BoundVariableKind>,
|
||||
}
|
||||
|
||||
impl<'tcx, T> Binder<'tcx, T>
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
/// Wraps `value` in a binder, asserting that `value` does not
|
||||
/// contain any bound vars that would be bound by the
|
||||
/// binder. This is commonly used to 'inject' a value T into a
|
||||
/// different binding level.
|
||||
#[track_caller]
|
||||
pub fn dummy(value: T) -> Binder<'tcx, T> {
|
||||
assert!(
|
||||
!value.has_escaping_bound_vars(),
|
||||
"`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
|
||||
);
|
||||
Binder { value, bound_vars: ty::List::empty() }
|
||||
}
|
||||
|
||||
pub fn bind_with_vars(value: T, bound_vars: &'tcx List<BoundVariableKind>) -> Binder<'tcx, T> {
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(bound_vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder { value, bound_vars }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> rustc_type_ir::inherent::BoundVars<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
|
||||
fn bound_vars(&self) -> &'tcx List<ty::BoundVariableKind> {
|
||||
self.bound_vars
|
||||
}
|
||||
|
||||
fn has_no_bound_vars(&self) -> bool {
|
||||
self.bound_vars.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Binder<'tcx, T> {
|
||||
/// Skips the binder and returns the "bound" value. This is a
|
||||
/// risky thing to do because it's easy to get confused about
|
||||
/// De Bruijn indices and the like. It is usually better to
|
||||
/// discharge the binder using `no_bound_vars` or
|
||||
/// `instantiate_bound_regions` or something like
|
||||
/// that. `skip_binder` is only valid when you are either
|
||||
/// extracting data that has nothing to do with bound vars, you
|
||||
/// are doing some sort of test that does not involve bound
|
||||
/// regions, or you are being very careful about your depth
|
||||
/// accounting.
|
||||
///
|
||||
/// Some examples where `skip_binder` is reasonable:
|
||||
///
|
||||
/// - extracting the `DefId` from a PolyTraitRef;
|
||||
/// - comparing the self type of a PolyTraitRef to see if it is equal to
|
||||
/// a type parameter `X`, since the type `X` does not reference any regions
|
||||
pub fn skip_binder(self) -> T {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn bound_vars(&self) -> &'tcx List<BoundVariableKind> {
|
||||
self.bound_vars
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> Binder<'tcx, &T> {
|
||||
Binder { value: &self.value, bound_vars: self.bound_vars }
|
||||
}
|
||||
|
||||
pub fn as_deref(&self) -> Binder<'tcx, &T::Target>
|
||||
where
|
||||
T: Deref,
|
||||
{
|
||||
Binder { value: &self.value, bound_vars: self.bound_vars }
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U: TypeVisitable<TyCtxt<'tcx>>>(&self, f: F) -> Binder<'tcx, U>
|
||||
where
|
||||
F: FnOnce(&T) -> U,
|
||||
{
|
||||
self.as_ref().map_bound(f)
|
||||
}
|
||||
|
||||
pub fn map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>>(self, f: F) -> Binder<'tcx, U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let value = f(value);
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(bound_vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder { value, bound_vars }
|
||||
}
|
||||
|
||||
pub fn try_map_bound<F, U: TypeVisitable<TyCtxt<'tcx>>, E>(
|
||||
self,
|
||||
f: F,
|
||||
) -> Result<Binder<'tcx, U>, E>
|
||||
where
|
||||
F: FnOnce(T) -> Result<U, E>,
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let value = f(value)?;
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(bound_vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Ok(Binder { value, bound_vars })
|
||||
}
|
||||
|
||||
/// Wraps a `value` in a binder, using the same bound variables as the
|
||||
/// current `Binder`. This should not be used if the new value *changes*
|
||||
/// the bound variables. Note: the (old or new) value itself does not
|
||||
/// necessarily need to *name* all the bound variables.
|
||||
///
|
||||
/// This currently doesn't do anything different than `bind`, because we
|
||||
/// don't actually track bound vars. However, semantically, it is different
|
||||
/// because bound vars aren't allowed to change here, whereas they are
|
||||
/// in `bind`. This may be (debug) asserted in the future.
|
||||
pub fn rebind<U>(&self, value: U) -> Binder<'tcx, U>
|
||||
where
|
||||
U: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
Binder::bind_with_vars(value, self.bound_vars)
|
||||
}
|
||||
|
||||
/// Unwraps and returns the value within, but only if it contains
|
||||
/// no bound vars at all. (In other words, if this binder --
|
||||
/// and indeed any enclosing binder -- doesn't bind anything at
|
||||
/// all.) Otherwise, returns `None`.
|
||||
///
|
||||
/// (One could imagine having a method that just unwraps a single
|
||||
/// binder, but permits late-bound vars bound by enclosing
|
||||
/// binders, but that would require adjusting the debruijn
|
||||
/// indices, and given the shallow binding structure we often use,
|
||||
/// would not be that useful.)
|
||||
pub fn no_bound_vars(self) -> Option<T>
|
||||
where
|
||||
T: TypeVisitable<TyCtxt<'tcx>>,
|
||||
{
|
||||
// `self.value` is equivalent to `self.skip_binder()`
|
||||
if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
|
||||
}
|
||||
|
||||
/// Splits the contents into two things that share the same binder
|
||||
/// level as the original, returning two distinct binders.
|
||||
///
|
||||
/// `f` should consider bound regions at depth 1 to be free, and
|
||||
/// anything it produces with bound regions at depth 1 will be
|
||||
/// bound in the resulting return values.
|
||||
pub fn split<U, V, F>(self, f: F) -> (Binder<'tcx, U>, Binder<'tcx, V>)
|
||||
where
|
||||
F: FnOnce(T) -> (U, V),
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let (u, v) = f(value);
|
||||
(Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> Binder<'tcx, Option<T>> {
|
||||
pub fn transpose(self) -> Option<Binder<'tcx, T>> {
|
||||
let Binder { value, bound_vars } = self;
|
||||
value.map(|value| Binder { value, bound_vars })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
|
||||
pub fn iter(self) -> impl Iterator<Item = ty::Binder<'tcx, T::Item>> {
|
||||
let Binder { value, bound_vars } = self;
|
||||
value.into_iter().map(|value| Binder { value, bound_vars })
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx, T> IntoDiagArg for Binder<'tcx, T>
|
||||
where
|
||||
T: IntoDiagArg,
|
||||
{
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.value.into_diag_arg()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
|
||||
pub struct GenSig<'tcx> {
|
||||
pub resume_ty: Ty<'tcx>,
|
||||
|
@ -1103,48 +906,6 @@ pub struct GenSig<'tcx> {
|
|||
}
|
||||
|
||||
pub type PolyFnSig<'tcx> = Binder<'tcx, FnSig<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyFnSig<'tcx> {
|
||||
#[inline]
|
||||
pub fn inputs(&self) -> Binder<'tcx, &'tcx [Ty<'tcx>]> {
|
||||
self.map_bound_ref(|fn_sig| fn_sig.inputs())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||
self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
|
||||
}
|
||||
|
||||
pub fn inputs_and_output(&self) -> ty::Binder<'tcx, &'tcx List<Ty<'tcx>>> {
|
||||
self.map_bound_ref(|fn_sig| fn_sig.inputs_and_output)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn output(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||
self.map_bound_ref(|fn_sig| fn_sig.output())
|
||||
}
|
||||
|
||||
pub fn c_variadic(&self) -> bool {
|
||||
self.skip_binder().c_variadic
|
||||
}
|
||||
|
||||
pub fn safety(&self) -> hir::Safety {
|
||||
self.skip_binder().safety
|
||||
}
|
||||
|
||||
pub fn abi(&self) -> abi::Abi {
|
||||
self.skip_binder().abi
|
||||
}
|
||||
|
||||
pub fn is_fn_trait_compatible(&self) -> bool {
|
||||
matches!(
|
||||
self.skip_binder(),
|
||||
ty::FnSig { safety: rustc_hir::Safety::Safe, abi: Abi::Rust, c_variadic: false, .. }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub type CanonicalPolyFnSig<'tcx> = Canonical<'tcx, Binder<'tcx, FnSig<'tcx>>>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
|
@ -1203,6 +964,10 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike<TyCtxt<'tcx>> for BoundTy {
|
|||
fn var(self) -> BoundVar {
|
||||
self.var
|
||||
}
|
||||
|
||||
fn assert_eq(self, var: ty::BoundVariableKind) {
|
||||
assert_eq!(self.kind, var.expect_ty())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
|
@ -2001,7 +1766,7 @@ impl<'tcx> Ty<'tcx> {
|
|||
FnPtr(f) => *f,
|
||||
Error(_) => {
|
||||
// ignore errors (#54954)
|
||||
ty::Binder::dummy(ty::FnSig {
|
||||
Binder::dummy(ty::FnSig {
|
||||
inputs_and_output: ty::List::empty(),
|
||||
c_variadic: false,
|
||||
safety: hir::Safety::Safe,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use crate::ty::{self, Binder, Ty, TyCtxt, TypeFlags};
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
use rustc_type_ir::fold::TypeFoldable;
|
||||
use std::ops::ControlFlow;
|
||||
|
||||
|
@ -145,103 +144,6 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ValidateBoundVars<'tcx> {
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
binder_index: ty::DebruijnIndex,
|
||||
// We may encounter the same variable at different levels of binding, so
|
||||
// this can't just be `Ty`
|
||||
visited: SsoHashSet<(ty::DebruijnIndex, Ty<'tcx>)>,
|
||||
}
|
||||
|
||||
impl<'tcx> ValidateBoundVars<'tcx> {
|
||||
pub fn new(bound_vars: &'tcx ty::List<ty::BoundVariableKind>) -> Self {
|
||||
ValidateBoundVars {
|
||||
bound_vars,
|
||||
binder_index: ty::INNERMOST,
|
||||
visited: SsoHashSet::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ValidateBoundVars<'tcx> {
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
|
||||
&mut self,
|
||||
t: &Binder<'tcx, T>,
|
||||
) -> Self::Result {
|
||||
self.binder_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
|
||||
if t.outer_exclusive_binder() < self.binder_index
|
||||
|| !self.visited.insert((self.binder_index, t))
|
||||
{
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
match *t.kind() {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
if self.bound_vars.len() <= bound_ty.var.as_usize() {
|
||||
bug!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
|
||||
}
|
||||
let list_var = self.bound_vars[bound_ty.var.as_usize()];
|
||||
match list_var {
|
||||
ty::BoundVariableKind::Ty(kind) => {
|
||||
if kind != bound_ty.kind {
|
||||
bug!(
|
||||
"Mismatched type kinds: {:?} doesn't var in list {:?}",
|
||||
bound_ty.kind,
|
||||
list_var
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
bug!("Mismatched bound variable kinds! Expected type, found {:?}", list_var)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
|
||||
match *r {
|
||||
ty::ReBound(index, br) if index == self.binder_index => {
|
||||
if self.bound_vars.len() <= br.var.as_usize() {
|
||||
bug!("Not enough bound vars: {:?} not found in {:?}", br, self.bound_vars);
|
||||
}
|
||||
let list_var = self.bound_vars[br.var.as_usize()];
|
||||
match list_var {
|
||||
ty::BoundVariableKind::Region(kind) => {
|
||||
if kind != br.kind {
|
||||
bug!(
|
||||
"Mismatched region kinds: {:?} doesn't match var ({:?}) in list ({:?})",
|
||||
br.kind,
|
||||
list_var,
|
||||
self.bound_vars
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => bug!(
|
||||
"Mismatched bound variable kinds! Expected region, found {:?}",
|
||||
list_var
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Collects all the late-bound regions at the innermost binding level
|
||||
/// into a hash set.
|
||||
struct LateBoundRegionsCollector {
|
||||
|
|
|
@ -217,10 +217,9 @@ impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I>
|
|||
self.infcx.interner()
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
|
||||
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
|
||||
where
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
self.binder_index.shift_in(1);
|
||||
let t = t.super_fold_with(self);
|
||||
|
@ -455,10 +454,9 @@ impl<I: Interner> TypeFolder<I> for RegionsToStatic<I> {
|
|||
self.interner
|
||||
}
|
||||
|
||||
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
|
||||
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
|
||||
where
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
self.binder.shift_in(1);
|
||||
let t = t.super_fold_with(self);
|
||||
|
|
|
@ -47,7 +47,8 @@ use crate::infer::InferCtxtExt as _;
|
|||
use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt;
|
||||
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
|
||||
use rustc_middle::ty::print::{
|
||||
with_forced_trimmed_paths, with_no_trimmed_paths, PrintTraitPredicateExt as _,
|
||||
with_forced_trimmed_paths, with_no_trimmed_paths, PrintPolyTraitPredicateExt as _,
|
||||
PrintTraitPredicateExt as _,
|
||||
};
|
||||
|
||||
use itertools::EitherOrBoth;
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops::{ControlFlow, Deref};
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::HashStable_NoContext;
|
||||
use rustc_serialize::Decodable;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
|
||||
use crate::inherent::*;
|
||||
use crate::lift::Lift;
|
||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
use crate::{self as ty, Interner, SsoHashSet};
|
||||
|
||||
/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
|
||||
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
|
||||
/// (which would be represented by the type `PolyTraitRef ==
|
||||
/// Binder<I, TraitRef>`). Note that when we instantiate,
|
||||
/// erase, or otherwise "discharge" these bound vars, we change the
|
||||
/// type from `Binder<I, T>` to just `T` (see
|
||||
/// e.g., `liberate_late_bound_regions`).
|
||||
///
|
||||
/// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = "T: Clone"),
|
||||
Copy(bound = "T: Copy"),
|
||||
Hash(bound = "T: Hash"),
|
||||
PartialEq(bound = "T: PartialEq"),
|
||||
Eq(bound = "T: Eq"),
|
||||
Debug(bound = "T: Debug")
|
||||
)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
pub struct Binder<I: Interner, T> {
|
||||
value: T,
|
||||
bound_vars: I::BoundVarKinds,
|
||||
}
|
||||
|
||||
// FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
|
||||
// understand how to turn `T` to `T::Lifted` in the output `type Lifted`.
|
||||
impl<I: Interner, U: Interner, T> Lift<U> for Binder<I, T>
|
||||
where
|
||||
T: Lift<U>,
|
||||
I::BoundVarKinds: Lift<U, Lifted = U::BoundVarKinds>,
|
||||
{
|
||||
type Lifted = Binder<U, T::Lifted>;
|
||||
|
||||
fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
|
||||
Some(Binder {
|
||||
value: self.value.lift_to_tcx(tcx)?,
|
||||
bound_vars: self.bound_vars.lift_to_tcx(tcx)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_binder_encode_decode {
|
||||
($($t:ty),+ $(,)?) => {
|
||||
$(
|
||||
impl<I: Interner, E: crate::TyEncoder<I = I>> rustc_serialize::Encodable<E> for ty::Binder<I, $t>
|
||||
where
|
||||
$t: rustc_serialize::Encodable<E>,
|
||||
I::BoundVarKinds: rustc_serialize::Encodable<E>,
|
||||
{
|
||||
fn encode(&self, e: &mut E) {
|
||||
self.bound_vars().encode(e);
|
||||
self.as_ref().skip_binder().encode(e);
|
||||
}
|
||||
}
|
||||
impl<I: Interner, D: crate::TyDecoder<I = I>> Decodable<D> for ty::Binder<I, $t>
|
||||
where
|
||||
$t: TypeVisitable<I> + rustc_serialize::Decodable<D>,
|
||||
I::BoundVarKinds: rustc_serialize::Decodable<D>,
|
||||
{
|
||||
fn decode(decoder: &mut D) -> Self {
|
||||
let bound_vars = Decodable::decode(decoder);
|
||||
ty::Binder::bind_with_vars(<$t>::decode(decoder), bound_vars)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_binder_encode_decode! {
|
||||
ty::FnSig<I>,
|
||||
ty::TraitPredicate<I>,
|
||||
ty::ExistentialPredicate<I>,
|
||||
ty::TraitRef<I>,
|
||||
ty::ExistentialTraitRef<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner, T> Binder<I, T>
|
||||
where
|
||||
T: TypeVisitable<I>,
|
||||
{
|
||||
/// Wraps `value` in a binder, asserting that `value` does not
|
||||
/// contain any bound vars that would be bound by the
|
||||
/// binder. This is commonly used to 'inject' a value T into a
|
||||
/// different binding level.
|
||||
#[track_caller]
|
||||
pub fn dummy(value: T) -> Binder<I, T> {
|
||||
assert!(
|
||||
!value.has_escaping_bound_vars(),
|
||||
"`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder."
|
||||
);
|
||||
Binder { value, bound_vars: Default::default() }
|
||||
}
|
||||
|
||||
pub fn bind_with_vars(value: T, bound_vars: I::BoundVarKinds) -> Binder<I, T> {
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(bound_vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder { value, bound_vars }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Binder<I, T> {
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
folder.try_fold_binder(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeVisitable<I> for Binder<I, T> {
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
visitor.visit_binder(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeFoldable<I>> TypeSuperFoldable<I> for Binder<I, T> {
|
||||
fn try_super_fold_with<F: FallibleTypeFolder<I>>(
|
||||
self,
|
||||
folder: &mut F,
|
||||
) -> Result<Self, F::Error> {
|
||||
self.try_map_bound(|ty| ty.try_fold_with(folder))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: TypeVisitable<I>> TypeSuperVisitable<I> for Binder<I, T> {
|
||||
fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.as_ref().skip_binder().visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T> Binder<I, T> {
|
||||
/// Skips the binder and returns the "bound" value. This is a
|
||||
/// risky thing to do because it's easy to get confused about
|
||||
/// De Bruijn indices and the like. It is usually better to
|
||||
/// discharge the binder using `no_bound_vars` or
|
||||
/// `instantiate_bound_regions` or something like
|
||||
/// that. `skip_binder` is only valid when you are either
|
||||
/// extracting data that has nothing to do with bound vars, you
|
||||
/// are doing some sort of test that does not involve bound
|
||||
/// regions, or you are being very careful about your depth
|
||||
/// accounting.
|
||||
///
|
||||
/// Some examples where `skip_binder` is reasonable:
|
||||
///
|
||||
/// - extracting the `DefId` from a PolyTraitRef;
|
||||
/// - comparing the self type of a PolyTraitRef to see if it is equal to
|
||||
/// a type parameter `X`, since the type `X` does not reference any regions
|
||||
pub fn skip_binder(self) -> T {
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn bound_vars(&self) -> I::BoundVarKinds {
|
||||
self.bound_vars
|
||||
}
|
||||
|
||||
pub fn as_ref(&self) -> Binder<I, &T> {
|
||||
Binder { value: &self.value, bound_vars: self.bound_vars }
|
||||
}
|
||||
|
||||
pub fn as_deref(&self) -> Binder<I, &T::Target>
|
||||
where
|
||||
T: Deref,
|
||||
{
|
||||
Binder { value: &self.value, bound_vars: self.bound_vars }
|
||||
}
|
||||
|
||||
pub fn map_bound_ref<F, U: TypeVisitable<I>>(&self, f: F) -> Binder<I, U>
|
||||
where
|
||||
F: FnOnce(&T) -> U,
|
||||
{
|
||||
self.as_ref().map_bound(f)
|
||||
}
|
||||
|
||||
pub fn map_bound<F, U: TypeVisitable<I>>(self, f: F) -> Binder<I, U>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let value = f(value);
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(bound_vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Binder { value, bound_vars }
|
||||
}
|
||||
|
||||
pub fn try_map_bound<F, U: TypeVisitable<I>, E>(self, f: F) -> Result<Binder<I, U>, E>
|
||||
where
|
||||
F: FnOnce(T) -> Result<U, E>,
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let value = f(value)?;
|
||||
if cfg!(debug_assertions) {
|
||||
let mut validator = ValidateBoundVars::new(bound_vars);
|
||||
value.visit_with(&mut validator);
|
||||
}
|
||||
Ok(Binder { value, bound_vars })
|
||||
}
|
||||
|
||||
/// Wraps a `value` in a binder, using the same bound variables as the
|
||||
/// current `Binder`. This should not be used if the new value *changes*
|
||||
/// the bound variables. Note: the (old or new) value itself does not
|
||||
/// necessarily need to *name* all the bound variables.
|
||||
///
|
||||
/// This currently doesn't do anything different than `bind`, because we
|
||||
/// don't actually track bound vars. However, semantically, it is different
|
||||
/// because bound vars aren't allowed to change here, whereas they are
|
||||
/// in `bind`. This may be (debug) asserted in the future.
|
||||
pub fn rebind<U>(&self, value: U) -> Binder<I, U>
|
||||
where
|
||||
U: TypeVisitable<I>,
|
||||
{
|
||||
Binder::bind_with_vars(value, self.bound_vars)
|
||||
}
|
||||
|
||||
/// Unwraps and returns the value within, but only if it contains
|
||||
/// no bound vars at all. (In other words, if this binder --
|
||||
/// and indeed any enclosing binder -- doesn't bind anything at
|
||||
/// all.) Otherwise, returns `None`.
|
||||
///
|
||||
/// (One could imagine having a method that just unwraps a single
|
||||
/// binder, but permits late-bound vars bound by enclosing
|
||||
/// binders, but that would require adjusting the debruijn
|
||||
/// indices, and given the shallow binding structure we often use,
|
||||
/// would not be that useful.)
|
||||
pub fn no_bound_vars(self) -> Option<T>
|
||||
where
|
||||
T: TypeVisitable<I>,
|
||||
{
|
||||
// `self.value` is equivalent to `self.skip_binder()`
|
||||
if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) }
|
||||
}
|
||||
|
||||
/// Splits the contents into two things that share the same binder
|
||||
/// level as the original, returning two distinct binders.
|
||||
///
|
||||
/// `f` should consider bound regions at depth 1 to be free, and
|
||||
/// anything it produces with bound regions at depth 1 will be
|
||||
/// bound in the resulting return values.
|
||||
pub fn split<U, V, F>(self, f: F) -> (Binder<I, U>, Binder<I, V>)
|
||||
where
|
||||
F: FnOnce(T) -> (U, V),
|
||||
{
|
||||
let Binder { value, bound_vars } = self;
|
||||
let (u, v) = f(value);
|
||||
(Binder { value: u, bound_vars }, Binder { value: v, bound_vars })
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T> Binder<I, Option<T>> {
|
||||
pub fn transpose(self) -> Option<Binder<I, T>> {
|
||||
let Binder { value, bound_vars } = self;
|
||||
value.map(|value| Binder { value, bound_vars })
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T: IntoIterator> Binder<I, T> {
|
||||
pub fn iter(self) -> impl Iterator<Item = Binder<I, T::Item>> {
|
||||
let Binder { value, bound_vars } = self;
|
||||
value.into_iter().map(move |value| Binder { value, bound_vars })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ValidateBoundVars<I: Interner> {
|
||||
bound_vars: I::BoundVarKinds,
|
||||
binder_index: ty::DebruijnIndex,
|
||||
// We may encounter the same variable at different levels of binding, so
|
||||
// this can't just be `Ty`
|
||||
visited: SsoHashSet<(ty::DebruijnIndex, I::Ty)>,
|
||||
}
|
||||
|
||||
impl<I: Interner> ValidateBoundVars<I> {
|
||||
pub fn new(bound_vars: I::BoundVarKinds) -> Self {
|
||||
ValidateBoundVars {
|
||||
bound_vars,
|
||||
binder_index: ty::INNERMOST,
|
||||
visited: SsoHashSet::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
|
||||
type Result = ControlFlow<()>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &Binder<I, T>) -> Self::Result {
|
||||
self.binder_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.binder_index.shift_out(1);
|
||||
result
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: I::Ty) -> Self::Result {
|
||||
if t.outer_exclusive_binder() < self.binder_index
|
||||
|| !self.visited.insert((self.binder_index, t))
|
||||
{
|
||||
return ControlFlow::Break(());
|
||||
}
|
||||
match t.kind() {
|
||||
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
|
||||
let idx = bound_ty.var().as_usize();
|
||||
if self.bound_vars.len() <= idx {
|
||||
panic!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
|
||||
}
|
||||
bound_ty.assert_eq(self.bound_vars[idx]);
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_region(&mut self, r: I::Region) -> Self::Result {
|
||||
match r.kind() {
|
||||
ty::ReBound(index, br) if index == self.binder_index => {
|
||||
let idx = br.var().as_usize();
|
||||
if self.bound_vars.len() <= idx {
|
||||
panic!("Not enough bound vars: {:?} not found in {:?}", r, self.bound_vars);
|
||||
}
|
||||
br.assert_eq(self.bound_vars[idx]);
|
||||
}
|
||||
|
||||
_ => (),
|
||||
};
|
||||
|
||||
ControlFlow::Continue(())
|
||||
}
|
||||
}
|
|
@ -48,8 +48,8 @@
|
|||
use rustc_index::{Idx, IndexVec};
|
||||
use std::mem;
|
||||
|
||||
use crate::Lrc;
|
||||
use crate::{visit::TypeVisitable, Interner};
|
||||
use crate::visit::TypeVisitable;
|
||||
use crate::{self as ty, Interner, Lrc};
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
type Never = !;
|
||||
|
@ -128,10 +128,9 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
|
|||
pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
|
||||
fn interner(&self) -> I;
|
||||
|
||||
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
|
||||
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
|
||||
where
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
t.super_fold_with(self)
|
||||
}
|
||||
|
@ -167,10 +166,9 @@ pub trait FallibleTypeFolder<I: Interner>: Sized {
|
|||
|
||||
fn interner(&self) -> I;
|
||||
|
||||
fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, Self::Error>
|
||||
fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Self::Error>
|
||||
where
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
t.try_super_fold_with(self)
|
||||
}
|
||||
|
@ -206,10 +204,9 @@ where
|
|||
TypeFolder::interner(self)
|
||||
}
|
||||
|
||||
fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, Never>
|
||||
fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Never>
|
||||
where
|
||||
T: TypeFoldable<I>,
|
||||
I::Binder<T>: TypeSuperFoldable<I>,
|
||||
{
|
||||
Ok(self.fold_binder(t))
|
||||
}
|
||||
|
|
|
@ -8,11 +8,8 @@ use std::hash::Hash;
|
|||
use std::ops::Deref;
|
||||
|
||||
use crate::fold::{TypeFoldable, TypeSuperFoldable};
|
||||
use crate::visit::{Flags, TypeSuperVisitable};
|
||||
use crate::{
|
||||
AliasTy, AliasTyKind, BoundVar, ConstKind, ConstVid, DebruijnIndex, DebugWithInfcx, InferConst,
|
||||
InferTy, Interner, RegionKind, TyKind, TyVid, UnevaluatedConst, UniverseIndex,
|
||||
};
|
||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||
use crate::{self as ty, DebugWithInfcx, Interner, UpcastFrom};
|
||||
|
||||
pub trait Ty<I: Interner<Ty = Self>>:
|
||||
Copy
|
||||
|
@ -21,24 +18,30 @@ pub trait Ty<I: Interner<Ty = Self>>:
|
|||
+ Eq
|
||||
+ Into<I::GenericArg>
|
||||
+ Into<I::Term>
|
||||
+ IntoKind<Kind = TyKind<I>>
|
||||
+ IntoKind<Kind = ty::TyKind<I>>
|
||||
+ TypeSuperVisitable<I>
|
||||
+ TypeSuperFoldable<I>
|
||||
+ Flags
|
||||
{
|
||||
fn new_bool(interner: I) -> Self;
|
||||
|
||||
fn new_infer(interner: I, var: InferTy) -> Self;
|
||||
fn new_infer(interner: I, var: ty::InferTy) -> Self;
|
||||
|
||||
fn new_var(interner: I, var: TyVid) -> Self;
|
||||
fn new_var(interner: I, var: ty::TyVid) -> Self;
|
||||
|
||||
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
|
||||
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
|
||||
|
||||
fn new_alias(interner: I, kind: AliasTyKind, alias_ty: AliasTy<I>) -> Self;
|
||||
fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
|
||||
}
|
||||
|
||||
pub trait Tys<I: Interner<Tys = Self>>:
|
||||
Copy + Debug + Hash + Eq + IntoIterator<Item = I::Ty> + Deref<Target: Deref<Target = [I::Ty]>>
|
||||
Copy
|
||||
+ Debug
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ IntoIterator<Item = I::Ty>
|
||||
+ Deref<Target: Deref<Target = [I::Ty]>>
|
||||
+ TypeVisitable<I>
|
||||
{
|
||||
fn split_inputs_and_output(self) -> (I::FnInputTys, I::Ty);
|
||||
}
|
||||
|
@ -49,13 +52,21 @@ pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
|
|||
}
|
||||
|
||||
pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
|
||||
fn is_safe(self) -> bool;
|
||||
|
||||
fn prefix_str(self) -> &'static str;
|
||||
}
|
||||
|
||||
pub trait Region<I: Interner<Region = Self>>:
|
||||
Copy + DebugWithInfcx<I> + Hash + Eq + Into<I::GenericArg> + IntoKind<Kind = RegionKind<I>> + Flags
|
||||
Copy
|
||||
+ DebugWithInfcx<I>
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ Into<I::GenericArg>
|
||||
+ IntoKind<Kind = ty::RegionKind<I>>
|
||||
+ Flags
|
||||
{
|
||||
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self;
|
||||
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
|
||||
|
||||
fn new_static(interner: I) -> Self;
|
||||
}
|
||||
|
@ -67,18 +78,23 @@ pub trait Const<I: Interner<Const = Self>>:
|
|||
+ Eq
|
||||
+ Into<I::GenericArg>
|
||||
+ Into<I::Term>
|
||||
+ IntoKind<Kind = ConstKind<I>>
|
||||
+ IntoKind<Kind = ty::ConstKind<I>>
|
||||
+ TypeSuperVisitable<I>
|
||||
+ TypeSuperFoldable<I>
|
||||
+ Flags
|
||||
{
|
||||
fn new_infer(interner: I, var: InferConst, ty: I::Ty) -> Self;
|
||||
fn new_infer(interner: I, var: ty::InferConst, ty: I::Ty) -> Self;
|
||||
|
||||
fn new_var(interner: I, var: ConstVid, ty: I::Ty) -> Self;
|
||||
fn new_var(interner: I, var: ty::ConstVid, ty: I::Ty) -> Self;
|
||||
|
||||
fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar, ty: I::Ty) -> Self;
|
||||
fn new_anon_bound(
|
||||
interner: I,
|
||||
debruijn: ty::DebruijnIndex,
|
||||
var: ty::BoundVar,
|
||||
ty: I::Ty,
|
||||
) -> Self;
|
||||
|
||||
fn new_unevaluated(interner: I, uv: UnevaluatedConst<I>, ty: I::Ty) -> Self;
|
||||
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>, ty: I::Ty) -> Self;
|
||||
|
||||
fn ty(self) -> I::Ty;
|
||||
}
|
||||
|
@ -100,6 +116,12 @@ pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
|||
fn type_at(self, i: usize) -> I::Ty;
|
||||
|
||||
fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
|
||||
|
||||
fn extend_with_error(
|
||||
tcx: I,
|
||||
def_id: I::DefId,
|
||||
original_args: &[I::GenericArg],
|
||||
) -> I::GenericArgs;
|
||||
}
|
||||
|
||||
pub trait Predicate<I: Interner<Predicate = Self>>:
|
||||
|
@ -108,14 +130,25 @@ pub trait Predicate<I: Interner<Predicate = Self>>:
|
|||
fn is_coinductive(self, interner: I) -> bool;
|
||||
}
|
||||
|
||||
pub trait Clause<I: Interner<Clause = Self>>:
|
||||
Copy
|
||||
+ Debug
|
||||
+ Hash
|
||||
+ Eq
|
||||
// FIXME: Remove these, uplift the `Upcast` impls.
|
||||
+ UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
|
||||
+ UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
|
||||
{
|
||||
}
|
||||
|
||||
/// Common capabilities of placeholder kinds
|
||||
pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
|
||||
fn universe(self) -> UniverseIndex;
|
||||
fn var(self) -> BoundVar;
|
||||
fn universe(self) -> ty::UniverseIndex;
|
||||
fn var(self) -> ty::BoundVar;
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self;
|
||||
fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
|
||||
|
||||
fn new(ui: UniverseIndex, var: BoundVar) -> Self;
|
||||
fn new(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self;
|
||||
}
|
||||
|
||||
pub trait IntoKind {
|
||||
|
@ -124,12 +157,8 @@ pub trait IntoKind {
|
|||
fn kind(self) -> Self::Kind;
|
||||
}
|
||||
|
||||
pub trait BoundVars<I: Interner> {
|
||||
fn bound_vars(&self) -> I::BoundVars;
|
||||
|
||||
fn has_no_bound_vars(&self) -> bool;
|
||||
}
|
||||
|
||||
pub trait BoundVarLike<I: Interner> {
|
||||
fn var(self) -> BoundVar;
|
||||
fn var(self) -> ty::BoundVar;
|
||||
|
||||
fn assert_eq(self, var: I::BoundVarKind);
|
||||
}
|
||||
|
|
|
@ -28,19 +28,28 @@ pub trait Interner:
|
|||
+ IrPrint<CoercePredicate<Self>>
|
||||
+ IrPrint<FnSig<Self>>
|
||||
{
|
||||
type DefId: Copy + Debug + Hash + Eq;
|
||||
type DefId: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type AdtDef: Copy + Debug + Hash + Eq;
|
||||
|
||||
type GenericArgs: GenericArgs<Self>;
|
||||
/// The slice of args for a specific item. For a GAT like `type Foo<'a>`, it will be `['a]`,
|
||||
/// not including the args from the parent item (trait or impl).
|
||||
type OwnItemArgs: Copy + Debug + Hash + Eq;
|
||||
type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Eq + IntoKind<Kind = GenericArgKind<Self>>;
|
||||
type Term: Copy + Debug + Hash + Eq + IntoKind<Kind = TermKind<Self>>;
|
||||
type GenericArg: Copy
|
||||
+ DebugWithInfcx<Self>
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ IntoKind<Kind = GenericArgKind<Self>>
|
||||
+ TypeVisitable<Self>;
|
||||
type Term: Copy + Debug + Hash + Eq + IntoKind<Kind = TermKind<Self>> + TypeVisitable<Self>;
|
||||
|
||||
type Binder<T: TypeVisitable<Self>>: BoundVars<Self> + TypeSuperVisitable<Self>;
|
||||
type BoundVars: IntoIterator<Item = Self::BoundVar>;
|
||||
type BoundVar;
|
||||
type BoundVarKinds: Copy
|
||||
+ Debug
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ Deref<Target: Deref<Target = [Self::BoundVarKind]>>
|
||||
+ Default;
|
||||
type BoundVarKind: Copy + Debug + Hash + Eq;
|
||||
|
||||
type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
|
||||
type PredefinedOpaques: Copy + Debug + Hash + Eq;
|
||||
|
@ -51,7 +60,7 @@ pub trait Interner:
|
|||
// Kinds of tys
|
||||
type Ty: Ty<Self>;
|
||||
type Tys: Tys<Self>;
|
||||
type FnInputTys: Copy + Debug + Hash + Eq + Deref<Target = [Self::Ty]>;
|
||||
type FnInputTys: Copy + Debug + Hash + Eq + Deref<Target = [Self::Ty]> + TypeVisitable<Self>;
|
||||
type ParamTy: Copy + Debug + Hash + Eq;
|
||||
type BoundTy: Copy + Debug + Hash + Eq + BoundVarLike<Self>;
|
||||
type PlaceholderTy: PlaceholderLike;
|
||||
|
@ -84,14 +93,15 @@ pub trait Interner:
|
|||
// Predicates
|
||||
type ParamEnv: Copy + Debug + Hash + Eq;
|
||||
type Predicate: Predicate<Self>;
|
||||
type TraitPredicate: Copy + Debug + Hash + Eq;
|
||||
type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
|
||||
type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
|
||||
type ProjectionPredicate: Copy + Debug + Hash + Eq;
|
||||
type NormalizesTo: Copy + Debug + Hash + Eq;
|
||||
type SubtypePredicate: Copy + Debug + Hash + Eq;
|
||||
type CoercePredicate: Copy + Debug + Hash + Eq;
|
||||
type ClosureKind: Copy + Debug + Hash + Eq;
|
||||
type Clause: Clause<Self>;
|
||||
type TraitPredicate: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type RegionOutlivesPredicate: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type TypeOutlivesPredicate: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type ProjectionPredicate: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type NormalizesTo: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type SubtypePredicate: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type CoercePredicate: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type ClosureKind: Copy + Debug + Hash + Eq + TypeVisitable<Self>;
|
||||
type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
|
||||
|
||||
fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::fmt;
|
||||
|
||||
use crate::{
|
||||
AliasTerm, AliasTy, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
|
||||
AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig,
|
||||
Interner, NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
|
||||
};
|
||||
|
||||
|
@ -22,6 +22,15 @@ macro_rules! define_display_via_print {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, T> fmt::Display for Binder<I, T>
|
||||
where
|
||||
I: IrPrint<Binder<I, T>>,
|
||||
{
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<I as IrPrint<Binder<I, T>>>::print(self, fmt)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_debug_via_print {
|
||||
($($ty:ident),+ $(,)?) => {
|
||||
$(
|
||||
|
|
|
@ -8,10 +8,14 @@
|
|||
#[cfg(feature = "nightly")]
|
||||
extern crate self as rustc_type_ir;
|
||||
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::sso::SsoHashSet;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_NoContext};
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
use std::collections::HashSet as SsoHashSet;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
#[cfg(not(feature = "nightly"))]
|
||||
|
@ -31,6 +35,7 @@ pub mod ty_kind;
|
|||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
mod binder;
|
||||
mod canonical;
|
||||
mod const_kind;
|
||||
mod debug;
|
||||
|
@ -43,6 +48,7 @@ mod predicate_kind;
|
|||
mod region_kind;
|
||||
mod upcast;
|
||||
|
||||
pub use binder::*;
|
||||
pub use canonical::*;
|
||||
#[cfg(feature = "nightly")]
|
||||
pub use codec::*;
|
||||
|
@ -374,6 +380,10 @@ impl<I: Interner> inherent::BoundVarLike<I> for BoundVar {
|
|||
fn var(self) -> BoundVar {
|
||||
self
|
||||
}
|
||||
|
||||
fn assert_eq(self, _var: I::BoundVarKind) {
|
||||
unreachable!("FIXME: We really should have a separate `BoundConst` for consts")
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the various closure traits in the language. This
|
||||
|
|
|
@ -6,10 +6,9 @@ use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEn
|
|||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::inherent::*;
|
||||
use crate::upcast::Upcast;
|
||||
use crate::visit::TypeVisitableExt as _;
|
||||
use crate::{
|
||||
AliasTy, AliasTyKind, DebugWithInfcx, InferCtxtLike, Interner, UnevaluatedConst, WithInfcx,
|
||||
};
|
||||
use crate::{self as ty, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
|
||||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where-clause:
|
||||
|
@ -75,6 +74,16 @@ impl<I: Interner> TraitRef<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, TraitRef<I>> {
|
||||
pub fn self_ty(&self) -> ty::Binder<I, I::Ty> {
|
||||
self.map_bound_ref(|tr| tr.self_ty())
|
||||
}
|
||||
|
||||
pub fn def_id(&self) -> I::DefId {
|
||||
self.skip_binder().def_id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
|
@ -112,6 +121,22 @@ impl<I: Interner> TraitPredicate<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, TraitPredicate<I>> {
|
||||
pub fn def_id(self) -> I::DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
self.skip_binder().def_id()
|
||||
}
|
||||
|
||||
pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
|
||||
self.map_bound(|trait_ref| trait_ref.self_ty())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn polarity(self) -> PredicatePolarity {
|
||||
self.skip_binder().polarity
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for TraitPredicate<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// FIXME(effects) printing?
|
||||
|
@ -204,6 +229,34 @@ impl<I: Interner> DebugWithInfcx<I> for ExistentialPredicate<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
|
||||
/// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
|
||||
/// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
|
||||
/// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
|
||||
pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> I::Clause {
|
||||
match self.skip_binder() {
|
||||
ExistentialPredicate::Trait(tr) => {
|
||||
self.rebind(tr).with_self_ty(tcx, self_ty).upcast(tcx)
|
||||
}
|
||||
ExistentialPredicate::Projection(p) => {
|
||||
self.rebind(p.with_self_ty(tcx, self_ty)).upcast(tcx)
|
||||
}
|
||||
ExistentialPredicate::AutoTrait(did) => {
|
||||
let generics = tcx.generics_of(did);
|
||||
let trait_ref = if generics.count() == 1 {
|
||||
ty::TraitRef::new(tcx, did, [self_ty])
|
||||
} else {
|
||||
// If this is an ill-formed auto trait, then synthesize
|
||||
// new error args for the missing generics.
|
||||
let err_args = GenericArgs::extend_with_error(tcx, did, &[self_ty.into()]);
|
||||
ty::TraitRef::new(tcx, did, err_args)
|
||||
};
|
||||
self.rebind(trait_ref).upcast(tcx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An existential reference to a trait, where `Self` is erased.
|
||||
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
||||
/// ```ignore (illustrative)
|
||||
|
@ -253,6 +306,20 @@ impl<I: Interner> ExistentialTraitRef<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
|
||||
pub fn def_id(&self) -> I::DefId {
|
||||
self.skip_binder().def_id
|
||||
}
|
||||
|
||||
/// Object types don't have a self type specified. Therefore, when
|
||||
/// we convert the principal trait-ref into a normal trait-ref,
|
||||
/// you must give *some* self type. A common choice is `mk_err()`
|
||||
/// or some placeholder type.
|
||||
pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
|
||||
self.map_bound(|trait_ref| trait_ref.with_self_ty(tcx, self_ty))
|
||||
}
|
||||
}
|
||||
|
||||
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
|
@ -308,6 +375,16 @@ impl<I: Interner> ExistentialProjection<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, ExistentialProjection<I>> {
|
||||
pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ty::Binder<I, ProjectionPredicate<I>> {
|
||||
self.map_bound(|p| p.with_self_ty(tcx, self_ty))
|
||||
}
|
||||
|
||||
pub fn item_def_id(&self) -> I::DefId {
|
||||
self.skip_binder().def_id
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
|
||||
pub enum AliasTermKind {
|
||||
|
@ -414,7 +491,7 @@ impl<I: Interner> AliasTerm<I> {
|
|||
AliasTerm { def_id, args, _use_alias_term_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn expect_ty(self, interner: I) -> AliasTy<I> {
|
||||
pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
|
||||
match self.kind(interner) {
|
||||
AliasTermKind::ProjectionTy
|
||||
| AliasTermKind::InherentTy
|
||||
|
@ -424,7 +501,7 @@ impl<I: Interner> AliasTerm<I> {
|
|||
panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
|
||||
}
|
||||
}
|
||||
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
|
||||
ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn kind(self, interner: I) -> AliasTermKind {
|
||||
|
@ -435,32 +512,32 @@ impl<I: Interner> AliasTerm<I> {
|
|||
match self.kind(interner) {
|
||||
AliasTermKind::ProjectionTy => Ty::new_alias(
|
||||
interner,
|
||||
AliasTyKind::Projection,
|
||||
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
ty::AliasTyKind::Projection,
|
||||
ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
)
|
||||
.into(),
|
||||
AliasTermKind::InherentTy => Ty::new_alias(
|
||||
interner,
|
||||
AliasTyKind::Inherent,
|
||||
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
ty::AliasTyKind::Inherent,
|
||||
ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
)
|
||||
.into(),
|
||||
AliasTermKind::OpaqueTy => Ty::new_alias(
|
||||
interner,
|
||||
AliasTyKind::Opaque,
|
||||
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
ty::AliasTyKind::Opaque,
|
||||
ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
)
|
||||
.into(),
|
||||
AliasTermKind::WeakTy => Ty::new_alias(
|
||||
interner,
|
||||
AliasTyKind::Weak,
|
||||
AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
ty::AliasTyKind::Weak,
|
||||
ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
|
||||
)
|
||||
.into(),
|
||||
AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
|
||||
I::Const::new_unevaluated(
|
||||
interner,
|
||||
UnevaluatedConst::new(self.def_id, self.args),
|
||||
ty::UnevaluatedConst::new(self.def_id, self.args),
|
||||
interner.type_of_instantiated(self.def_id, self.args),
|
||||
)
|
||||
.into()
|
||||
|
@ -514,14 +591,14 @@ impl<I: Interner> AliasTerm<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> From<AliasTy<I>> for AliasTerm<I> {
|
||||
fn from(ty: AliasTy<I>) -> Self {
|
||||
impl<I: Interner> From<ty::AliasTy<I>> for AliasTerm<I> {
|
||||
fn from(ty: ty::AliasTy<I>) -> Self {
|
||||
AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> From<UnevaluatedConst<I>> for AliasTerm<I> {
|
||||
fn from(ct: UnevaluatedConst<I>) -> Self {
|
||||
impl<I: Interner> From<ty::UnevaluatedConst<I>> for AliasTerm<I> {
|
||||
fn from(ct: ty::UnevaluatedConst<I>) -> Self {
|
||||
AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
|
||||
}
|
||||
}
|
||||
|
@ -571,6 +648,40 @@ impl<I: Interner> ProjectionPredicate<I> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
|
||||
/// Returns the `DefId` of the trait of the associated item being projected.
|
||||
#[inline]
|
||||
pub fn trait_def_id(&self, tcx: I) -> I::DefId {
|
||||
self.skip_binder().projection_term.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
/// Get the trait ref required for this projection to be well formed.
|
||||
/// Note that for generic associated types the predicates of the associated
|
||||
/// type also need to be checked.
|
||||
#[inline]
|
||||
pub fn required_poly_trait_ref(&self, tcx: I) -> ty::Binder<I, TraitRef<I>> {
|
||||
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
|
||||
// `self.0.trait_ref` is permitted to have escaping regions.
|
||||
// This is because here `self` has a `Binder` and so does our
|
||||
// return value, so we are preserving the number of binding
|
||||
// levels.
|
||||
self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx))
|
||||
}
|
||||
|
||||
pub fn term(&self) -> ty::Binder<I, I::Term> {
|
||||
self.map_bound(|predicate| predicate.term)
|
||||
}
|
||||
|
||||
/// The `DefId` of the `TraitItem` for the associated type.
|
||||
///
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
|
||||
pub fn projection_def_id(&self) -> I::DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
self.skip_binder().projection_term.def_id
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_term, self.term)
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen
|
|||
use std::fmt;
|
||||
|
||||
use crate::inherent::*;
|
||||
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, TraitRef, WithInfcx};
|
||||
use crate::{self as ty, DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
|
||||
|
||||
use self::TyKind::*;
|
||||
|
||||
|
@ -514,7 +514,7 @@ impl<I: Interner> AliasTy<I> {
|
|||
/// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
|
||||
/// then this function would return a `T: StreamingIterator` trait reference and
|
||||
/// `['a]` as the own args.
|
||||
pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::OwnItemArgs) {
|
||||
pub fn trait_ref_and_own_args(self, interner: I) -> (ty::TraitRef<I>, I::OwnItemArgs) {
|
||||
debug_assert_eq!(self.kind(interner), AliasTyKind::Projection);
|
||||
interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ impl<I: Interner> AliasTy<I> {
|
|||
/// WARNING: This will drop the args for generic associated types
|
||||
/// consider calling [Self::trait_ref_and_own_args] to get those
|
||||
/// as well.
|
||||
pub fn trait_ref(self, interner: I) -> TraitRef<I> {
|
||||
pub fn trait_ref(self, interner: I) -> ty::TraitRef<I> {
|
||||
self.trait_ref_and_own_args(interner).0
|
||||
}
|
||||
}
|
||||
|
@ -982,6 +982,49 @@ impl<I: Interner> FnSig<I> {
|
|||
pub fn output(self) -> I::Ty {
|
||||
self.split_inputs_and_output().1
|
||||
}
|
||||
|
||||
pub fn is_fn_trait_compatible(self) -> bool {
|
||||
let FnSig { safety, abi, c_variadic, .. } = self;
|
||||
!c_variadic && safety.is_safe() && abi.is_rust()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> ty::Binder<I, FnSig<I>> {
|
||||
#[inline]
|
||||
pub fn inputs(self) -> ty::Binder<I, I::FnInputTys> {
|
||||
self.map_bound(|fn_sig| fn_sig.inputs())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[track_caller]
|
||||
pub fn input(self, index: usize) -> ty::Binder<I, I::Ty> {
|
||||
self.map_bound(|fn_sig| fn_sig.inputs()[index])
|
||||
}
|
||||
|
||||
pub fn inputs_and_output(self) -> ty::Binder<I, I::Tys> {
|
||||
self.map_bound(|fn_sig| fn_sig.inputs_and_output)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn output(self) -> ty::Binder<I, I::Ty> {
|
||||
self.map_bound(|fn_sig| fn_sig.output())
|
||||
}
|
||||
|
||||
pub fn c_variadic(self) -> bool {
|
||||
self.skip_binder().c_variadic
|
||||
}
|
||||
|
||||
pub fn safety(self) -> I::Safety {
|
||||
self.skip_binder().safety
|
||||
}
|
||||
|
||||
pub fn abi(self) -> I::Abi {
|
||||
self.skip_binder().abi
|
||||
}
|
||||
|
||||
pub fn is_fn_trait_compatible(&self) -> bool {
|
||||
self.skip_binder().is_fn_trait_compatible()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for FnSig<I> {
|
||||
|
|
|
@ -90,7 +90,7 @@ pub trait TypeVisitor<I: Interner>: Sized {
|
|||
#[cfg(not(feature = "nightly"))]
|
||||
type Result: VisitorResult;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
|
||||
t.super_visit_with(self)
|
||||
}
|
||||
|
||||
|
@ -376,11 +376,11 @@ impl std::fmt::Debug for HasTypeFlagsVisitor {
|
|||
impl<I: Interner> TypeVisitor<I> for HasTypeFlagsVisitor {
|
||||
type Result = ControlFlow<FoundFlags>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
|
||||
// If we're looking for the HAS_BINDER_VARS flag, check if the
|
||||
// binder has vars. This won't be present in the binder's bound
|
||||
// value, so we need to check here too.
|
||||
if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.has_no_bound_vars() {
|
||||
if self.flags.intersects(TypeFlags::HAS_BINDER_VARS) && !t.bound_vars().is_empty() {
|
||||
return ControlFlow::Break(FoundFlags);
|
||||
}
|
||||
|
||||
|
@ -476,7 +476,7 @@ struct HasEscapingVarsVisitor {
|
|||
impl<I: Interner> TypeVisitor<I> for HasEscapingVarsVisitor {
|
||||
type Result = ControlFlow<FoundEscapingVars>;
|
||||
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> Self::Result {
|
||||
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &ty::Binder<I, T>) -> Self::Result {
|
||||
self.outer_index.shift_in(1);
|
||||
let result = t.super_visit_with(self);
|
||||
self.outer_index.shift_out(1);
|
||||
|
|
Loading…
Reference in New Issue