Как вызвать метод, когда trait и struct используют одно и то же имя метода?

Эта программа умирает из-за бесконечной рекурсии:

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))
}

Сам компилятор предупреждает об этом:

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

Почему универсальный синтаксис вызова не работает в этом случае? Компилятор не понимает, что я хочу вызвать Vec::get not Foo::get.

Как я могу это исправить, если я не хочу менять имена функций?

Ответ 1

Чтобы указать, какой метод вызывать, присущий или предоставленный из черты, вы хотите использовать полный синтаксис:

Type::function(maybe_self, needed_arguments, more_arguments)
Trait::function(maybe_self, needed_arguments, more_arguments)

Ваш случай не работает, потому что у Vec нет метода get ! get предоставляется из реализации Deref в [T].

Самое простое решение - вызвать as_slice напрямую:

self.as_slice().get(index).map(|v| v as &Any)

Вы также можете использовать полный синтаксис, который требует угловых скобок в этом случае (<...>), чтобы избежать двусмысленности с объявлением литерала массива:

<[i32]>::get(self, index).map(|v| v as &Any)

синтаксис универсального вызова

Обратите внимание, что хотя Rust первоначально использовал термин универсальный синтаксис вызова функций (UFCS), использование этого термина противоречило существующему понимаемому термину программирования, поэтому его использование не предлагается. Заменяющий термин - полностью определенный синтаксис.