TL;DR - I wonder if it would make sense to lift this restriction and allow private types in where
conditions in impl Trait ...
contexts?
Recently I’ve been trying to fix one of annoying issues with derive
, especially derive(Default)
.
Currently, any built-in derive requires all the type generics to implement same derived trait. This doesn’t always work well:
#[derive(Default)]
struct MyVec<T>(Vec<T>);
struct Value;
/// ...
let values: MyVec<Value> = Default::default();
/*
9 | let values: MyVec<Value> = Default::default();
| ^^^^^^^^^^^^^^^^ the trait `std::default::Default` is not implemented for `main::Value`
*/
The reason for this is that derive expands into:
impl <T: Default> Default for MyVec<T> {
fn default() -> MyVec<T> { MyVec(Default::default()) }
}
In general, this would be easy to fix, The idea is that where
predicates allow complex type constraints, and all we really care about is that all the field types of the structure implement derived trait, and not that actual type params do. For example, for Vec<T>
(or any other collection, whether in std
or not) to implement Default
, T
does not need to implement Default
, and we could express that requirement directly:
impl <T> Default for MyVec<T> where Vec<T>: Default /* ...similarly list all the field types when deriving */ {
fn default() -> MyVec<T> { MyVec(Default::default()) }
}
And I actually implemented it locally in rustc
, but then found out that some tests are failing with private type `Inner<T>` in public interface
.
Indeed, turns out that code like following is invalid:
struct Inner<T>(...); // private type
pub struct MyStruct<T>(Inner<T>);
impl<T> Default for MyStruct<T> where Inner<T>: Default {
// ...
}
On one hand, it makes some sense - indeed, where
predicate is part of the public interface, but on another, personally, I never ran into such issue in manual code before and not sure that it’s common enough to be a problem for impl Trait for ...
blocks, especially given that we can still provide error messages stating that MyStruct<T>
doesn’t implement Default
, without involving names of these private types.