| //! 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, |
| } |