【问题标题】:Disable Implicit Deref Coercions禁用隐式取消引用强制
【发布时间】:2020-04-17 04:17:40
【问题描述】:

我的问题非常具体。 我想禁用隐式取消引用强制(假设是因为我不喜欢它们)。更具体地说,我希望这段代码失败:

fn main() {
    let x = Box::new(0);
    let mut y = &x;
    y = &mut y;
    println!("GOT {}",*y);
}

在我看来,这是一个非常荒谬的例子。但是,它编译是因为(我相信)&mut T 强制转换为 T,因此,y = &mut y 语句是一个 nop。

假设这是正确的,我如何防止 Rust 这样做?例如,我尝试使用 #[no_implicit_prelude],但没有任何乐趣。

【问题讨论】:

  • 我非常怀疑是否可以禁用,因为它是一项核心语言功能。这有点像询问如何禁用for 循环。
  • 您提供的代码没有使用自动解引用。 *y 的类型是Box<i32>Display 的格式为Box 只是为了打印它的内容。
  • 不清楚什么你想在这里禁用或者你为什么认为禁用前奏会起作用。
  • 禁用前奏是为了防止包含Deref trait。

标签: rust


【解决方案1】:

您提供的代码实际上并未使用任何自动取消引用。 y 的类型是 &Box<i32> 并且 println 有效,因为 BoxDisplay 格式只是委托给它的内容 Display 实现。

如果我稍微改变一下你的例子,我们可以使用自动取消引用:

fn main() {
    let x = Box::new(0);
    let mut y: &i32 = &x; // <-- Deref impl is used here
    y = &mut y;
    println!("GOT {}", y);
}

您不能禁用为内置类型实现的任何特征。您可以创建自己的 Box 而不实现 Deref

use std::{boxed, fmt};

struct Box<T>(boxed::Box<T>);

impl<T> Box<T> {
    pub fn new(value: T) -> Self {
        Self(boxed::Box::new(value))
    }
}

impl<T: fmt::Display> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

自动取消引用不起作用:

fn main() {
    let x = Box::new(0);
    let mut y: &i32 = &x; // <-- Error:  expected `i32`, found struct `Box`
    y = &mut y;
    println!("GOT {}", y);
}

但您仍然可以打印盒子本身:

fn main() {
    let x = Box::new(0);
    let mut y = &x; 
    y = &mut y;
    println!("GOT {}", y); // y: &Box<i32>
}

我不确定你为什么要这样做。您将不得不重新实现 很多 Box 功能以使其普遍有用,而且完全不清楚没有 Deref impl 有什么好处。

【讨论】:

  • 事实上,OP 根本不想要 deref,所以所有实现 Deref 的类型都必须重写。
  • 您在技术上是正确的,但 OP 的示例使用 Box 使事情变得混乱。 y = &amp;mut y 行中发生了 deref 强制,但您无法通过重新实现 Box 来“修复”它,因为它实际上是适用于 &amp;mut TDeref impl。
  • 不确定这是否实现了我想要的,尽管欣赏我想要的并不明显。正如@trentcl 所说,这个答案并没有解决y = &amp;mut y 这实际上是我关心的问题。最后,答案似乎是您不能禁用原始类型的 deref 强制。我认为可能有一些包含魔法,例如#[no_deref_coercion],这是我不知道的。我认为我们不应该太担心为什么我想这样做......这是出于一个非常奇怪的原因(想想学术实验)。
猜你喜欢
  • 2020-11-01
  • 1970-01-01
  • 2017-04-17
  • 2015-10-05
  • 2011-10-02
  • 1970-01-01
  • 2019-03-09
  • 2018-06-01
  • 2014-06-24
相关资源
最近更新 更多