gpt4 book ai didi

reference - 为什么 &mut 的引用弱化发生在某些特征方法调用中?

转载 作者:行者123 更新时间:2023-11-29 07:45:48 25 4
gpt4 key购买 nike

Rust 中可用的少数隐式转换之一是 pointer weakening , 它可以变成 &mut T进入&T :

fn just_foo<T>(_: &T) {}

just_foo(&mut vec![1, 2, 3]);

但是,匹配特征时不会发生这种情况。例如,虽然带有引用作为右侧值的 + 运算符是为数字类型实现的,但它们不会接受对同一类型的可变引用:

5 + &mut 5;
(&5) + &mut 5;

错误信息:

error[E0277]: the trait bound `{integer}: std::ops::Add<&mut {integer}>` is not satisfied
--> src/main.rs:38:7
|
38 | 5 + &mut 5;
| ^ no implementation for `{integer} + &mut {integer}`
|
= help: the trait `std::ops::Add<&mut {integer}>` is not implemented for `{integer}`

error[E0277]: the trait bound `&{integer}: std::ops::Add<&mut {integer}>` is not satisfied
--> src/main.rs:43:10
|
43 | (&5) + &mut 5;
| ^ no implementation for `&{integer} + &mut {integer}`
|
= help: the trait `std::ops::Add<&mut {integer}>` is not implemented for `&{integer}`

另一个更有趣的例子是,我添加了 Add 的各种实现。对于单位类型 Foo :

use std::ops::Add;

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

impl Add<Foo> for Foo {
type Output = Foo;
fn add(self, _: Foo) -> Foo {
Foo
}
}

impl<'a> Add<&'a Foo> for Foo {
type Output = Foo;
fn add(self, _: &'a Foo) -> Foo {
Foo
}
}

impl<'a, 'b> Add<&'a Foo> for &'b Foo {
type Output = Foo;
fn add(self, _: &'a Foo) -> Foo {
Foo
}
}

才发现我可以执行&Foo + &mut Foo , 但不是 Foo + &mut Foo :

&Foo + &mut Foo; // ok
Foo + &mut Foo; // not ok

Full Playground

第二种情况符合上面前面的例子,但第一种情况则不然。似乎 RHS &mut Foo被迫&Foo匹配 &Foo + &Foo 的实现.看起来也没有发生其他强制转换,因为 &Foo as Add<&Foo> 的接收类型已经是&Foo .我也可以扔掉语法糖并获得相同的结果:

(&Foo).add(&mut Foo); // ok
Foo.add(&mut Foo); // not ok

鉴于强制转换,根据 Nomicon,在进行特征匹配时不应该发生,为什么会这样 &Foo + &mut Foo工作时&i32 + &mut i32不是吗?是因为 Add 的实现只有一个吗?对于 &Foo ?如果是这样,为什么它会使编译器的行为有所不同?

最佳答案

Is it because there is a single implementation of Add for &Foo?

让我们看看添加此实现后会发生什么:

impl<'b> Add<Foo> for &'b Foo {
type Output = Foo;
fn add(self, _: Foo) -> Foo {
Foo
}
}

现在&Foo + &mut Foo&Foo + &mut &mut Foo编译失败:

error[E0277]: the trait bound `&Foo: std::ops::Add<&mut Foo>` is not satisfied
--> src/main.rs:39:10
|
39 | &Foo + &mut Foo;
| ^ no implementation for `&Foo + &mut Foo`
|
= help: the trait `std::ops::Add<&mut Foo>` is not implemented for `&Foo`

error[E0277]: the trait bound `&Foo: std::ops::Add<&mut &mut Foo>` is not satisfied
--> src/main.rs:40:10
|
40 | &Foo + &mut &mut Foo;
| ^ no implementation for `&Foo + &mut &mut Foo`
|
= help: the trait `std::ops::Add<&mut &mut Foo>` is not implemented for `&Foo`

所以答案是

If so, why does it make the compiler behave differently?

Add<T> 有一个适用的实现时(或任何其他通用特征),编译器不需要推断 T从论点;它已经解决了T基于那个单一的实现。基本上,就好像这个特征根本不是通用的。因此,也可以应用适用于非泛型参数的强制转换。

关于reference - 为什么 &mut 的引用弱化发生在某些特征方法调用中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49454023/

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