Try   HackMD

Design of Neglect parameter

How do we represent combinations of transmutation options?

Const Parameter

Make Neglect a const parameter:

unsafe trait AlwaysTransmuteFrom<Src, const NEGLECT: ???>
{ ... }

unsafe trait UnstableTransmuteFrom<Src, Scope, const NEGLECT: ???>
{ ... }

What do we replace "???" with?

const NEGLECT: Neglect

Surface syntax:

fn example<Src, Dst>()
where
    /* not neglecting any static checks */
    Dst: AlwaysTransmuteFrom<Src, {Neglect::NOTHING}>,

    /* neglecting just validity */
    Dst: AlwaysTransmuteFrom<Src, {Neglect {validity: true, ..Neglect::NOTHING}}>,
    
    /* neglecting validity and alignment */
    Dst: AlwaysTransmuteFrom<Src, {Neglect {alignment: true, validity: true, ..Neglect::NOTHING}}>,
{}

Behind the scenes.

Pros:

  • ordering and multiplicity of options doesn't matter!

Cons:

  • NEGLECT cannot be defaulted; common case of neglect nothing thus isn't syntactically free
  • depends on const_generics

const NEGLECT: &'static [Neglect]

Surface syntax:

fn example<Src, Dst>()
where
    /* not neglecting any static checks */
    Dst: AlwaysTransmuteFrom<Src, {&[]}>,

    /* neglecting just validity */
    Dst: AlwaysTransmuteFrom<Src, {&[Neglect::Validity]}>,
    
    /* neglecting validity and alignment */
    Dst: AlwaysTransmuteFrom<Src, {&[Neglect::Validity, Neglect::Alignment]}>,
    /* or, equivalently: */
    Dst: AlwaysTransmuteFrom<Src, {&[Neglect::Alignment, Neglect::Validity]}>,
{}

Behind the scenes.

Pros:

  • array syntax is familiar

Cons:

  • NEGLECT cannot be defaulted; common case of neglect nothing thus isn't syntactically free
  • ordering and multiplicity of options shouldn't matter, but it does; [Neglect::Validity, Neglect::Alignment] and [Neglect::Alignment, Neglect::Validity] are distinct types.
  • depends on const_generics

Type Parameter

unsafe trait AlwaysTransmuteFrom<Src, Neglect>
where
    Neglect: TransmuteOptions
{ ... }

unsafe trait UnstableTransmuteFrom<Src, Neglect>
where
    Neglect: TransmuteOptions
{ ... }

This time, we don't need to settle what the exact type of Neglect ought to be.

(Option, ...)

Surface syntax:

fn example<Src, Dst>()
where
    /* not neglecting any static checks */
    Dst: AlwaysTransmuteFrom<Src>,

    /* neglecting just validity */
    Dst: AlwaysTransmuteFrom<Src, Neglect::Validity>,

    /* neglecting validity and alignment */
    Dst: AlwaysTransmuteFrom<Src, (Neglect::Validity, Neglect::Alignment)>,
    /* or, equivalently: */
    Dst: AlwaysTransmuteFrom<Src, (Neglect::Alignment, Neglect::Validity)>,
{}

Pros:

  • Neglect can be defaulted; common case of neglect nothing therefore requires no additional typing
  • availability of methods can depend on how Neglect is instantiated.
  • works on stable rust
  • tuple syntax is familiar

Cons:

  • ordering and multiplicity of options shouldn't matter, but it does; (Neglect::Validity, Neglect::Alignment) and (Neglect::Alignment, Neglect::Validity) are distinct types.

Option + Option

Surface syntax:

fn example<Src, Dst>()
where
    /* not neglecting any static checks */
    Dst: AlwaysTransmuteFrom<Src>,

    /* neglecting just validity */
    Dst: AlwaysTransmuteFrom<Src, NeglectValidity>,

    /* neglecting validity and alignment */
    Dst: AlwaysTransmuteFrom<Src, NeglectValidity + NeglectAlignment>,
{}

Behind the scenes.

Pros:

  • Neglect can be defaulted; common case of neglect nothing therefore requires no additional typing
  • availability of methods can depend on how Neglect is instantiated.
  • works on stable rust
  • not sensitive to reorderings or duplications of options!

Cons:

  • bare_trait_objects are deprecated. could we squash that lint for these particular types?