gpt4 book ai didi

rust - 尽管存在约束,仍会使用rust `cannot infer type`

转载 作者:行者123 更新时间:2023-12-03 11:33:22 35 4
gpt4 key购买 nike

我想编写一段代码,可以接受可复制类型的引用或拥有的值,并返回该类型的拥有的版本。我减少了以下代码的类型推断所带来的问题,这些错误:

use std::borrow::Borrow;

fn copy<R, E>(val: E) -> R
where
R: Default + Copy,
E: Borrow<R>,
{
*val.borrow()
}

fn main() {
assert_eq!(6, copy(&6));
assert_eq!(6, copy(6));
assert_eq!(6.0, copy(&6.0));
assert!((6.0f64 - copy(&6.0f64)).abs() < 1e-6);
}
错误来自最后一个断言:
error[E0282]: type annotations needed
--> src/main.rs:15:13
|
15 | assert!((6.0f64 - copy(&6.0f64)).abs() < 1e-6);
| ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
|
= note: type must be known at this point
我唯一的假设是 Sub上的 f64特性允许 f64&f64,并且如果没有 Default约束,则最后一个副本的有效表达式将是 copy::<&f64, &f64>(&6.0f64),但这是不允许的,因为 &f64没有实现 Default。如果我们按值传递 f64的话,它会起作用,大概是因为这样会将 R限制为 f64而不是两者中的任何一个。
我不清楚的是,为什么编译器不能进一步限制 copy的返回类型,或者如何向编译器指示返回的值将不是引用。

最佳答案

copy中的任何内容都不会将R约束为特定的具体类型。特别地,&f64可以为Borrow<R>的多个值(而不仅仅是R)实现f64。它不在您当前的代码中,但是缺少替代方法并不被认为是选择特定实现的依据。
我什至可以添加一个匹配的实现:

#[derive(Copy, Clone, Debug, Default)]
struct Foo;

impl Borrow<Foo> for &f64 {
fn borrow(&self) -> &Foo { &Foo }
}
(即使 f64是标准库类型,也可以使用此特征实现,因为 Foo是当前包装箱中定义的类型。)
现在我们可以实际使用该选择了:
fn main() {
dbg!(copy::<f64, _>(&1.0));
dbg!(copy::<Foo, _>(&1.0));
}
[src/main.rs:19] copy::<f64, _>(&1.0) = 1.0
[src/main.rs:20] copy::<Foo, _>(&1.0) = Foo
copy这样的函数只能在其返回类型实际上取决于参数类型时才从其参数类型派生其返回类型:例如,如果它是由参数实现的特征的关联类型。 AsRefBorrow都具有类型参数,而不是关联的类型(因此,对于相同的实现类型,可以多次实现); Deref具有关联的 Target类型,但是 Deref不提供从 f64f64的转换。您可以为此实现自己的特征:
trait DerefCopy: Copy {
type Output;
fn deref_copy(self) -> Self::Output;
}

impl<T: Copy> DerefCopy for &T {
type Output = T;
fn deref_copy(self) -> T {
*self
}
}

impl DerefCopy for f64 {
type Output = Self;
fn deref_copy(self) -> Self {
self
}
}

fn main() {
assert_eq!(6, (&6).deref_copy());
assert_eq!(6, (6).deref_copy());
assert_eq!(6.0, (&6.0).deref_copy());
assert!((6.0f64 - (&6.0f64).deref_copy()).abs() < 1e-6);
}
但是,这将要求您为每个希望与之一起使用的非引用类型实现 DerefCopy,因为不可能为所有非引用 T编写一个通用实现; Borrow可以全面实现的原因是 impl Borrow<T> for Timpl Borrow<T> for &T不冲突,因为如果我们假设T本身是引用 &U,我们得到的 impl Borrow<&U> for &&U仍然与 impl Borrow<T> for T不同。

关于rust - 尽管存在约束,仍会使用rust `cannot infer type`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66466258/

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com