繁体   English   中英

为什么在某些特征方法调用中会导致&mut导致引用弱化?

[英]Why does reference weakening from &mut occur in some trait method calls?

Rust中可用的少数隐式转换之一是指针减弱 ,它可以将&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}`

对于另一个更有趣的示例,我为单元类型Foo添加了各种各样的Add实现:

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

完整的游乐场

第二种情况与上面的示例一致,但第一种情况并非如此。 似乎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不起作用的情况下&i32 + &mut i32 是否因为有一个Add for &Foo 如果是这样,为什么它会使编译器的行为有所不同?

是否因为有一个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`

所以答案是肯定的

如果是这样,为什么它会使编译器的行为有所不同?

当存在Add<T>的单个适用实现(或任何其他通用特性)时,编译器无需根据参数推断T 它已经基于该单个实现解决了T 基本上,就好像特质根本不是通用的。 因此,也可以应用对非泛型参数起作用的强制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM