Specializing `Option<T>` for `bool` with associated types is not expressible (even on nightly)
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I am trying to implement a trait for Option<T> with a special case for Option<bool>.
It is about a trait for converting object to intermediate form for using in FFI.
The trait definition is like this:
trait IntoInterm {
type IntermT: Default + Debug + ?Sized;
fn into_interm(self) -> Result<Self::IntermT, Error>;
}
Desired behavior:
-
For
Option<T>(general case):Option<T> -> IntermediateOption -
For
Option<bool>(special case):Option<bool> -> IntermediateOptionBool
This is required for FFI reasons (ABI/layout differences).
Object definitions:
#[repr(C)]
#[derive(Debug, Default)]
pub struct IntermOption {
pub value: *mut c_void,
pub item_type: IntermType
}
#[repr(C)]
#[derive(Debug, Default)]
pub struct IntermOptionBool {
pub kind: OptionKind, // Some | None,
pub value: bool
}
The reason for such a definition is to achieve generality.
Attempt 1: Stable Rust (expectedly impossible)
On stable Rust, this is not possible due to the lack of:
- specialization
- negative bounds (
T != bool) - conditional type constraints
- difference of return types
This part is understood and expected.
Attempt 2: Nightly specialization (fails)
Code
#![feature(specialization)]
impl<T> IntoInterm for Option<T>
where
T: IntoInterm,
{
default type IntermT = IntermediateOption<T::IntermT>;
default fn into_interm(self) -> Self::IntermT {
// implementations
Ok(IntermOption { /* ... */ }) // or even Ok(Self::IntermT { /* ... */ })
}
}
impl IntoInterm for Option<bool> {
type IntermT = IntermediateOptionBool;
fn into_interm(self) -> Self::IntermT {
if let Some(val) = self {
Ok(IntermOptionBool { kind: SOME, value: val })
}
else {
Ok(IntermOptionBool { kind: NONE, value: false })
}
}
}
Error
error[E0308]: mismatched types
default type IntermT = IntermOption;
------------------------------------ associated type is `default` and may be overridden
Ok(IntermOption { /* ... */ })
^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found `IntermOption`
Attempt 3: Indirection via helper traits (also fails)
A natural workaround is to defer construction via another trait, e.g.:
trait OptionCtor<V> {
fn some(v: V) -> Self;
fn none() -> Self;
}
and then require:
where Self::IntermT: OptionCtor<T::IntermT>
However, this is not allowed, constraints on Self::IntermT inside a specializing impl are rejected. So this approach is also invalid.
What's the solution?
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the specialization and associated-type examples in the issue, then investigate the E0308 diagnostic and the rejected helper-trait constraint. Compare the behavior of the general Option implementation with the Option specialization. Done means establishing whether this behavior is supported or identifying the language or compiler change required.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100