Hi
I may have missed something, but I recently got stuck with a question:
The code (modified from rust-by-example):
struct Sheep { naked: bool, name: &'static str }
trait Animal {
fn new(name: &'static str) -> Self;
fn name(&self) -> &'static str;
}
impl Animal for Sheep {
fn new(name: &'static str) -> Sheep {
Sheep { name: name, naked: false }
}
fn name(&self) -> &'static str {
self.name
}
}
fn main() {
let dolly = Sheep::new("Dolly");
println!("{}", dolly.name); // It's OK
let molly = bounded_return("Molly");
println!("{}", molly.name); // It produces an Error
// ^attempted to take value
// of method `name` on type `impl Animal`
// method, not a field!
println!("{}", molly.name()); // It's OK
//
// OR the same with Type annotation
//
let molly: Sheep = bounded_return("Molly"); // It produces an Error
// ^mismatched types
// expected struct `Sheep`
// found opaque type `impl Animal`
}
fn bounded_return(x: &'static str) -> impl Animal {
Sheep {
name: x,
naked: false,
}
}
Having instantiated struct Sheep
with the bounded_return
function, I then cannot access the value of name
field of the instance. It's only possible to get the value as self.name
via the name
function, declared in the Animal
trait.
So, do I understand it right?:
-
If a value of some type is returned from a function with
impl Trait
syntax in the return position of its signature, that returned value is never just a value "of some type that implements theTrait
", but instead a value of the typeimpl Trait
; -
impl Trait
is a so called "opaque type" that only makes it possible to access a specific set of methods defined when thatTrait
was implemented on a type, and nothing apart from those methods (that's whymolly.name
, which isn't anAnimal
method, does not work but 'molly.name()' does); -
The code, calling functions with
impl Trait
return type never knows about the "real, behind the scenes" type (Sheep), which is hence called "hidden", but yet can infer it (in the given code, from the body of thebounded_return
function).- It is somewhat similar to using
let dolly: Sheep = Animal::new("Dolly");
instead oflet dolly = Sheep::new("Dolly");
for instantiatingSheep
.
- It is somewhat similar to using
And one more question:
- were these "opaque" and "hidden" types introduced by design or are just an unintentional by-prodict of
impl Trait
syntax?