rust - 比较相等性时如何帮助推断通用向量的类型

标签 rust

我有以下代码:

struct HeadTail<T>(T, Vec<T>);

fn head_tail<T : Clone>(v: &Vec<T>) -> Option<HeadTail<T>> {
    match v.len() {
        0 => None,
        _ => {
            let mut tmp_v = v.clone();
            let head = tmp_v.remove(0);
            Some(HeadTail(head, tmp_v))
        }
    }
}

#[test]
fn head_tail_many() {
    let vec = vec![1, 2, 3, 4];
    let result = head_tail(&vec);

    match result {
        None => unreachable!(),
        Some(HeadTail(head, tail)) => {
            assert_eq!(1, head);
            assert_eq!(3, tail.len());
            assert_eq!([2, 3, 4], tail);
        }
    };
}

Online demo with the problem

失败并出现以下异常:

<std macros>:5:8: 5:33 error: the trait `core::cmp::PartialEq<collections::vec::Vec<_>>` is not implemented for the type `[_; 3]` [E0277]
<std macros>:5 if ! ( * left_val == * right_val ) {

为什么 Rust 不能在这种情况下推断出类型?

我该怎么做才能让它知道它是任何数字类型(例如 u8)?

最佳答案

create a MCVE 很有用在调试这些类型的东西时。这是一个例子:

fn main() {
    let vec = vec![1, 2, 3, 4];
    assert_eq!([1,2,3,4], vec);
}

有错误

<std macros>:5:8: 5:33 error: the trait `core::cmp::PartialEq<collections::vec::Vec<_>>` is not implemented for the type `[_; 4]` [E0277]
<std macros>:5 if ! ( * left_val == * right_val ) {
                      ^~~~~~~~~~~~~~~~~~~~~~~~~

因此,PartialEq 存在某种错误,让我们尝试进一步减少:

fn main() {
    let vec = vec![1, 2, 3, 4];
    [1,2,3,4] == vec;
}

同样的基本错误:

<anon>:3:5: 3:21 error: the trait `core::cmp::PartialEq<collections::vec::Vec<_>>` is not implemented for the type `[_; 4]` [E0277]
<anon>:3     [1,2,3,4] == vec;
             ^~~~~~~~~~~~~~~~

_Vec<_>表示尚未被破坏的类型。让我们使用显式类型来查看是否是问题所在:

fn main() {
    let vec = vec![1u8, 2, 3, 4];
    [1u8,2,3,4] == vec;
}

没有,还是一样的错误:

<anon>:3:5: 3:23 error: the trait `core::cmp::PartialEq<collections::vec::Vec<u8>>` is not implemented for the type `[u8; 4]` [E0277]
<anon>:3     [1u8,2,3,4] == vec;
             ^~~~~~~~~~~~~~~~~~

让我们尝试翻转一下:

fn main() {
    let vec = vec![1u8, 2, 3, 4];
    vec == [1u8,2,3,4];
}

嗯。这行得通!交换原始代码中的顺序也可以。

当然,剩下的大问题是为什么。让我们看看docs for Vec ,特别是关于 PartialEq 的部分:

impl<'a, 'b, A, B> PartialEq<[B; 4]> for Vec<A>
    where A: PartialEq<B>
{
    fn eq(&self, other: &[B; 4]) -> bool { ... }
}

因此,您可以测试 Vec<A>&[B; 4]为了平等,如果你可以测试 AB为了平等。反过来呢? docs for arrays别提Vec根本没有(这是有道理的,因为它们更像是一个核心功能),并且没有任何 PartialEq 的逆向实现。 .这看起来确实令人惊讶,而且我没有很好的解释为什么它们不存在......

啊,看来这发生在this commit .这是提交消息:

The primary implementation which was lost was the ability to compare &[T] and Vec<T> (in that order).

This change also modifies the assert_eq! macro to not consider both directions of equality, only the one given in the left/right forms to the macro. This modification is motivated due to the fact that &[T] == Vec<T> no longer compiles, causing hundreds of errors in unit tests in the standard library (and likely throughout the community as well).

Manishearth found一个comprehensive blog post详细描述了这一变化背后的基本原理!

关于rust - 比较相等性时如何帮助推断通用向量的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30282497/

相关文章:

rust - Vec和HashMap之间的特征对象差异

multithreading - 如何将不可变参数传递给线程? (关于终生)

rust - 我的 Cargo.toml 显示一些红线,错误无法编译 serde_derive

rust - 如何运行特定模块下的所有测试功能?

import - 第三方库上的 Rust `unresolved import`

file - 从文件中读取字节并使用 `pom`解析器库进行解析

rust - 是否可以使用变量作为格式的fill参数!宏?

rust - 如何将一种类型传递给在 Rust 中用两种类型定义的泛型?

memory - 为什么 ?Sized 是某些 RefCell 函数的边界,但不是全部?

rust - 如何正确特征化与对象不安全类型一起使用的对象?