1
Fork 0

Uplift binder

This commit is contained in:
Michael Goulet 2024-05-20 12:57:07 -04:00
parent e8fbd99128
commit 28ce588321
23 changed files with 702 additions and 666 deletions

View file

@ -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>,
}

View file

@ -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()
}

View file

@ -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> {

View file

@ -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,

View file

@ -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>>
}

View file

@ -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 {

View file

@ -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,

View file

@ -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,

View file

@ -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 {