Auto merge of #125001 - compiler-errors:uplift-trait-predicate, r=lcnr
Uplift various `*Predicate` types into `rustc_type_ir` Uplifts `ProjectionPredicate`, `ExistentialTraitRef`, `ExistentialProjection`, `TraitPredicate`, `NormalizesTo`, `CoercePredicate`, and `SubtypePredicate`. Adds `rustc_type_ir_macros`, which semi-duplicates the derive for `TypeVisitable`, `TypeFoldable`, and `Lift`, but in a way that is interner-agnostic. Moves `rustc_type_ir::trait_ref` to `rustc_type_ir::predicate`. The specific placement of all these structs doesn't matter b/c of glob imports, tho.
This commit is contained in:
commit
ee97564e3a
11
Cargo.lock
11
Cargo.lock
@ -4837,9 +4837,20 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"rustc_type_ir_macros",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_type_ir_macros"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.62",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
|
@ -100,6 +100,12 @@ fn into_diag_arg(self) -> DiagArgValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
}
|
||||
}
|
||||
|
||||
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||
|
||||
impl IntoDiagArg for bool {
|
||||
|
@ -7,7 +7,7 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS;
|
||||
use rustc_middle::ty::fold::BottomUpFolder;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable};
|
||||
use rustc_middle::ty::{DynKind, ToPredicate};
|
||||
use rustc_span::{ErrorGuaranteed, Span};
|
||||
use rustc_trait_selection::traits::error_reporting::report_object_safety_error;
|
||||
|
@ -1,9 +1,8 @@
|
||||
use rustc_hir as hir;
|
||||
use rustc_infer::infer::TyCtxtInferExt;
|
||||
use rustc_macros::{LintDiagnostic, Subdiagnostic};
|
||||
use rustc_middle::ty::{
|
||||
self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable,
|
||||
};
|
||||
use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath};
|
||||
use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable};
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::{symbol::kw, Span};
|
||||
use rustc_trait_selection::traits;
|
||||
|
@ -26,6 +26,7 @@
|
||||
use crate::traits::solve::{
|
||||
ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData,
|
||||
};
|
||||
use crate::ty::predicate::ExistentialPredicateStableCmpExt as _;
|
||||
use crate::ty::{
|
||||
self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData,
|
||||
GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern,
|
||||
@ -99,17 +100,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
type CanonicalVars = CanonicalVarInfos<'tcx>;
|
||||
|
||||
type Ty = Ty<'tcx>;
|
||||
type Pat = Pattern<'tcx>;
|
||||
type Tys = &'tcx List<Ty<'tcx>>;
|
||||
type AliasTy = ty::AliasTy<'tcx>;
|
||||
type ParamTy = ParamTy;
|
||||
type BoundTy = ty::BoundTy;
|
||||
type PlaceholderTy = ty::PlaceholderType;
|
||||
|
||||
type ErrorGuaranteed = ErrorGuaranteed;
|
||||
|
||||
type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
|
||||
type PolyFnSig = PolyFnSig<'tcx>;
|
||||
type AllocId = crate::mir::interpret::AllocId;
|
||||
type Pat = Pattern<'tcx>;
|
||||
|
||||
type Const = ty::Const<'tcx>;
|
||||
type AliasConst = ty::UnevaluatedConst<'tcx>;
|
||||
@ -121,8 +122,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||
|
||||
type Region = Region<'tcx>;
|
||||
type EarlyParamRegion = ty::EarlyParamRegion;
|
||||
type BoundRegion = ty::BoundRegion;
|
||||
type LateParamRegion = ty::LateParamRegion;
|
||||
type BoundRegion = ty::BoundRegion;
|
||||
type InferRegion = ty::RegionVid;
|
||||
type PlaceholderRegion = ty::PlaceholderRegion;
|
||||
|
||||
@ -146,6 +147,10 @@ fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics {
|
||||
self.generics_of(def_id)
|
||||
}
|
||||
|
||||
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
|
||||
self.mk_args(args)
|
||||
}
|
||||
|
||||
fn check_and_mk_args(
|
||||
self,
|
||||
def_id: DefId,
|
||||
@ -153,6 +158,10 @@ fn check_and_mk_args(
|
||||
) -> ty::GenericArgsRef<'tcx> {
|
||||
self.check_and_mk_args(def_id, args)
|
||||
}
|
||||
|
||||
fn parent(self, def_id: Self::DefId) -> Self::DefId {
|
||||
self.parent(def_id)
|
||||
}
|
||||
}
|
||||
|
||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||
|
@ -96,13 +96,13 @@
|
||||
pub use self::parameterized::ParameterizedOverTcx;
|
||||
pub use self::pattern::{Pattern, PatternKind};
|
||||
pub use self::predicate::{
|
||||
Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialProjection,
|
||||
ExistentialTraitRef, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
|
||||
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
|
||||
PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
|
||||
PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
|
||||
RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitPredicate,
|
||||
TraitRef, TypeOutlivesPredicate,
|
||||
Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt,
|
||||
ExistentialProjection, ExistentialTraitRef, NormalizesTo, OutlivesPredicate,
|
||||
PolyCoercePredicate, PolyExistentialPredicate, PolyExistentialProjection,
|
||||
PolyExistentialTraitRef, PolyProjectionPredicate, PolyRegionOutlivesPredicate,
|
||||
PolySubtypePredicate, PolyTraitPredicate, PolyTraitRef, PolyTypeOutlivesPredicate, Predicate,
|
||||
PredicateKind, ProjectionPredicate, RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef,
|
||||
ToPredicate, TraitPredicate, TraitRef, TypeOutlivesPredicate,
|
||||
};
|
||||
pub use self::region::{
|
||||
BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region,
|
||||
@ -275,61 +275,6 @@ pub enum ImplSubject<'tcx> {
|
||||
Inherent(Ty<'tcx>),
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum ImplPolarity {
|
||||
/// `impl Trait for Type`
|
||||
Positive,
|
||||
/// `impl !Trait for Type`
|
||||
Negative,
|
||||
/// `#[rustc_reservation_impl] impl Trait for Type`
|
||||
///
|
||||
/// This is a "stability hack", not a real Rust feature.
|
||||
/// See #64631 for details.
|
||||
Reservation,
|
||||
}
|
||||
|
||||
impl fmt::Display for ImplPolarity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Positive => f.write_str("positive"),
|
||||
Self::Negative => f.write_str("negative"),
|
||||
Self::Reservation => f.write_str("reservation"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Polarity for a trait predicate. May either be negative or positive.
|
||||
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
||||
/// "reservation" level.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum PredicatePolarity {
|
||||
/// `Type: Trait`
|
||||
Positive,
|
||||
/// `Type: !Trait`
|
||||
Negative,
|
||||
}
|
||||
|
||||
impl PredicatePolarity {
|
||||
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
||||
pub fn flip(&self) -> PredicatePolarity {
|
||||
match self {
|
||||
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
||||
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PredicatePolarity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Positive => f.write_str("positive"),
|
||||
Self::Negative => f.write_str("negative"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum Asyncness {
|
||||
|
@ -1,22 +1,28 @@
|
||||
use rustc_data_structures::captures::Captures;
|
||||
use rustc_data_structures::intern::Interned;
|
||||
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||
use rustc_type_ir::ClauseKind as IrClauseKind;
|
||||
use rustc_type_ir::PredicateKind as IrPredicateKind;
|
||||
use rustc_type_ir::TraitRef as IrTraitRef;
|
||||
use rustc_macros::{
|
||||
extension, HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable,
|
||||
};
|
||||
use rustc_type_ir as ir;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
use crate::ty::visit::TypeVisitableExt;
|
||||
use crate::ty::{
|
||||
self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef,
|
||||
PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
|
||||
self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags,
|
||||
WithCachedTypeInfo,
|
||||
};
|
||||
|
||||
pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
|
||||
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
||||
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
|
||||
pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
|
||||
pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
|
||||
pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
|
||||
pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
|
||||
pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
|
||||
pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
|
||||
pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
|
||||
pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
|
||||
pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
|
||||
pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>;
|
||||
pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
|
||||
|
||||
/// A statement that can be proven by a trait solver. This includes things that may
|
||||
/// show up in where clauses, such as trait predicates and projection predicates,
|
||||
@ -195,43 +201,25 @@ pub fn as_region_outlives_clause(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub enum ExistentialPredicate<'tcx> {
|
||||
/// E.g., `Iterator`.
|
||||
Trait(ExistentialTraitRef<'tcx>),
|
||||
/// E.g., `Iterator::Item = T`.
|
||||
Projection(ExistentialProjection<'tcx>),
|
||||
/// E.g., `Send`.
|
||||
AutoTrait(DefId),
|
||||
}
|
||||
|
||||
impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ExistentialPredicate<'tcx> {
|
||||
fn fmt<Infcx: rustc_type_ir::InferCtxtLike<Interner = TyCtxt<'tcx>>>(
|
||||
this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>,
|
||||
f: &mut std::fmt::Formatter<'_>,
|
||||
) -> std::fmt::Result {
|
||||
std::fmt::Debug::fmt(&this.data, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
|
||||
impl<'tcx> ExistentialPredicate<'tcx> {
|
||||
/// Compares via an ordering that will not change if modules are reordered or other changes are
|
||||
/// made to the tree. In particular, this ordering is preserved across incremental compilations.
|
||||
pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
|
||||
use self::ExistentialPredicate::*;
|
||||
fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
|
||||
match (*self, *other) {
|
||||
(Trait(_), Trait(_)) => Ordering::Equal,
|
||||
(Projection(ref a), Projection(ref b)) => {
|
||||
(ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
|
||||
(ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
|
||||
tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
|
||||
}
|
||||
(AutoTrait(ref a), AutoTrait(ref b)) => {
|
||||
(ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
|
||||
tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
|
||||
}
|
||||
(Trait(_), _) => Ordering::Less,
|
||||
(Projection(_), Trait(_)) => Ordering::Greater,
|
||||
(Projection(_), _) => Ordering::Less,
|
||||
(AutoTrait(_), _) => Ordering::Greater,
|
||||
(ExistentialPredicate::Trait(_), _) => Ordering::Less,
|
||||
(ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
|
||||
Ordering::Greater
|
||||
}
|
||||
(ExistentialPredicate::Projection(_), _) => Ordering::Less,
|
||||
(ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -340,52 +328,6 @@ pub fn def_id(&self) -> DefId {
|
||||
}
|
||||
}
|
||||
|
||||
/// An existential reference to a trait, where `Self` is erased.
|
||||
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
||||
/// ```ignore (illustrative)
|
||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||
/// ```
|
||||
/// The generic parameters don't include the erased `Self`, only trait
|
||||
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct ExistentialTraitRef<'tcx> {
|
||||
pub def_id: DefId,
|
||||
pub args: GenericArgsRef<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> ExistentialTraitRef<'tcx> {
|
||||
pub fn erase_self_ty(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: ty::TraitRef<'tcx>,
|
||||
) -> ty::ExistentialTraitRef<'tcx> {
|
||||
// Assert there is a Self.
|
||||
trait_ref.args.type_at(0);
|
||||
|
||||
ty::ExistentialTraitRef {
|
||||
def_id: trait_ref.def_id,
|
||||
args: tcx.mk_args(&trait_ref.args[1..]),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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::TraitRef<'tcx> {
|
||||
// otherwise the escaping vars would be captured by the binder
|
||||
// debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||
|
||||
ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> IntoDiagArg for ExistentialTraitRef<'tcx> {
|
||||
fn into_diag_arg(self) -> DiagArgValue {
|
||||
self.to_string().into_diag_arg()
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
||||
@ -402,62 +344,8 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTrai
|
||||
}
|
||||
}
|
||||
|
||||
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct ExistentialProjection<'tcx> {
|
||||
pub def_id: DefId,
|
||||
pub args: GenericArgsRef<'tcx>,
|
||||
pub term: Term<'tcx>,
|
||||
}
|
||||
|
||||
pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
|
||||
|
||||
impl<'tcx> ExistentialProjection<'tcx> {
|
||||
/// Extracts the underlying existential trait reference from this projection.
|
||||
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
|
||||
/// then this function would return an `exists T. T: Iterator` existential trait
|
||||
/// reference.
|
||||
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
|
||||
let def_id = tcx.parent(self.def_id);
|
||||
let args_count = tcx.generics_of(def_id).count() - 1;
|
||||
let args = tcx.mk_args(&self.args[..args_count]);
|
||||
ty::ExistentialTraitRef { def_id, args }
|
||||
}
|
||||
|
||||
pub fn with_self_ty(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
self_ty: Ty<'tcx>,
|
||||
) -> ty::ProjectionPredicate<'tcx> {
|
||||
// otherwise the escaping regions would be captured by the binders
|
||||
debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||
|
||||
ty::ProjectionPredicate {
|
||||
projection_ty: AliasTy::new(
|
||||
tcx,
|
||||
self.def_id,
|
||||
[self_ty.into()].into_iter().chain(self.args),
|
||||
),
|
||||
term: self.term,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn erase_self_ty(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
projection_predicate: ty::ProjectionPredicate<'tcx>,
|
||||
) -> Self {
|
||||
// Assert there is a Self.
|
||||
projection_predicate.projection_ty.args.type_at(0);
|
||||
|
||||
Self {
|
||||
def_id: projection_predicate.projection_ty.def_id,
|
||||
args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]),
|
||||
term: projection_predicate.term,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PolyExistentialProjection<'tcx> {
|
||||
pub fn with_self_ty(
|
||||
&self,
|
||||
@ -578,37 +466,8 @@ pub fn instantiate_supertrait(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct TraitPredicate<'tcx> {
|
||||
pub trait_ref: TraitRef<'tcx>,
|
||||
|
||||
/// If polarity is Positive: we are proving that the trait is implemented.
|
||||
///
|
||||
/// If polarity is Negative: we are proving that a negative impl of this trait
|
||||
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
||||
/// exist via a series of predicates.)
|
||||
///
|
||||
/// If polarity is Reserved: that's a bug.
|
||||
pub polarity: PredicatePolarity,
|
||||
}
|
||||
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> TraitPredicate<'tcx> {
|
||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
||||
Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> DefId {
|
||||
self.trait_ref.def_id
|
||||
}
|
||||
|
||||
pub fn self_ty(self) -> Ty<'tcx> {
|
||||
self.trait_ref.self_ty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
pub fn def_id(self) -> DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
@ -634,64 +493,10 @@ pub fn polarity(self) -> PredicatePolarity {
|
||||
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
|
||||
pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
|
||||
|
||||
/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
|
||||
/// whether the `a` type is the type that we should label as "expected" when
|
||||
/// presenting user diagnostics.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct SubtypePredicate<'tcx> {
|
||||
pub a_is_expected: bool,
|
||||
pub a: Ty<'tcx>,
|
||||
pub b: Ty<'tcx>,
|
||||
}
|
||||
pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
|
||||
|
||||
/// Encodes that we have to coerce *from* the `a` type to the `b` type.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct CoercePredicate<'tcx> {
|
||||
pub a: Ty<'tcx>,
|
||||
pub b: Ty<'tcx>,
|
||||
}
|
||||
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
|
||||
|
||||
/// This kind of predicate has no *direct* correspondent in the
|
||||
/// syntax, but it roughly corresponds to the syntactic forms:
|
||||
///
|
||||
/// 1. `T: TraitRef<..., Item = Type>`
|
||||
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
|
||||
///
|
||||
/// In particular, form #1 is "desugared" to the combination of a
|
||||
/// normal trait predicate (`T: TraitRef<...>`) and one of these
|
||||
/// predicates. Form #2 is a broader form in that it also permits
|
||||
/// equality between arbitrary types. Processing an instance of
|
||||
/// Form #2 eventually yields one of these `ProjectionPredicate`
|
||||
/// instances to normalize the LHS.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct ProjectionPredicate<'tcx> {
|
||||
pub projection_ty: AliasTy<'tcx>,
|
||||
pub term: Term<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> ProjectionPredicate<'tcx> {
|
||||
pub fn self_ty(self) -> Ty<'tcx> {
|
||||
self.projection_ty.self_ty()
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
|
||||
Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.projection_ty.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> DefId {
|
||||
self.projection_ty.def_id
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
@ -728,33 +533,6 @@ pub fn projection_def_id(&self) -> DefId {
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
|
||||
/// proven by actually normalizing `alias`.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct NormalizesTo<'tcx> {
|
||||
pub alias: AliasTy<'tcx>,
|
||||
pub term: Term<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> NormalizesTo<'tcx> {
|
||||
pub fn self_ty(self) -> Ty<'tcx> {
|
||||
self.alias.self_ty()
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
|
||||
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.alias.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> DefId {
|
||||
self.alias.def_id
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToPolyTraitRef<'tcx> {
|
||||
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
|
||||
}
|
||||
|
@ -2953,8 +2953,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
#[extension(pub trait PrintTraitPredicateExt<'tcx>)]
|
||||
impl<'tcx> ty::TraitPredicate<'tcx> {
|
||||
pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
|
||||
fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> {
|
||||
TraitPredPrintModifiersAndPath(self)
|
||||
}
|
||||
}
|
||||
@ -3037,6 +3038,15 @@ macro_rules! define_print_and_forward_display {
|
||||
p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path()))
|
||||
}
|
||||
|
||||
ty::TraitPredicate<'tcx> {
|
||||
p!(print(self.trait_ref.self_ty()), ": ");
|
||||
p!(pretty_print_bound_constness(self.trait_ref));
|
||||
if let ty::PredicatePolarity::Negative = self.polarity {
|
||||
p!("!");
|
||||
}
|
||||
p!(print(self.trait_ref.print_trait_sugared()))
|
||||
}
|
||||
|
||||
ty::TypeAndMut<'tcx> {
|
||||
p!(write("{}", self.mutbl.prefix_str()), print(self.ty))
|
||||
}
|
||||
@ -3077,13 +3087,15 @@ macro_rules! define_print_and_forward_display {
|
||||
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
define_print_and_forward_display! {
|
||||
(self, cx):
|
||||
|
||||
&'tcx ty::List<Ty<'tcx>> {
|
||||
p!("{{", comma_sep(self.iter()), "}}")
|
||||
ty::ExistentialPredicate<'tcx> {
|
||||
match *self {
|
||||
ty::ExistentialPredicate::Trait(x) => p!(print(x)),
|
||||
ty::ExistentialPredicate::Projection(x) => p!(print(x)),
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||
p!(print_def_path(def_id, &[]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ty::ExistentialTraitRef<'tcx> {
|
||||
@ -3098,14 +3110,36 @@ macro_rules! define_print_and_forward_display {
|
||||
p!(write("{} = ", name), print(self.term))
|
||||
}
|
||||
|
||||
ty::ExistentialPredicate<'tcx> {
|
||||
match *self {
|
||||
ty::ExistentialPredicate::Trait(x) => p!(print(x)),
|
||||
ty::ExistentialPredicate::Projection(x) => p!(print(x)),
|
||||
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
||||
p!(print_def_path(def_id, &[]));
|
||||
}
|
||||
}
|
||||
ty::ProjectionPredicate<'tcx> {
|
||||
p!(print(self.projection_ty), " == ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.term))
|
||||
}
|
||||
|
||||
ty::SubtypePredicate<'tcx> {
|
||||
p!(print(self.a), " <: ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.b))
|
||||
}
|
||||
|
||||
ty::CoercePredicate<'tcx> {
|
||||
p!(print(self.a), " -> ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.b))
|
||||
}
|
||||
|
||||
ty::NormalizesTo<'tcx> {
|
||||
p!(print(self.alias), " normalizes-to ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.term))
|
||||
}
|
||||
}
|
||||
|
||||
define_print_and_forward_display! {
|
||||
(self, cx):
|
||||
|
||||
&'tcx ty::List<Ty<'tcx>> {
|
||||
p!("{{", comma_sep(self.iter()), "}}")
|
||||
}
|
||||
|
||||
ty::FnSig<'tcx> {
|
||||
@ -3164,39 +3198,6 @@ macro_rules! define_print_and_forward_display {
|
||||
p!(write("{}", self.name))
|
||||
}
|
||||
|
||||
ty::SubtypePredicate<'tcx> {
|
||||
p!(print(self.a), " <: ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.b))
|
||||
}
|
||||
|
||||
ty::CoercePredicate<'tcx> {
|
||||
p!(print(self.a), " -> ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.b))
|
||||
}
|
||||
|
||||
ty::TraitPredicate<'tcx> {
|
||||
p!(print(self.trait_ref.self_ty()), ": ");
|
||||
p!(pretty_print_bound_constness(self.trait_ref));
|
||||
if let ty::PredicatePolarity::Negative = self.polarity {
|
||||
p!("!");
|
||||
}
|
||||
p!(print(self.trait_ref.print_trait_sugared()))
|
||||
}
|
||||
|
||||
ty::ProjectionPredicate<'tcx> {
|
||||
p!(print(self.projection_ty), " == ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.term))
|
||||
}
|
||||
|
||||
ty::NormalizesTo<'tcx> {
|
||||
p!(print(self.alias), " normalizes-to ");
|
||||
cx.reset_type_limit();
|
||||
p!(print(self.term))
|
||||
}
|
||||
|
||||
ty::Term<'tcx> {
|
||||
match self.unpack() {
|
||||
ty::TermKind::Ty(ty) => p!(print(ty)),
|
||||
|
@ -5,8 +5,10 @@
|
||||
//! subtyping, type equality, etc.
|
||||
|
||||
use crate::ty::error::{ExpectedFound, TypeError};
|
||||
use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable};
|
||||
use crate::ty::{GenericArg, GenericArgKind, GenericArgsRef};
|
||||
use crate::ty::{
|
||||
self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg,
|
||||
GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::DefId;
|
||||
@ -702,14 +704,21 @@ fn relate<R: TypeRelation<'tcx>>(
|
||||
}
|
||||
|
||||
let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| {
|
||||
use crate::ty::ExistentialPredicate::*;
|
||||
match (ep_a.skip_binder(), ep_b.skip_binder()) {
|
||||
(Trait(a), Trait(b)) => Ok(ep_a
|
||||
.rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))),
|
||||
(Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
))),
|
||||
(AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))),
|
||||
(ExistentialPredicate::Trait(a), ExistentialPredicate::Trait(b)) => Ok(ep_a
|
||||
.rebind(ExistentialPredicate::Trait(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
))),
|
||||
(ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => {
|
||||
Ok(ep_a.rebind(ExistentialPredicate::Projection(
|
||||
relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
|
||||
)))
|
||||
}
|
||||
(ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b))
|
||||
if a == b =>
|
||||
{
|
||||
Ok(ep_a.rebind(ExistentialPredicate::AutoTrait(a)))
|
||||
}
|
||||
_ => Err(TypeError::ExistentialMismatch(expected_found(a, b))),
|
||||
}
|
||||
});
|
||||
|
@ -55,12 +55,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
with_no_trimmed_paths!(fmt::Display::fmt(self, f))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?} -> {}", self.kind, self.target)
|
||||
@ -158,25 +152,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// FIXME(effects) printing?
|
||||
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.kind())
|
||||
|
@ -1142,6 +1142,36 @@ pub struct AliasTy<'tcx> {
|
||||
_use_alias_ty_new_instead: (),
|
||||
}
|
||||
|
||||
impl<'tcx> rustc_type_ir::inherent::AliasTy<TyCtxt<'tcx>> for AliasTy<'tcx> {
|
||||
fn new(
|
||||
interner: TyCtxt<'tcx>,
|
||||
trait_def_id: DefId,
|
||||
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
|
||||
) -> Self {
|
||||
AliasTy::new(interner, trait_def_id, args)
|
||||
}
|
||||
|
||||
fn def_id(self) -> DefId {
|
||||
self.def_id
|
||||
}
|
||||
|
||||
fn args(self) -> ty::GenericArgsRef<'tcx> {
|
||||
self.args
|
||||
}
|
||||
|
||||
fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId {
|
||||
self.trait_def_id(interner)
|
||||
}
|
||||
|
||||
fn self_ty(self) -> Ty<'tcx> {
|
||||
self.self_ty()
|
||||
}
|
||||
|
||||
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
||||
self.with_self_ty(tcx, self_ty)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> AliasTy<'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
@ -8,7 +8,8 @@
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::{
|
||||
self, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, UintTy,
|
||||
self, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable,
|
||||
TypeVisitableExt, UintTy,
|
||||
};
|
||||
use rustc_span::sym;
|
||||
use rustc_trait_selection::traits;
|
||||
|
@ -45,7 +45,9 @@
|
||||
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};
|
||||
use rustc_middle::ty::print::{
|
||||
with_forced_trimmed_paths, with_no_trimmed_paths, PrintTraitPredicateExt as _,
|
||||
};
|
||||
|
||||
use itertools::EitherOrBoth;
|
||||
use itertools::Itertools;
|
||||
|
@ -38,7 +38,8 @@
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
|
||||
use rustc_middle::ty::print::{
|
||||
with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitRefExt as _,
|
||||
with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitPredicateExt as _,
|
||||
PrintTraitRefExt as _,
|
||||
};
|
||||
use rustc_middle::ty::{
|
||||
self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable,
|
||||
|
@ -18,7 +18,8 @@
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::{
|
||||
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
||||
self, EarlyBinder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitor,
|
||||
};
|
||||
use rustc_middle::ty::{GenericArg, GenericArgs};
|
||||
use rustc_middle::ty::{ToPredicate, TypeVisitableExt};
|
||||
|
@ -13,7 +13,8 @@ rustc_index = { path = "../rustc_index", default-features = false }
|
||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||
rustc_span = { path = "../rustc_span", optional = true }
|
||||
smallvec = { version = "1.8.1" }
|
||||
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
|
||||
smallvec = { version = "1.8.1", default-features = false }
|
||||
# tidy-alphabetical-end
|
||||
|
||||
[features]
|
||||
|
@ -1,20 +1,25 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::inherent::*;
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::{Interner, UniverseIndex};
|
||||
|
||||
/// A "canonicalized" type `V` is one where all free inference
|
||||
/// variables have been rewritten to "canonical vars". These are
|
||||
/// numbered starting from 0 in order of first appearance.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
|
||||
#[derivative(
|
||||
Clone(bound = "V: Clone"),
|
||||
Hash(bound = "V: Hash"),
|
||||
PartialEq(bound = "V: PartialEq"),
|
||||
Eq(bound = "V: Eq"),
|
||||
Debug(bound = "V: fmt::Debug"),
|
||||
Copy(bound = "V: Copy")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub struct Canonical<I: Interner, V> {
|
||||
pub value: V,
|
||||
@ -64,18 +69,6 @@ pub fn unchecked_rebind<W>(self, value: W) -> Canonical<I, W> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
|
||||
|
||||
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
*value == other.value
|
||||
&& *max_universe == other.max_universe
|
||||
&& *variables == other.variables
|
||||
&& *defining_opaque_types == other.defining_opaque_types
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
@ -86,84 +79,25 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: fmt::Debug> fmt::Debug for Canonical<I, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
f.debug_struct("Canonical")
|
||||
.field("value", &value)
|
||||
.field("max_universe", &max_universe)
|
||||
.field("variables", &variables)
|
||||
.field("defining_opaque_types", &defining_opaque_types)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: Copy> Copy for Canonical<I, V> where I::CanonicalVars: Copy {}
|
||||
|
||||
impl<I: Interner, V: TypeFoldable<I>> TypeFoldable<I> for Canonical<I, V>
|
||||
where
|
||||
I::CanonicalVars: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(Canonical {
|
||||
value: self.value.try_fold_with(folder)?,
|
||||
max_universe: self.max_universe.try_fold_with(folder)?,
|
||||
variables: self.variables.try_fold_with(folder)?,
|
||||
defining_opaque_types: self.defining_opaque_types,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: TypeVisitable<I>> TypeVisitable<I> for Canonical<I, V>
|
||||
where
|
||||
I::CanonicalVars: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
try_visit!(value.visit_with(folder));
|
||||
try_visit!(max_universe.visit_with(folder));
|
||||
try_visit!(defining_opaque_types.visit_with(folder));
|
||||
variables.visit_with(folder)
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a canonical variable that is included with the
|
||||
/// canonical value. This is sufficient information for code to create
|
||||
/// a copy of the canonical value in some other inference context,
|
||||
/// with fresh inference variables replacing the canonical values.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
Debug(bound = ""),
|
||||
Eq(bound = ""),
|
||||
PartialEq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct CanonicalVarInfo<I: Interner> {
|
||||
pub kind: CanonicalVarKind<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner> PartialEq for CanonicalVarInfo<I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.kind == other.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for CanonicalVarInfo<I> {}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.kind.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for CanonicalVarInfo<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(CanonicalVarInfo { kind: self.kind.try_fold_with(folder)? })
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarInfo<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
self.kind.universe()
|
||||
@ -216,6 +150,7 @@ pub fn expect_placeholder_index(self) -> usize {
|
||||
/// that analyzes type-like values.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum CanonicalVarKind<I: Interner> {
|
||||
/// Some kind of type inference variable.
|
||||
@ -258,51 +193,6 @@ fn eq(&self, other: &Self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for CanonicalVarKind<I> {}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(_)
|
||||
| CanonicalVarKind::PlaceholderTy(_)
|
||||
| CanonicalVarKind::Region(_)
|
||||
| CanonicalVarKind::PlaceholderRegion(_)
|
||||
| CanonicalVarKind::Effect => V::Result::output(),
|
||||
CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
|
||||
ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for CanonicalVarKind<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
CanonicalVarKind::Ty(kind) => CanonicalVarKind::Ty(kind),
|
||||
CanonicalVarKind::Region(kind) => CanonicalVarKind::Region(kind),
|
||||
CanonicalVarKind::Const(kind, ty) => {
|
||||
CanonicalVarKind::Const(kind, ty.try_fold_with(folder)?)
|
||||
}
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderTy(placeholder)
|
||||
}
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder)
|
||||
}
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, ty.try_fold_with(folder)?)
|
||||
}
|
||||
CanonicalVarKind::Effect => CanonicalVarKind::Effect,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarKind<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
match self {
|
||||
@ -355,6 +245,7 @@ pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind<I> {
|
||||
/// usize or f32). In order to faithfully reproduce a type, we need to
|
||||
/// know what set of types a given type variable can be unified with.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum CanonicalTyVarKind {
|
||||
/// General type variable `?T` that can be unified with arbitrary types.
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
/// Represents a constant in Rust.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum ConstKind<I: Interner> {
|
||||
/// A const generic parameter.
|
||||
@ -58,8 +58,6 @@ fn eq(&self, other: &Self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for ConstKind<I> {}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
WithInfcx::with_no_infcx(self).fmt(f)
|
||||
|
@ -1,5 +1,6 @@
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::fold::TypeSuperFoldable;
|
||||
use crate::visit::{Flags, TypeSuperVisitable};
|
||||
@ -50,7 +51,12 @@ pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
||||
}
|
||||
|
||||
pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
||||
Copy + DebugWithInfcx<I> + Hash + Eq + IntoIterator<Item = I::GenericArg>
|
||||
Copy
|
||||
+ DebugWithInfcx<I>
|
||||
+ Hash
|
||||
+ Eq
|
||||
+ IntoIterator<Item = I::GenericArg>
|
||||
+ Deref<Target: Deref<Target = [I::GenericArg]>>
|
||||
{
|
||||
fn type_at(self, i: usize) -> I::Ty;
|
||||
|
||||
@ -83,3 +89,22 @@ pub trait BoundVars<I: Interner> {
|
||||
|
||||
fn has_no_bound_vars(&self) -> bool;
|
||||
}
|
||||
|
||||
// FIXME: Uplift `AliasTy`
|
||||
pub trait AliasTy<I: Interner>: Copy + DebugWithInfcx<I> + Hash + Eq + Sized {
|
||||
fn new(
|
||||
interner: I,
|
||||
trait_def_id: I::DefId,
|
||||
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||
) -> Self;
|
||||
|
||||
fn def_id(self) -> I::DefId;
|
||||
|
||||
fn args(self) -> I::GenericArgs;
|
||||
|
||||
fn trait_def_id(self, interner: I) -> I::DefId;
|
||||
|
||||
fn self_ty(self) -> I::Ty;
|
||||
|
||||
fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
|
||||
}
|
||||
|
@ -5,9 +5,23 @@
|
||||
use crate::inherent::*;
|
||||
use crate::ir_print::IrPrint;
|
||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||
use crate::{CanonicalVarInfo, DebugWithInfcx, TraitRef};
|
||||
use crate::{
|
||||
CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef,
|
||||
NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
|
||||
};
|
||||
|
||||
pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
|
||||
pub trait Interner:
|
||||
Sized
|
||||
+ Copy
|
||||
+ IrPrint<TraitRef<Self>>
|
||||
+ IrPrint<TraitPredicate<Self>>
|
||||
+ IrPrint<ExistentialTraitRef<Self>>
|
||||
+ IrPrint<ExistentialProjection<Self>>
|
||||
+ IrPrint<ProjectionPredicate<Self>>
|
||||
+ IrPrint<NormalizesTo<Self>>
|
||||
+ IrPrint<SubtypePredicate<Self>>
|
||||
+ IrPrint<CoercePredicate<Self>>
|
||||
{
|
||||
type DefId: Copy + Debug + Hash + Eq;
|
||||
type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
|
||||
type AdtDef: Copy + Debug + Hash + Eq;
|
||||
@ -25,7 +39,7 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
|
||||
// Kinds of tys
|
||||
type Ty: Ty<Self>;
|
||||
type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
|
||||
type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq;
|
||||
type AliasTy: AliasTy<Self>;
|
||||
type ParamTy: Copy + Debug + Hash + Eq;
|
||||
type BoundTy: Copy + Debug + Hash + Eq;
|
||||
type PlaceholderTy: PlaceholderLike;
|
||||
@ -71,11 +85,15 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> {
|
||||
type GenericsOf: GenericsOf<Self>;
|
||||
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
|
||||
|
||||
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
|
||||
|
||||
fn check_and_mk_args(
|
||||
self,
|
||||
def_id: Self::DefId,
|
||||
args: impl IntoIterator<Item: Into<Self::GenericArg>>,
|
||||
) -> Self::GenericArgs;
|
||||
|
||||
fn parent(self, def_id: Self::DefId) -> Self::DefId;
|
||||
}
|
||||
|
||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||
|
@ -1,6 +1,9 @@
|
||||
use std::fmt;
|
||||
|
||||
use crate::{Interner, TraitRef};
|
||||
use crate::{
|
||||
CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo,
|
||||
ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef,
|
||||
};
|
||||
|
||||
pub trait IrPrint<T> {
|
||||
fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
@ -15,7 +18,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<I as IrPrint<$ty<I>>>::print(self, fmt)
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! define_debug_via_print {
|
||||
($($ty:ident),+ $(,)?) => {
|
||||
$(
|
||||
impl<I: Interner> fmt::Debug for $ty<I> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<I as IrPrint<$ty<I>>>::print_debug(self, fmt)
|
||||
@ -25,4 +34,15 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
define_display_via_print!(TraitRef,);
|
||||
define_display_via_print!(
|
||||
TraitRef,
|
||||
TraitPredicate,
|
||||
ExistentialTraitRef,
|
||||
ExistentialProjection,
|
||||
ProjectionPredicate,
|
||||
NormalizesTo,
|
||||
SubtypePredicate,
|
||||
CoercePredicate,
|
||||
);
|
||||
|
||||
define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
|
||||
|
@ -37,9 +37,9 @@
|
||||
mod flags;
|
||||
mod infcx;
|
||||
mod interner;
|
||||
mod predicate;
|
||||
mod predicate_kind;
|
||||
mod region_kind;
|
||||
mod trait_ref;
|
||||
|
||||
pub use canonical::*;
|
||||
#[cfg(feature = "nightly")]
|
||||
@ -49,9 +49,9 @@
|
||||
pub use flags::*;
|
||||
pub use infcx::InferCtxtLike;
|
||||
pub use interner::*;
|
||||
pub use predicate::*;
|
||||
pub use predicate_kind::*;
|
||||
pub use region_kind::*;
|
||||
pub use trait_ref::*;
|
||||
pub use ty_info::*;
|
||||
pub use ty_kind::*;
|
||||
pub use AliasKind::*;
|
||||
|
@ -53,4 +53,5 @@ fn visit_with<F: $crate::visit::TypeVisitor<I>>(
|
||||
crate::UniverseIndex,
|
||||
rustc_ast_ir::Mutability,
|
||||
rustc_ast_ir::Movability,
|
||||
crate::PredicatePolarity,
|
||||
}
|
||||
|
434
compiler/rustc_type_ir/src/predicate.rs
Normal file
434
compiler/rustc_type_ir/src/predicate.rs
Normal file
@ -0,0 +1,434 @@
|
||||
use std::fmt;
|
||||
|
||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::inherent::*;
|
||||
use crate::visit::TypeVisitableExt as _;
|
||||
use crate::{DebugWithInfcx, Interner};
|
||||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where-clause:
|
||||
/// ```ignore (illustrative)
|
||||
/// T: Foo<U>
|
||||
/// ```
|
||||
/// This would be represented by a trait-reference where the `DefId` is the
|
||||
/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
|
||||
/// and `U` as parameter 1.
|
||||
///
|
||||
/// Trait references also appear in object types like `Foo<U>`, but in
|
||||
/// that case the `Self` parameter is absent from the generic parameters.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct TraitRef<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
pub args: I::GenericArgs,
|
||||
/// This field exists to prevent the creation of `TraitRef` without
|
||||
/// calling [`TraitRef::new`].
|
||||
_use_trait_ref_new_instead: (),
|
||||
}
|
||||
|
||||
impl<I: Interner> TraitRef<I> {
|
||||
pub fn new(
|
||||
interner: I,
|
||||
trait_def_id: I::DefId,
|
||||
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||
) -> Self {
|
||||
let args = interner.check_and_mk_args(trait_def_id, args);
|
||||
Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
|
||||
let generics = interner.generics_of(trait_id);
|
||||
TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
|
||||
}
|
||||
|
||||
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
|
||||
/// are the parameters defined on trait.
|
||||
pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
|
||||
TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
||||
TraitRef::new(
|
||||
interner,
|
||||
self.def_id,
|
||||
[self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn self_ty(&self) -> I::Ty {
|
||||
self.args.type_at(0)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct TraitPredicate<I: Interner> {
|
||||
pub trait_ref: TraitRef<I>,
|
||||
|
||||
/// If polarity is Positive: we are proving that the trait is implemented.
|
||||
///
|
||||
/// If polarity is Negative: we are proving that a negative impl of this trait
|
||||
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
||||
/// exist via a series of predicates.)
|
||||
///
|
||||
/// If polarity is Reserved: that's a bug.
|
||||
pub polarity: PredicatePolarity,
|
||||
}
|
||||
|
||||
impl<I: Interner> TraitPredicate<I> {
|
||||
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
||||
Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity }
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> I::DefId {
|
||||
self.trait_ref.def_id
|
||||
}
|
||||
|
||||
pub fn self_ty(self) -> I::Ty {
|
||||
self.trait_ref.self_ty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for TraitPredicate<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// FIXME(effects) printing?
|
||||
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum ImplPolarity {
|
||||
/// `impl Trait for Type`
|
||||
Positive,
|
||||
/// `impl !Trait for Type`
|
||||
Negative,
|
||||
/// `#[rustc_reservation_impl] impl Trait for Type`
|
||||
///
|
||||
/// This is a "stability hack", not a real Rust feature.
|
||||
/// See #64631 for details.
|
||||
Reservation,
|
||||
}
|
||||
|
||||
impl fmt::Display for ImplPolarity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Positive => f.write_str("positive"),
|
||||
Self::Negative => f.write_str("negative"),
|
||||
Self::Reservation => f.write_str("reservation"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Polarity for a trait predicate. May either be negative or positive.
|
||||
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
||||
/// "reservation" level.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum PredicatePolarity {
|
||||
/// `Type: Trait`
|
||||
Positive,
|
||||
/// `Type: !Trait`
|
||||
Negative,
|
||||
}
|
||||
|
||||
impl PredicatePolarity {
|
||||
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
||||
pub fn flip(&self) -> PredicatePolarity {
|
||||
match self {
|
||||
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
||||
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PredicatePolarity {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Positive => f.write_str("positive"),
|
||||
Self::Negative => f.write_str("negative"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum ExistentialPredicate<I: Interner> {
|
||||
/// E.g., `Iterator`.
|
||||
Trait(ExistentialTraitRef<I>),
|
||||
/// E.g., `Iterator::Item = T`.
|
||||
Projection(ExistentialProjection<I>),
|
||||
/// E.g., `Send`.
|
||||
AutoTrait(I::DefId),
|
||||
}
|
||||
|
||||
// FIXME: Implement this the right way after
|
||||
impl<I: Interner> DebugWithInfcx<I> for ExistentialPredicate<I> {
|
||||
fn fmt<Infcx: rustc_type_ir::InferCtxtLike<Interner = I>>(
|
||||
this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>,
|
||||
f: &mut fmt::Formatter<'_>,
|
||||
) -> fmt::Result {
|
||||
fmt::Debug::fmt(&this.data, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// An existential reference to a trait, where `Self` is erased.
|
||||
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
||||
/// ```ignore (illustrative)
|
||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||
/// ```
|
||||
/// The generic parameters don't include the erased `Self`, only trait
|
||||
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct ExistentialTraitRef<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
pub args: I::GenericArgs,
|
||||
}
|
||||
|
||||
impl<I: Interner> ExistentialTraitRef<I> {
|
||||
pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
|
||||
// Assert there is a Self.
|
||||
trait_ref.args.type_at(0);
|
||||
|
||||
ExistentialTraitRef {
|
||||
def_id: trait_ref.def_id,
|
||||
args: interner.mk_args(&trait_ref.args[1..]),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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, interner: I, self_ty: I::Ty) -> TraitRef<I> {
|
||||
// otherwise the escaping vars would be captured by the binder
|
||||
// debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||
|
||||
TraitRef::new(
|
||||
interner,
|
||||
self.def_id,
|
||||
[self_ty.into()].into_iter().chain(self.args.into_iter()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct ExistentialProjection<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
pub args: I::GenericArgs,
|
||||
pub term: I::Term,
|
||||
}
|
||||
|
||||
impl<I: Interner> ExistentialProjection<I> {
|
||||
/// Extracts the underlying existential trait reference from this projection.
|
||||
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
|
||||
/// then this function would return an `exists T. T: Iterator` existential trait
|
||||
/// reference.
|
||||
pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef<I> {
|
||||
let def_id = tcx.parent(self.def_id);
|
||||
let args_count = tcx.generics_of(def_id).count() - 1;
|
||||
let args = tcx.mk_args(&self.args[..args_count]);
|
||||
ExistentialTraitRef { def_id, args }
|
||||
}
|
||||
|
||||
pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
|
||||
// otherwise the escaping regions would be captured by the binders
|
||||
debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||
|
||||
ProjectionPredicate {
|
||||
projection_ty: I::AliasTy::new(
|
||||
tcx,
|
||||
self.def_id,
|
||||
[self_ty.into()].into_iter().chain(self.args),
|
||||
),
|
||||
term: self.term,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate<I>) -> Self {
|
||||
// Assert there is a Self.
|
||||
projection_predicate.projection_ty.args().type_at(0);
|
||||
|
||||
Self {
|
||||
def_id: projection_predicate.projection_ty.def_id(),
|
||||
args: tcx.mk_args(&projection_predicate.projection_ty.args()[1..]),
|
||||
term: projection_predicate.term,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This kind of predicate has no *direct* correspondent in the
|
||||
/// syntax, but it roughly corresponds to the syntactic forms:
|
||||
///
|
||||
/// 1. `T: TraitRef<..., Item = Type>`
|
||||
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
|
||||
///
|
||||
/// In particular, form #1 is "desugared" to the combination of a
|
||||
/// normal trait predicate (`T: TraitRef<...>`) and one of these
|
||||
/// predicates. Form #2 is a broader form in that it also permits
|
||||
/// equality between arbitrary types. Processing an instance of
|
||||
/// Form #2 eventually yields one of these `ProjectionPredicate`
|
||||
/// instances to normalize the LHS.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct ProjectionPredicate<I: Interner> {
|
||||
pub projection_ty: I::AliasTy,
|
||||
pub term: I::Term,
|
||||
}
|
||||
|
||||
impl<I: Interner> ProjectionPredicate<I> {
|
||||
pub fn self_ty(self) -> I::Ty {
|
||||
self.projection_ty.self_ty()
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
|
||||
Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn trait_def_id(self, tcx: I) -> I::DefId {
|
||||
self.projection_ty.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> I::DefId {
|
||||
self.projection_ty.def_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
|
||||
/// proven by actually normalizing `alias`.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct NormalizesTo<I: Interner> {
|
||||
pub alias: I::AliasTy,
|
||||
pub term: I::Term,
|
||||
}
|
||||
|
||||
impl<I: Interner> NormalizesTo<I> {
|
||||
pub fn self_ty(self) -> I::Ty {
|
||||
self.alias.self_ty()
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo<I> {
|
||||
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn trait_def_id(self, tcx: I) -> I::DefId {
|
||||
self.alias.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> I::DefId {
|
||||
self.alias.def_id()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> fmt::Debug for NormalizesTo<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
|
||||
/// whether the `a` type is the type that we should label as "expected" when
|
||||
/// presenting user diagnostics.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct SubtypePredicate<I: Interner> {
|
||||
pub a_is_expected: bool,
|
||||
pub a: I::Ty,
|
||||
pub b: I::Ty,
|
||||
}
|
||||
|
||||
/// Encodes that we have to coerce *from* the `a` type to the `b` type.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = ""),
|
||||
Debug(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct CoercePredicate<I: Interner> {
|
||||
pub a: I::Ty,
|
||||
pub b: I::Ty,
|
||||
}
|
@ -1,17 +1,15 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use std::fmt;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
|
||||
/// A clause is something that can appear in where bounds or be inferred
|
||||
/// by implied bounds.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum ClauseKind<I: Interner> {
|
||||
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
|
||||
@ -55,61 +53,6 @@ fn eq(&self, other: &Self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for ClauseKind<I> {}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
I::Const: TypeFoldable<I>,
|
||||
I::GenericArg: TypeFoldable<I>,
|
||||
I::TraitPredicate: TypeFoldable<I>,
|
||||
I::ProjectionPredicate: TypeFoldable<I>,
|
||||
I::TypeOutlivesPredicate: TypeFoldable<I>,
|
||||
I::RegionOutlivesPredicate: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
ClauseKind::Trait(p) => ClauseKind::Trait(p.try_fold_with(folder)?),
|
||||
ClauseKind::RegionOutlives(p) => ClauseKind::RegionOutlives(p.try_fold_with(folder)?),
|
||||
ClauseKind::TypeOutlives(p) => ClauseKind::TypeOutlives(p.try_fold_with(folder)?),
|
||||
ClauseKind::Projection(p) => ClauseKind::Projection(p.try_fold_with(folder)?),
|
||||
ClauseKind::ConstArgHasType(c, t) => {
|
||||
ClauseKind::ConstArgHasType(c.try_fold_with(folder)?, t.try_fold_with(folder)?)
|
||||
}
|
||||
ClauseKind::WellFormed(p) => ClauseKind::WellFormed(p.try_fold_with(folder)?),
|
||||
ClauseKind::ConstEvaluatable(p) => {
|
||||
ClauseKind::ConstEvaluatable(p.try_fold_with(folder)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for ClauseKind<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
I::Const: TypeVisitable<I>,
|
||||
I::GenericArg: TypeVisitable<I>,
|
||||
I::TraitPredicate: TypeVisitable<I>,
|
||||
I::ProjectionPredicate: TypeVisitable<I>,
|
||||
I::TypeOutlivesPredicate: TypeVisitable<I>,
|
||||
I::RegionOutlivesPredicate: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self {
|
||||
ClauseKind::Trait(p) => p.visit_with(visitor),
|
||||
ClauseKind::RegionOutlives(p) => p.visit_with(visitor),
|
||||
ClauseKind::TypeOutlives(p) => p.visit_with(visitor),
|
||||
ClauseKind::Projection(p) => p.visit_with(visitor),
|
||||
ClauseKind::ConstArgHasType(c, t) => {
|
||||
try_visit!(c.visit_with(visitor));
|
||||
t.visit_with(visitor)
|
||||
}
|
||||
ClauseKind::WellFormed(p) => p.visit_with(visitor),
|
||||
ClauseKind::ConstEvaluatable(p) => p.visit_with(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
@ -118,6 +61,7 @@ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum PredicateKind<I: Interner> {
|
||||
/// Prove a clause
|
||||
@ -167,69 +111,6 @@ pub enum PredicateKind<I: Interner> {
|
||||
AliasRelate(I::Term, I::Term, AliasRelationDirection),
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
|
||||
where
|
||||
I::DefId: TypeFoldable<I>,
|
||||
I::Const: TypeFoldable<I>,
|
||||
I::GenericArgs: TypeFoldable<I>,
|
||||
I::Term: TypeFoldable<I>,
|
||||
I::CoercePredicate: TypeFoldable<I>,
|
||||
I::SubtypePredicate: TypeFoldable<I>,
|
||||
I::NormalizesTo: TypeFoldable<I>,
|
||||
ClauseKind<I>: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?),
|
||||
PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?),
|
||||
PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?),
|
||||
PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?),
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?)
|
||||
}
|
||||
PredicateKind::Ambiguous => PredicateKind::Ambiguous,
|
||||
PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?),
|
||||
PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate(
|
||||
a.try_fold_with(folder)?,
|
||||
b.try_fold_with(folder)?,
|
||||
d.try_fold_with(folder)?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for PredicateKind<I>
|
||||
where
|
||||
I::DefId: TypeVisitable<I>,
|
||||
I::Const: TypeVisitable<I>,
|
||||
I::GenericArgs: TypeVisitable<I>,
|
||||
I::Term: TypeVisitable<I>,
|
||||
I::CoercePredicate: TypeVisitable<I>,
|
||||
I::SubtypePredicate: TypeVisitable<I>,
|
||||
I::NormalizesTo: TypeVisitable<I>,
|
||||
ClauseKind<I>: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self {
|
||||
PredicateKind::Clause(p) => p.visit_with(visitor),
|
||||
PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
|
||||
PredicateKind::Subtype(s) => s.visit_with(visitor),
|
||||
PredicateKind::Coerce(s) => s.visit_with(visitor),
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
try_visit!(a.visit_with(visitor));
|
||||
b.visit_with(visitor)
|
||||
}
|
||||
PredicateKind::Ambiguous => V::Result::output(),
|
||||
PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
|
||||
PredicateKind::AliasRelate(a, b, d) => {
|
||||
try_visit!(a.visit_with(visitor));
|
||||
try_visit!(b.visit_with(visitor));
|
||||
d.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))]
|
||||
pub enum AliasRelationDirection {
|
||||
|
@ -115,7 +115,7 @@
|
||||
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
|
||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
|
||||
pub enum RegionKind<I: Interner> {
|
||||
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
|
||||
@ -208,9 +208,6 @@ fn eq(&self, other: &RegionKind<I>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Eq`
|
||||
impl<I: Interner> Eq for RegionKind<I> {}
|
||||
|
||||
impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
|
||||
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
|
@ -1,109 +0,0 @@
|
||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::inherent::*;
|
||||
use crate::lift::Lift;
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
/// but perhaps the most recognizable form is in a where-clause:
|
||||
/// ```ignore (illustrative)
|
||||
/// T: Foo<U>
|
||||
/// ```
|
||||
/// This would be represented by a trait-reference where the `DefId` is the
|
||||
/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
|
||||
/// and `U` as parameter 1.
|
||||
///
|
||||
/// Trait references also appear in object types like `Foo<U>`, but in
|
||||
/// that case the `Self` parameter is absent from the generic parameters.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct TraitRef<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
pub args: I::GenericArgs,
|
||||
/// This field exists to prevent the creation of `TraitRef` without
|
||||
/// calling [`TraitRef::new`].
|
||||
_use_trait_ref_new_instead: (),
|
||||
}
|
||||
|
||||
impl<I: Interner> TraitRef<I> {
|
||||
pub fn new(
|
||||
interner: I,
|
||||
trait_def_id: I::DefId,
|
||||
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||
) -> Self {
|
||||
let args = interner.check_and_mk_args(trait_def_id, args);
|
||||
Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
|
||||
}
|
||||
|
||||
pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
|
||||
let generics = interner.generics_of(trait_id);
|
||||
TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
|
||||
}
|
||||
|
||||
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
|
||||
/// are the parameters defined on trait.
|
||||
pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
|
||||
TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
||||
TraitRef::new(
|
||||
interner,
|
||||
self.def_id,
|
||||
[self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn self_ty(&self) -> I::Ty {
|
||||
self.args.type_at(0)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(compiler-errors): Make this into a `Lift_Generic` impl.
|
||||
impl<I: Interner, U: Interner> Lift<U> for TraitRef<I>
|
||||
where
|
||||
I::DefId: Lift<U, Lifted = U::DefId>,
|
||||
I::GenericArgs: Lift<U, Lifted = U::GenericArgs>,
|
||||
{
|
||||
type Lifted = TraitRef<U>;
|
||||
|
||||
fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
|
||||
Some(TraitRef {
|
||||
def_id: self.def_id.lift_to_tcx(tcx)?,
|
||||
args: self.args.lift_to_tcx(tcx)?,
|
||||
_use_trait_ref_new_instead: (),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for TraitRef<I>
|
||||
where
|
||||
I::GenericArgs: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.args.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for TraitRef<I>
|
||||
where
|
||||
I::GenericArgs: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(TraitRef {
|
||||
def_id: self.def_id,
|
||||
args: self.args.try_fold_with(folder)?,
|
||||
_use_trait_ref_new_instead: (),
|
||||
})
|
||||
}
|
||||
}
|
@ -1,14 +1,12 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use std::fmt;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||
|
||||
@ -65,7 +63,7 @@ pub fn descr(self) -> &'static str {
|
||||
/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
|
||||
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum TyKind<I: Interner> {
|
||||
/// The primitive boolean type. Written as `bool`.
|
||||
@ -341,9 +339,6 @@ fn eq(&self, other: &TyKind<I>) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Eq`
|
||||
impl<I: Interner> Eq for TyKind<I> {}
|
||||
|
||||
impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
|
||||
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
@ -804,29 +799,8 @@ fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||
Debug(bound = "")
|
||||
)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
pub struct TypeAndMut<I: Interner> {
|
||||
pub ty: I::Ty,
|
||||
pub mutbl: Mutability,
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for TypeAndMut<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(TypeAndMut {
|
||||
ty: self.ty.try_fold_with(folder)?,
|
||||
mutbl: self.mutbl.try_fold_with(folder)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for TypeAndMut<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
try_visit!(self.ty.visit_with(visitor));
|
||||
self.mutbl.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
15
compiler/rustc_type_ir_macros/Cargo.toml
Normal file
15
compiler/rustc_type_ir_macros/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "rustc_type_ir_macros"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2.0.9", features = ["full"] }
|
||||
synstructure = "0.13.0"
|
||||
# tidy-alphabetical-end
|
159
compiler/rustc_type_ir_macros/src/lib.rs
Normal file
159
compiler/rustc_type_ir_macros/src/lib.rs
Normal file
@ -0,0 +1,159 @@
|
||||
use quote::quote;
|
||||
use syn::{parse_quote, visit_mut::VisitMut};
|
||||
use synstructure::decl_derive;
|
||||
|
||||
decl_derive!(
|
||||
[TypeFoldable_Generic] => type_foldable_derive
|
||||
);
|
||||
decl_derive!(
|
||||
[TypeVisitable_Generic] => type_visitable_derive
|
||||
);
|
||||
decl_derive!(
|
||||
[Lift_Generic] => lift_derive
|
||||
);
|
||||
|
||||
fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
|
||||
s.add_impl_generic(parse_quote! { I });
|
||||
}
|
||||
|
||||
s.add_where_predicate(parse_quote! { I: Interner });
|
||||
s.add_bounds(synstructure::AddBounds::Fields);
|
||||
s.bind_with(|_| synstructure::BindStyle::Move);
|
||||
let body_fold = s.each_variant(|vi| {
|
||||
let bindings = vi.bindings();
|
||||
vi.construct(|_, index| {
|
||||
let bind = &bindings[index];
|
||||
quote! {
|
||||
::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
s.bound_impl(
|
||||
quote!(::rustc_type_ir::fold::TypeFoldable<I>),
|
||||
quote! {
|
||||
fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
|
||||
self,
|
||||
__folder: &mut __F
|
||||
) -> Result<Self, __F::Error> {
|
||||
Ok(match self { #body_fold })
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
|
||||
s.add_impl_generic(parse_quote! { I });
|
||||
}
|
||||
|
||||
s.add_bounds(synstructure::AddBounds::None);
|
||||
s.add_where_predicate(parse_quote! { I: Interner });
|
||||
s.add_impl_generic(parse_quote! { J });
|
||||
s.add_where_predicate(parse_quote! { J: Interner });
|
||||
|
||||
let mut wc = vec![];
|
||||
s.bind_with(|_| synstructure::BindStyle::Move);
|
||||
let body_fold = s.each_variant(|vi| {
|
||||
let bindings = vi.bindings();
|
||||
vi.construct(|field, index| {
|
||||
let ty = field.ty.clone();
|
||||
let lifted_ty = lift(ty.clone());
|
||||
wc.push(parse_quote! { #ty: ::rustc_type_ir::lift::Lift<J, Lifted = #lifted_ty> });
|
||||
let bind = &bindings[index];
|
||||
quote! {
|
||||
#bind.lift_to_tcx(interner)?
|
||||
}
|
||||
})
|
||||
});
|
||||
for wc in wc {
|
||||
s.add_where_predicate(wc);
|
||||
}
|
||||
|
||||
let (_, ty_generics, _) = s.ast().generics.split_for_impl();
|
||||
let name = s.ast().ident.clone();
|
||||
let self_ty: syn::Type = parse_quote! { #name #ty_generics };
|
||||
let lifted_ty = lift(self_ty);
|
||||
|
||||
s.bound_impl(
|
||||
quote!(::rustc_type_ir::lift::Lift<J>),
|
||||
quote! {
|
||||
type Lifted = #lifted_ty;
|
||||
|
||||
fn lift_to_tcx(
|
||||
self,
|
||||
interner: J,
|
||||
) -> Option<Self::Lifted> {
|
||||
Some(match self { #body_fold })
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn lift(mut ty: syn::Type) -> syn::Type {
|
||||
struct ItoJ;
|
||||
impl VisitMut for ItoJ {
|
||||
fn visit_type_path_mut(&mut self, i: &mut syn::TypePath) {
|
||||
if i.qself.is_none() {
|
||||
if let Some(first) = i.path.segments.first_mut() {
|
||||
if first.ident == "I" {
|
||||
*first = parse_quote! { J };
|
||||
}
|
||||
}
|
||||
}
|
||||
syn::visit_mut::visit_type_path_mut(self, i);
|
||||
}
|
||||
}
|
||||
|
||||
ItoJ.visit_type_mut(&mut ty);
|
||||
|
||||
ty
|
||||
}
|
||||
|
||||
fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
|
||||
s.add_impl_generic(parse_quote! { I });
|
||||
}
|
||||
|
||||
s.add_where_predicate(parse_quote! { I: Interner });
|
||||
s.add_bounds(synstructure::AddBounds::Fields);
|
||||
let body_visit = s.each(|bind| {
|
||||
quote! {
|
||||
match ::rustc_ast_ir::visit::VisitorResult::branch(
|
||||
::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
|
||||
) {
|
||||
::core::ops::ControlFlow::Continue(()) => {},
|
||||
::core::ops::ControlFlow::Break(r) => {
|
||||
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
s.bind_with(|_| synstructure::BindStyle::Move);
|
||||
|
||||
s.bound_impl(
|
||||
quote!(::rustc_type_ir::visit::TypeVisitable<I>),
|
||||
quote! {
|
||||
fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
|
||||
&self,
|
||||
__visitor: &mut __V
|
||||
) -> __V::Result {
|
||||
match *self { #body_visit }
|
||||
<__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user