In a project I'm working on, I have an immutable buildable struct that contains an optional generic field. When this field is not set, the compiler throws an error because it cannot infer its type.
However, since the struct is immutable, this field would stay None forever, meaning that its corresponding type would not be relevant. I attempted to fix this by giving it a Default Generic Type Parameter with a throwaway type, but it did not work as I expected.
This is a minimal example of the issue.
I set the placeholder type to Vec<String> because in my project the type of B has bounds which prevent it from being ().
use derive_builder::Builder;
#[derive(Builder)]
struct GenericStruct<A, B = Vec<String>> {
required_field: A,
#[builder(setter(strip_option), default)]
optional_field: Option<B>
}
fn main() {
let a = GenericStructBuilder::default()
.optional_field(30)
.required_field("hello")
.build();
// **Error**
let b = GenericStructBuilder::default()
.required_field("hello")
.build();
}
error[E0282]: type annotations needed for `std::result::Result<GenericStruct<&str, B>, String>`
--> src/main.rs:18:13
|
18 | let b = GenericStructBuilder::default()
| - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `B` declared on the struct `GenericStructBuilder`
| |
| consider giving `b` the explicit type `std::result::Result<GenericStruct<&str, B>, String>`, where the type parameter `B` is specified
Potential User Workarounds
Remove strip_option and default, and make users explicitly pass in Option::<()>::None to the setter
Something with Box?
Potential Crate Solutions
Internally use workaround #1 before build() to set the type
In a project I'm working on, I have an immutable buildable struct that contains an optional generic field. When this field is not set, the compiler throws an error because it cannot infer its type.
However, since the struct is immutable, this field would stay
None
forever, meaning that its corresponding type would not be relevant. I attempted to fix this by giving it a Default Generic Type Parameter with a throwaway type, but it did not work as I expected.This is a minimal example of the issue.
I set the placeholder type to
Vec<String>
because in my project the type ofB
has bounds which prevent it from being()
.Potential User Workarounds
strip_option
anddefault
, and make users explicitly pass inOption::<()>::None
to the setterPotential Crate Solutions
build()
to set the typeOther Notes
default_type_parameter_fallback
feature gate, but could not get it to workdefault = "Option::<Vec<String>>::None"
, but that didn't workResources
derive_builder
): stackoverflow post asking about a similar situation