This program dies because of infinite recursion:
use std::any::Any; trait Foo { fn get(&self, index: usize) -> Option<&Any>; } impl Foo for Vec<i32> { fn get(&self, index: usize) -> Option<&Any> { Vec::get(self, index).map(|v| v as &Any) } } fn main() { let v: Vec<i32> = vec![1, 2, 4]; println!("Results: {:?}", v.get(0)) }
The compiler itself warns about this:
warning: function cannot return without recurring --> src/main.rs:8:5 | 8 | fn get(&self, index: usize) -> Option<&Any> { | _____^ starting here... 9 | | Vec::get(self, index).map(|v| v as &Any) 10 | | } | |_____^ ...ending here | = note: #[warn(unconditional_recursion)] on by default note: recursive call site --> src/main.rs:9:9 | 9 | Vec::get(self, index).map(|v| v as &Any) | ^^^^^^^^^^^^^^^^^^^^^ = help: a `loop` may express intention better if this is on purpose
Why does universal call syntax not work in this case? The compiler does not understand that I want to call Vec::get
not Foo::get
.
How can I fix this, if I do not want to change function names?
To specify which method to call, whether inherent or provided from a trait, you want to use the fully qualified syntax:
Type::function(maybe_self, needed_arguments, more_arguments) Trait::function(maybe_self, needed_arguments, more_arguments)
Your case doesn't work because Vec
doesn't have a method called get
! get
is provided from the Deref
implementation to [T]
.
The easiest fix is to call as_slice
directly:
self.as_slice().get(index).map(|v| v as &Any)
You could also use the fully qualified syntax which requires the angle brackets in this case (<...>
) to avoid ambiguity with declaring an array literal:
<[i32]>::get(self, index).map(|v| v as &Any)
universal call syntax
Note that while Rust originally used the term universal function call syntax (UFCS), the usage of this term conflicted with the existing understood programming term, so the use of it is not suggested. The replacement term is fully qualified syntax.
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