Reputation: 585
When calling a default implementation on a trait which does not take self
, why does it neeed an implementing type to be annotated?
A minimal, reproducible example is below (playground):
mod builder {
pub trait Builder: Sized {
fn new() -> Simple {
Simple
}
}
pub struct Simple;
impl Builder for Simple {}
}
pub fn main() {
let _ = builder::Builder::new();
/* Working version */
// use builder::Builder;
// let _ = builder::Simple::new();
}
Which gives:
error[E0283]: type annotations needed
--> src/main.rs:14:13
|
3 | fn new() -> Simple {
| ------------------ required by `builder::Builder::new`
...
14 | let _ = builder::Builder::new();
| ^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: cannot satisfy `_: builder::Builder`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0283`.
error: could not compile `playground`.
To learn more, run the command again with --verbose.
The compiler explanation for E0283
does not mention a default implementation, which I agree it makes sense. But for default implementations, why is a type required?
Upvotes: 1
Views: 173
Reputation: 27905
Provided methods in Rust are not like static
methods in Java. Even a function with no arguments and a default implementation can be overridden by implementors. Consider adding another type that implements Builder
but overrides the new
function:
struct Noisy {}
impl builder::Builder for Noisy {
fn new() -> builder::Simple {
println!("Ahahahah I'm creating a Simple!!!11!");
builder::Simple
}
}
fn main() {
// wait, should this call builder::Simple::new() or Noisy::new()?
let _ = builder::Builder::new();
}
If you want the effect of a Java static
function that always has the same behavior, you should use a free function, as prog-fh's answer also suggests.
Upvotes: 1
Reputation: 16850
This is not only a default implementation but the very specific case in which this default implementation does not even mention Self
/self
in its parameters, result and body.
I find much more easy to understand a rule saying that a type is required every time we use a trait, in any case, rather that « except if the default implementation does not even mention Self
/self
in its parameters, result and body ».
For this very specific use case, where you do not want to explicitly name a type when calling the function you need, I suggest using a free function.
mod builder {
// ...
pub fn make_default() -> Simple {
Simple
}
// ...
}
pub fn main() {
let _ = builder::make_default();
}
Upvotes: 5