blob: de0f633c449ee2bb067c2391154291b31f828182 [file] [log] [blame]
//! Contains the definition for the "Rust IR" -- this is basically a "lowered"
//! version of the AST, roughly corresponding to [the HIR] in the Rust
//! compiler.
use chalk_derive::{HasInterner, TypeFoldable, TypeVisitable};
use chalk_ir::cast::Cast;
use chalk_ir::fold::shift::Shift;
use chalk_ir::interner::Interner;
use chalk_ir::{
try_break, visit::TypeVisitable, AdtId, AliasEq, AliasTy, AssocTypeId, Binders, DebruijnIndex,
FnDefId, GenericArg, ImplId, OpaqueTyId, ProjectionTy, QuantifiedWhereClause, Substitution,
ToGenericArg, TraitId, TraitRef, Ty, TyKind, VariableKind, WhereClause, WithKind,
};
use std::iter;
use std::ops::ControlFlow;
/// Identifier for an "associated type value" found in some impl.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AssociatedTyValueId<I: Interner>(pub I::DefId);
chalk_ir::id_visit!(AssociatedTyValueId);
chalk_ir::id_fold!(AssociatedTyValueId);
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable)]
pub struct ImplDatum<I: Interner> {
pub polarity: Polarity,
pub binders: Binders<ImplDatumBound<I>>,
pub impl_type: ImplType,
pub associated_ty_value_ids: Vec<AssociatedTyValueId<I>>,
}
impl<I: Interner> ImplDatum<I> {
pub fn is_positive(&self) -> bool {
self.polarity.is_positive()
}
pub fn trait_id(&self) -> TraitId<I> {
self.binders.skip_binders().trait_ref.trait_id
}
pub fn self_type_adt_id(&self, interner: I) -> Option<AdtId<I>> {
match self
.binders
.skip_binders()
.trait_ref
.self_type_parameter(interner)
.kind(interner)
{
TyKind::Adt(id, _) => Some(*id),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, TypeFoldable, TypeVisitable)]
pub struct ImplDatumBound<I: Interner> {
pub trait_ref: TraitRef<I>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ImplType {
Local,
External,
}
chalk_ir::const_visit!(ImplType);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DefaultImplDatum<I: Interner> {
pub binders: Binders<DefaultImplDatumBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner)]
pub struct DefaultImplDatumBound<I: Interner> {
pub trait_ref: TraitRef<I>,
pub accessible_tys: Vec<Ty<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable)]
pub struct AdtDatum<I: Interner> {
pub binders: Binders<AdtDatumBound<I>>,
pub id: AdtId<I>,
pub flags: AdtFlags,
pub kind: AdtKind,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum AdtKind {
Struct,
Enum,
Union,
}
chalk_ir::const_visit!(AdtKind);
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
pub struct AdtDatumBound<I: Interner> {
pub variants: Vec<AdtVariantDatum<I>>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
pub struct AdtVariantDatum<I: Interner> {
pub fields: Vec<Ty<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AdtFlags {
pub upstream: bool,
pub fundamental: bool,
pub phantom_data: bool,
}
chalk_ir::const_visit!(AdtFlags);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AdtRepr<I: Interner> {
pub c: bool,
pub packed: bool,
pub int: Option<chalk_ir::Ty<I>>,
}
/// Information about the size and alignment of an ADT.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AdtSizeAlign {
one_zst: bool,
}
impl AdtSizeAlign {
pub fn from_one_zst(one_zst: bool) -> AdtSizeAlign {
AdtSizeAlign { one_zst }
}
pub fn one_zst(&self) -> bool {
self.one_zst
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// A rust intermediate represention (rust_ir) of a function definition/declaration.
/// For example, in the following rust code:
///
/// ```ignore
/// fn foo<T>() -> i32 where T: Eq;
/// ```
///
/// This would represent the declaration of `foo`.
///
/// Note this is distinct from a function pointer, which points to
/// a function with a given type signature, whereas this represents
/// a specific function definition.
pub struct FnDefDatum<I: Interner> {
pub id: FnDefId<I>,
pub sig: chalk_ir::FnSig<I>,
pub binders: Binders<FnDefDatumBound<I>>,
}
/// Avoids visiting `I::FnAbi`
impl<I: Interner> TypeVisitable<I> for FnDefDatum<I> {
fn visit_with<B>(
&self,
visitor: &mut dyn chalk_ir::visit::TypeVisitor<I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<B> {
try_break!(self.id.visit_with(visitor, outer_binder));
self.binders.visit_with(visitor, outer_binder)
}
}
/// Represents the inputs and outputs on a `FnDefDatum`. This is split
/// from the where clauses, since these can contain bound lifetimes.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
pub struct FnDefInputsAndOutputDatum<I: Interner> {
/// Types of the function's arguments
/// ```ignore
/// fn foo<T>(bar: i32, baz: T);
/// ^^^ ^
/// ```
///
pub argument_types: Vec<Ty<I>>,
/// Return type of the function
/// ```ignore
/// fn foo<T>() -> i32;
/// ^^^
/// ```
pub return_type: Ty<I>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
/// Represents the bounds on a `FnDefDatum`, including
/// the function definition's type signature and where clauses.
pub struct FnDefDatumBound<I: Interner> {
/// Inputs and outputs defined on a function
/// These are needed for late-bound regions in rustc. For example the
/// lifetime `'a` in
/// ```ignore
/// fn foo<'a, T>(&'a T);
/// ^^
/// ```
/// Rustc doesn't pass in late-bound the regions in substs, but the inputs
/// and outputs may use them. `where_clauses` don't need an extra set of
/// `Binders`, since any lifetimes found in where clauses are not late-bound.
///
/// For more information, see [this rustc-dev-guide chapter](https://rustc-dev-guide.rust-lang.org/early-late-bound.html).
pub inputs_and_output: Binders<FnDefInputsAndOutputDatum<I>>,
/// Where clauses defined on the function
/// ```ignore
/// fn foo<T>() where T: Eq;
/// ^^^^^^^^^^^
/// ```
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
/// A rust intermediate representation (rust_ir) of a Trait Definition. For
/// example, given the following rust code:
///
/// ```
/// use std::fmt::Debug;
///
/// trait Foo<T>
/// where
/// T: Debug,
/// {
/// type Bar<U>;
/// }
/// ```
///
/// This would represent the `trait Foo` declaration. Note that the details of
/// the trait members (e.g., the associated type declaration (`type Bar<U>`) are
/// not contained in this type, and are represented separately (e.g., in
/// [`AssociatedTyDatum`]).
///
/// Not to be confused with the rust_ir for a Trait Implementation, which is
/// represented by [`ImplDatum`]
///
/// [`ImplDatum`]: struct.ImplDatum.html
/// [`AssociatedTyDatum`]: struct.AssociatedTyDatum.html
#[derive(TypeVisitable)]
pub struct TraitDatum<I: Interner> {
pub id: TraitId<I>,
pub binders: Binders<TraitDatumBound<I>>,
/// "Flags" indicate special kinds of traits, like auto traits.
/// In Rust syntax these are represented in different ways, but in
/// chalk we add annotations like `#[auto]`.
pub flags: TraitFlags,
pub associated_ty_ids: Vec<AssocTypeId<I>>,
/// If this is a well-known trait, which one? If `None`, this is a regular,
/// user-defined trait.
pub well_known: Option<WellKnownTrait>,
}
/// A list of the traits that are "well known" to chalk, which means that
/// the chalk-solve crate has special, hard-coded impls for them.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum WellKnownTrait {
Sized,
Copy,
Clone,
Drop,
/// The trait `FnOnce<Args>` - the generic argument `Args` is always a tuple
/// corresponding to the arguments of a function implementing this trait.
/// E.g. `fn(u8, bool): FnOnce<(u8, bool)>`
FnOnce,
FnMut,
Fn,
Unsize,
Unpin,
CoerceUnsized,
DiscriminantKind,
Generator,
DispatchFromDyn,
Tuple,
Pointee,
FnPtr,
}
chalk_ir::const_visit!(WellKnownTrait);
impl<I: Interner> TraitDatum<I> {
pub fn is_auto_trait(&self) -> bool {
self.flags.auto
}
pub fn is_non_enumerable_trait(&self) -> bool {
self.flags.non_enumerable
}
pub fn is_coinductive_trait(&self) -> bool {
self.flags.coinductive
}
/// Gives access to the where clauses of the trait, quantified over the type parameters of the trait:
///
/// ```ignore
/// trait Foo<T> where T: Debug { }
/// ^^^^^^^^^^^^^^
/// ```
pub fn where_clauses(&self) -> Binders<&Vec<QuantifiedWhereClause<I>>> {
self.binders.as_ref().map(|td| &td.where_clauses)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, TypeVisitable)]
pub struct TraitDatumBound<I: Interner> {
/// Where clauses defined on the trait:
///
/// ```ignore
/// trait Foo<T> where T: Debug { }
/// ^^^^^^^^^^^^^^
/// ```
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TraitFlags {
/// An "auto trait" is one that is "automatically implemented" for every
/// struct, so long as no explicit impl is given.
///
/// Examples are `Send` and `Sync`.
pub auto: bool,
pub marker: bool,
/// Indicate that a trait is defined upstream (in a dependency), used during
/// coherence checking.
pub upstream: bool,
/// A fundamental trait is a trait where adding an impl for an existing type
/// is considered a breaking change. Examples of fundamental traits are the
/// closure traits like `Fn` and `FnMut`.
///
/// As of this writing (2020-03-27), fundamental traits are declared by the
/// unstable `#[fundamental]` attribute in rustc, and hence cannot appear
/// outside of the standard library.
pub fundamental: bool,
/// Indicates that chalk cannot list all of the implementations of the given
/// trait, likely because it is a publicly exported trait in a library.
///
/// Currently (2020-03-27) rustc and rust-analyzer mark all traits as
/// non_enumerable, and in the future it may become the only option.
pub non_enumerable: bool,
pub coinductive: bool,
}
chalk_ir::const_visit!(TraitFlags);
/// An inline bound, e.g. `: Foo<K>` in `impl<K, T: Foo<K>> SomeType<T>`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
pub enum InlineBound<I: Interner> {
TraitBound(TraitBound<I>),
AliasEqBound(AliasEqBound<I>),
}
#[allow(type_alias_bounds)]
pub type QuantifiedInlineBound<I: Interner> = Binders<InlineBound<I>>;
pub trait IntoWhereClauses<I: Interner> {
type Output;
fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<Self::Output>;
}
impl<I: Interner> IntoWhereClauses<I> for InlineBound<I> {
type Output = WhereClause<I>;
/// Applies the `InlineBound` to `self_ty` and lowers to a
/// [`chalk_ir::DomainGoal`].
///
/// Because an `InlineBound` does not know anything about what it's binding,
/// you must provide that type as `self_ty`.
fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
match self {
InlineBound::TraitBound(b) => b.into_where_clauses(interner, self_ty),
InlineBound::AliasEqBound(b) => b.into_where_clauses(interner, self_ty),
}
}
}
impl<I: Interner> IntoWhereClauses<I> for QuantifiedInlineBound<I> {
type Output = QuantifiedWhereClause<I>;
fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<QuantifiedWhereClause<I>> {
let self_ty = self_ty.shifted_in(interner);
self.map_ref(|b| b.into_where_clauses(interner, self_ty))
.into_iter()
.collect()
}
}
/// Represents a trait bound on e.g. a type or type parameter.
/// Does not know anything about what it's binding.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub struct TraitBound<I: Interner> {
pub trait_id: TraitId<I>,
pub args_no_self: Vec<GenericArg<I>>,
}
impl<I: Interner> TraitBound<I> {
fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
let trait_ref = self.as_trait_ref(interner, self_ty);
vec![WhereClause::Implemented(trait_ref)]
}
pub fn as_trait_ref(&self, interner: I, self_ty: Ty<I>) -> TraitRef<I> {
TraitRef {
trait_id: self.trait_id,
substitution: Substitution::from_iter(
interner,
iter::once(self_ty.cast(interner)).chain(self.args_no_self.iter().cloned()),
),
}
}
}
/// Represents an alias equality bound on e.g. a type or type parameter.
/// Does not know anything about what it's binding.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub struct AliasEqBound<I: Interner> {
pub trait_bound: TraitBound<I>,
pub associated_ty_id: AssocTypeId<I>,
/// Does not include trait parameters.
pub parameters: Vec<GenericArg<I>>,
pub value: Ty<I>,
}
impl<I: Interner> AliasEqBound<I> {
fn into_where_clauses(&self, interner: I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
let trait_ref = self.trait_bound.as_trait_ref(interner, self_ty);
let substitution = Substitution::from_iter(
interner,
self.parameters
.iter()
.cloned()
.chain(trait_ref.substitution.iter(interner).cloned()),
);
vec![
WhereClause::Implemented(trait_ref),
WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: self.associated_ty_id,
substitution,
}),
ty: self.value.clone(),
}),
]
}
}
pub trait Anonymize<I: Interner> {
/// Utility function that converts from a list of generic arguments
/// which *have* associated data (`WithKind<I, T>`) to a list of
/// "anonymous" generic parameters that just preserves their
/// kinds (`VariableKind<I>`). Often convenient in lowering.
fn anonymize(&self) -> Vec<VariableKind<I>>;
}
impl<I: Interner, T> Anonymize<I> for [WithKind<I, T>] {
fn anonymize(&self) -> Vec<VariableKind<I>> {
self.iter().map(|pk| pk.kind.clone()).collect()
}
}
/// Represents an associated type declaration found inside of a trait:
///
/// ```notrust
/// trait Foo<P1..Pn> { // P0 is Self
/// type Bar<Pn..Pm>: [bounds]
/// where
/// [where_clauses];
/// }
/// ```
///
/// The meaning of each of these parts:
///
/// * The *parameters* `P0...Pm` are all in scope for this associated type.
/// * The *bounds* `bounds` are things that the impl must prove to be true.
/// * The *where clauses* `where_clauses` are things that the impl can *assume* to be true
/// (but which projectors must prove).
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AssociatedTyDatum<I: Interner> {
/// The trait this associated type is defined in.
pub trait_id: TraitId<I>,
/// The ID of this associated type
pub id: AssocTypeId<I>,
/// Name of this associated type.
pub name: I::Identifier,
/// These binders represent the `P0...Pm` variables. The binders
/// are in the order `[Pn..Pm; P0..Pn]`. That is, the variables
/// from `Bar` come first (corresponding to the de bruijn concept
/// that "inner" binders are lower indices, although within a
/// given binder we do not have an ordering).
pub binders: Binders<AssociatedTyDatumBound<I>>,
}
// Manual implementation to avoid I::Identifier type.
impl<I: Interner> TypeVisitable<I> for AssociatedTyDatum<I> {
fn visit_with<B>(
&self,
visitor: &mut dyn chalk_ir::visit::TypeVisitor<I, BreakTy = B>,
outer_binder: DebruijnIndex,
) -> ControlFlow<B> {
try_break!(self.trait_id.visit_with(visitor, outer_binder));
try_break!(self.id.visit_with(visitor, outer_binder));
self.binders.visit_with(visitor, outer_binder)
}
}
/// Encodes the parts of `AssociatedTyDatum` where the parameters
/// `P0..Pm` are in scope (`bounds` and `where_clauses`).
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
pub struct AssociatedTyDatumBound<I: Interner> {
/// Bounds on the associated type itself.
///
/// These must be proven by the implementer, for all possible parameters that
/// would result in a well-formed projection.
pub bounds: Vec<QuantifiedInlineBound<I>>,
/// Where clauses that must hold for the projection to be well-formed.
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
impl<I: Interner> AssociatedTyDatum<I> {
/// Returns the associated ty's bounds applied to the projection type, e.g.:
///
/// ```notrust
/// Implemented(<?0 as Foo>::Item<?1>: Sized)
/// ```
///
/// these quantified where clauses are in the scope of the
/// `binders` field.
pub fn bounds_on_self(&self, interner: I) -> Vec<QuantifiedWhereClause<I>> {
let (binders, assoc_ty_datum) = self.binders.as_ref().into();
// Create a list `P0...Pn` of references to the binders in
// scope for this associated type:
let substitution = Substitution::from_iter(
interner,
binders
.iter(interner)
.enumerate()
.map(|p| p.to_generic_arg(interner)),
);
// The self type will be `<P0 as Foo<P1..Pn>>::Item<Pn..Pm>` etc
let self_ty = TyKind::Alias(AliasTy::Projection(ProjectionTy {
associated_ty_id: self.id,
substitution,
}))
.intern(interner);
// Now use that as the self type for the bounds, transforming
// something like `type Bar<Pn..Pm>: Debug` into
//
// ```
// <P0 as Foo<P1..Pn>>::Item<Pn..Pm>: Debug
// ```
assoc_ty_datum
.bounds
.iter()
.flat_map(|b| b.into_where_clauses(interner, self_ty.clone()))
.collect()
}
}
/// Represents the *value* of an associated type that is assigned
/// from within some impl.
///
/// ```ignore
/// impl Iterator for Foo {
/// type Item = XXX; // <-- represents this line!
/// }
/// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub struct AssociatedTyValue<I: Interner> {
/// Impl in which this associated type value is found. You might
/// need to look at this to find the generic parameters defined on
/// the impl, for example.
///
/// ```ignore
/// impl Iterator for Foo { // <-- refers to this impl
/// type Item = XXX; // <-- (where this is self)
/// }
/// ```
pub impl_id: ImplId<I>,
/// Associated type being defined.
///
/// ```ignore
/// impl Iterator for Foo {
/// type Item = XXX; // <-- (where this is self)
/// }
/// ...
/// trait Iterator {
/// type Item; // <-- refers to this declaration here!
/// }
/// ```
pub associated_ty_id: AssocTypeId<I>,
/// Additional binders declared on the associated type itself,
/// beyond those from the impl. This would be empty for normal
/// associated types, but non-empty for generic associated types.
///
/// ```ignore
/// impl<T> Iterable for Vec<T> {
/// type Iter<'a> = vec::Iter<'a, T>;
/// // ^^^^ refers to these generics here
/// }
/// ```
pub value: Binders<AssociatedTyValueBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable, HasInterner)]
pub struct AssociatedTyValueBound<I: Interner> {
/// Type that we normalize to. The X in `type Foo<'a> = X`.
pub ty: Ty<I>,
}
/// Represents the bounds for an `impl Trait` type.
///
/// ```ignore
/// opaque type T: A + B = HiddenTy;
/// ```
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)]
pub struct OpaqueTyDatum<I: Interner> {
/// The placeholder `!T` that corresponds to the opaque type `T`.
pub opaque_ty_id: OpaqueTyId<I>,
/// The type bound to when revealed.
pub bound: Binders<OpaqueTyDatumBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner, TypeVisitable)]
pub struct OpaqueTyDatumBound<I: Interner> {
/// Trait bounds for the opaque type. These are bounds that the hidden type must meet.
pub bounds: Binders<Vec<QuantifiedWhereClause<I>>>,
/// Where clauses that inform well-formedness conditions for the opaque type.
/// These are conditions on the generic parameters of the opaque type which must be true
/// for a reference to the opaque type to be well-formed.
pub where_clauses: Binders<Vec<QuantifiedWhereClause<I>>>,
}
// The movability of a generator: whether a generator contains self-references,
// causing it to be !Unpin
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Movability {
Static,
Movable,
}
chalk_ir::copy_fold!(Movability);
/// Represents a generator type.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
pub struct GeneratorDatum<I: Interner> {
// Can the generator be moved (is Unpin or not)
pub movability: Movability,
/// All of the nested types for this generator. The `Binder`
/// represents the types and lifetimes that this generator is generic over -
/// this behaves in the same way as `AdtDatum.binders`
pub input_output: Binders<GeneratorInputOutputDatum<I>>,
}
/// The nested types for a generator. This always appears inside a `GeneratorDatum`
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
pub struct GeneratorInputOutputDatum<I: Interner> {
/// The generator resume type - a value of this type
/// is supplied by the caller when resuming the generator.
/// Currently, this plays no rule in goal resolution.
pub resume_type: Ty<I>,
/// The generator yield type - a value of this type
/// is supplied by the generator during a yield.
/// Currently, this plays no role in goal resolution.
pub yield_type: Ty<I>,
/// The generator return type - a value of this type
/// is supplied by the generator when it returns.
/// Currently, this plays no role in goal resolution
pub return_type: Ty<I>,
/// The upvars stored by the generator. These represent
/// types captured from the generator's environment,
/// and are stored across all yields. These types (along with the witness types)
/// are considered 'constituent types' for the purposes of determining auto trait
/// implementations - that its, a generator impls an auto trait A
/// iff all of its constituent types implement A.
pub upvars: Vec<Ty<I>>,
}
/// The generator witness data. Each `GeneratorId` has both a `GeneratorDatum`
/// and a `GeneratorWitnessDatum` - these represent two distinct types in Rust.
/// `GeneratorWitnessDatum` is logically 'inside' a generator - this only
/// matters when we treat the witness type as a 'constituent type for the
/// purposes of determining auto trait implementations.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
pub struct GeneratorWitnessDatum<I: Interner> {
/// This binder is identical to the `input_output` binder in `GeneratorWitness` -
/// it binds the types and lifetimes that the generator is generic over.
/// There is an additional binder inside `GeneratorWitnessExistential`, which
/// is treated specially.
pub inner_types: Binders<GeneratorWitnessExistential<I>>,
}
/// The generator witness types, together with existentially bound lifetimes.
/// Each 'witness type' represents a type stored inside the generator across
/// a yield. When a generator type is constructed, the precise region relationships
/// found in the generator body are erased. As a result, we are left with existential
/// lifetimes - each type is parameterized over *some* lifetimes, but we do not
/// know their precise values.
///
/// Unlike the binder in `GeneratorWitnessDatum`, this `Binder` never gets substituted
/// via an `Ty`. Instead, we handle this `Binders` specially when determining
/// auto trait impls. See `push_auto_trait_impls_generator_witness` for more details.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, HasInterner)]
pub struct GeneratorWitnessExistential<I: Interner> {
pub types: Binders<Vec<Ty<I>>>,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum Polarity {
Positive,
Negative,
}
chalk_ir::const_visit!(Polarity);
impl Polarity {
pub fn is_positive(&self) -> bool {
match *self {
Polarity::Positive => true,
Polarity::Negative => false,
}
}
}
/// Indicates the "most permissive" Fn-like trait that the closure implements.
/// If the closure kind for a closure is FnMut, for example, then the closure
/// implements FnMut and FnOnce.
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum ClosureKind {
Fn,
FnMut,
FnOnce,
}