Struct chalk_solve::wf::WfWellKnownConstraints

source ·
struct WfWellKnownConstraints;
Expand description

Defines methods to compute well-formedness goals for well-known traits (e.g. a goal for all fields of struct in a Copy impl to be Copy)

Implementations§

source§

impl WfWellKnownConstraints

source

pub fn struct_sized_constraint<I: Interner>( db: &dyn RustIrDatabase<I>, fields: &[Ty<I>], size_all: bool, ) -> Option<Goal<I>>

Computes a goal to prove Sized constraints on a struct definition. Struct is considered well-formed (in terms of Sized) when it either has no fields or all of it’s fields except the last are proven to be Sized.

source

fn copy_impl_constraint<I: Interner>( solver: &mut dyn Solver<I>, db: &dyn RustIrDatabase<I>, impl_datum: &ImplDatum<I>, ) -> bool

Verify constraints on a Copy implementation. Copy impl is considered well-formed for a) certain builtin types (scalar values, shared ref, etc..) b) adts which 1) have all Copy fields 2) don’t have a Drop impl

source

fn drop_impl_constraint<I: Interner>( solver: &mut dyn Solver<I>, db: &dyn RustIrDatabase<I>, impl_datum: &ImplDatum<I>, ) -> bool

Verifies constraints on a Drop implementation Drop implementation is considered well-formed if: a) it’s implemented on an ADT b) The generic parameters of the impl’s type must all be parameters of the Drop impl itself (i.e., no specialization like impl Drop for S<Foo> {...} is allowed). c) Any bounds on the genereic parameters of the impl must be deductible from the bounds imposed by the struct definition (i.e. the implementation must be exactly as generic as the ADT definition).

struct S<T1, T2> { }
struct Foo<T> { }

impl<U1: Copy, U2: Sized> Drop for S<U2, Foo<U1>> { }

generates the following: goal derived from c):

forall<U1, U2> {
   Implemented(U1: Copy), Implemented(U2: Sized) :- FromEnv(S<U2, Foo<U1>>)
}

goal derived from b):

forall <T1, T2> {
    exists<U1, U2> {
       S<T1, T2> = S<U2, Foo<U1>>
    }
}
source

fn coerce_unsized_impl_constraint<I: Interner>( solver: &mut dyn Solver<I>, db: &dyn RustIrDatabase<I>, impl_datum: &ImplDatum<I>, ) -> bool

Verify constraints a CoerceUnsized impl. Rules for CoerceUnsized impl to be considered well-formed:

  1. pointer conversions: &[mut] T -> &[mut] U, &[mut] T -> *[mut] U, *[mut] T -> *[mut] U are considered valid if

    1. T: Unsize<U>
    2. mutability is respected, i.e. immutable -> immutable, mutable -> immutable, mutable -> mutable conversions are allowed, immutable -> mutable is not.
  2. struct conversions of structures with the same definition, S<P0...Pn> -> S<Q0...Qn>. To check if this impl is legal, we would walk down the fields of S and consider their types with both substitutes. We are looking to find exactly one (non-phantom) field that has changed its type (from T to U), and expect T to be unsizeable to U, i.e. T: CoerceUnsized<U>.

    As an example, consider a struct

    struct Foo<T, U> {
        extra: T,
        ptr: *mut U,
    }

    We might have an impl that allows (e.g.) Foo<T, [i32; 3]> to be unsized to Foo<T, [i32]>. That impl would look like:

    impl<T, U: Unsize<V>, V> CoerceUnsized<Foo<T, V>> for Foo<T, U> {}

    In this case:

    • extra has type T before and type T after
    • ptr has type *mut U before and type *mut V after

    Since just one field changed, we would then check that *mut U: CoerceUnsized<*mut V> is implemented. This will work out because U: Unsize<V>, and we have a libcore rule that *mut U can be coerced to *mut V if U: Unsize<V>.

source

fn dispatch_from_dyn_constraint<I: Interner>( solver: &mut dyn Solver<I>, db: &dyn RustIrDatabase<I>, impl_datum: &ImplDatum<I>, ) -> bool

Verify constraints of a DispatchFromDyn impl.

Rules for DispatchFromDyn impl to be considered well-formed:

  • Self and the type parameter must both be references or raw pointers with the same mutabilty
  • OR all the following hold:
    • Self and the type parameter must be structs
    • Self and the type parameter must have the same definitions
    • Self must not be #[repr(packed)] or #[repr(C)]
    • Self must have exactly one field which is not a 1-ZST (there may be any number of 1-ZST fields), and that field must have a different type in the type parameter (i.e., it is the field being coerced)
    • DispatchFromDyn is implemented for the type of the field being coerced.

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> Cast for T

source§

fn cast<U>(self, interner: <U as HasInterner>::Interner) -> U
where Self: CastTo<U>, U: HasInterner,

Cast a value to type U using CastTo.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more