Why can't a trait build itself?

This code gives me a compilation error:

trait IBoo { fn new() -> Box<IBoo>; } 

while this code compiles without errors:

 trait IBoo { //fn new() -> Box<IBoo>; } trait IFoo { fn new() -> Box<IBoo>; } 
  • Why doesn't the first compile? rustc --explain E0038 does not give me a direct indication of why this is not possible.
  • Is it possible to combine construction and methods in one interface (feature)?
+8
rust
source share
2 answers

The compiler tells you the exact reason why this does not work:

 error[E0038]: the trait `IBoo` cannot be made into an object --> src/main.rs:2:5 | 2 | fn new() -> Box<IBoo>; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `IBoo` cannot be made into an object | = note: method `new` has no receiver 

Pay attention to the last line. He tells you that the cause of the error is that new() is independent of the existence of an instance of the value that implements the IBoo attribute.

Without using any pointer to self , the method cannot be called by dynamic dispatch. If it cannot be caused by dynamic dispatching, it means that it cannot get into the vtable associated with the symbol. Must be related to vtable, because it works something like Box<IBoo> . Some time ago, the main developers of Rust decided that even one β€œnon-object safe” method in the attribute disqualified the whole trait from being used as an object.

In other words: since you have defined a method that cannot be dynamically dispatched, the IBoo attribute is generally disqualified from use with dynamically dispatched.

If you want some kind of design function, you need to have a different way of writing it. It could be using simple function pointers or IBooFactory traits, as you could with Java.

+12
source share

This is from the description of E0038 :

The method has no receiver

Methods that do not accept the self parameter cannot be called since there will be no way to get a pointer to the method table for them.

 trait Foo { fn foo() -> u8; } 

This can be called <Foo as Foo>::foo() , which will not be able to select an implementation.

Adding Self: Sized bindings to these methods usually does this compilation.

 trait Foo { fn foo() -> u8 where Self: Sized; } 

You can do it:

 trait IBoo { fn new() -> Box<IBoo> where Self: Sized; } 

In other cases, you can set a limit on the entire impl:

+9
source share

All Articles