I've encountered a problem which I reduced to the following code:
trait Logger {}
struct DefaultLogger;
impl Logger for DefaultLogger {}
struct A<L> where L: Logger {
logger: Box<L>,
}
impl<L> A<L> where L: Logger {
fn new() -> Self {
let logger = DefaultLogger;
A {
logger: Box::new(logger),
// ^^^^^^ Here is the problem
}
}
}
fn main() {
let a = A::new();
}
which produces the following error:
error[E0308]: mismatched types
--> src/main.rs:16:30
|
16 | logger: Box::new(logger),
| ^^^^^^ expected type parameter, found struct `DefaultLogger`
|
= note: expected type `L`
found type `DefaultLogger`
When I construct trait A
in a normal function (like main
), like I expected it to work. Example:
trait Logger {}
struct DefaultLogger;
impl Logger for DefaultLogger {}
struct A<L> where L: Logger {
logger: Box<L>,
}
fn main() {
let logger = DefaultLogger;
let _a = A {
logger: Box::new(logger),
};
}
The problem is here:
impl<L> A<L> where L: Logger {
fn new() -> Self {
let logger = DefaultLogger;
A {
logger: Box::new(logger),
}
}
}
You want to return A<L>
but you return A<DefaultLogger>
where you cannot be sure that L == DefaultLogger
.
To fix that you can provide specialisation that will create method A::new
only for DefaultLogger
:
impl A<DefaultLogger> {
fn new() -> Self {
let logger = DefaultLogger;
A {
logger: Box::new(logger),
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With