Почему синтаксис impl Trait не работает с двумя параметрами?

В примере проекта Rust я создал функцию, которая сравнивает два значения типов, реализующих признак PartialOrd, но не компилируется:

fn main(){
    let x: i32 = 5;
    let y: i32 = 6;
    dbg!(greater_than(&x, &y));
}

fn greater_than(x: &impl PartialOrd, y: &impl PartialOrd) -> bool{
    x > y
}
error[E0308]: mismatched types
 --> src/main.rs:8:9
  |
7 | fn greater_than(x: &impl PartialOrd, y: &impl PartialOrd) -> bool{
  |                     ---------------      --------------- found type parameter
  |                     |
  |                     expected type parameter
8 |     x > y
  |         ^ expected type parameter `impl PartialOrd`, found a different type parameter `impl PartialOrd`
  |
  = note: expected reference `&impl PartialOrd` (type parameter `impl PartialOrd`)
             found reference `&impl PartialOrd` (type parameter `impl PartialOrd`)
  = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
  = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters

Насколько я понимаю, как только ваши параметры в сигнатуре вашей функции были набраны с использованием синтаксиса признака impl, любой тип, реализующий этот признак (i32 предназначен для реализации признака PartialOrd), может использоваться в функции в качестве аргумента. (Я использовал другую сигнатуру функции, используя границы свойств, как показано ниже, и она работала нормально): fn greater_than<T: PartialOrd>(x: &T, y: &T) -> bool

Как создавать пользовательские общие типы в Python (50/100 дней Python)
Как создавать пользовательские общие типы в Python (50/100 дней Python)
Помимо встроенных типов, модуль типизации в Python предоставляет возможность определения общих типов, что позволяет вам определять типы, которые могут...
2
0
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Каждое появление impl Trait дает новый отдельный параметр типа. Например, x может быть u32 и yString. Оба реализуют PartialOrd, но их все равно нельзя сравнивать друг с другом.

То, что вы хотите, не может быть выражено с помощью impl Trait, так как вам нужно указать тип дважды:

fn greater_than<T: PartialOrd>(x: &T, y: &T) -> bool{
    x > y
}

Или принять даже два разных типа, если их можно сравнивать:

fn greater_than<T: PartialOrd<U>, U>(x: &T, y: &U) -> bool {
    x > y
}
Ответ принят как подходящий

Насколько я понимаю, как только ваши параметры в сигнатуре вашей функции были набраны с использованием синтаксиса признака impl, любой тип, реализующий этот признак (i32 предназначен для реализации признака PartialOrd), может использоваться в функции в качестве аргумента.

Ну да, но impl trait не определяет никакой связи между вашими аргументами, поэтому то, что вы написали, по сути,

fn greater_than<T: PartialOrd, U: PartialOrd>(x: &T, y: &U) -> bool

Таким образом, каждый аргумент частично сопоставим сам с собой, но из этого не следует, что они частично сопоставимы друг с другом. Что касается Rust, вы можете передать i32 в качестве первого параметра и строку в качестве второго, оба impl PartialOrd.

Другие вопросы по теме