详解Rust的连贯性和孤儿规则

最近学习Rust时候看到两个术语:连贯性(Coherence)和孤儿规则(Orphan rules),书上解释的不是很清楚,又没有给出具体的代码示例,让人很难理解。我在网上搜了好久,最后又查了Rust语言规范,算是搞明白了这两个概念,在这里尝试解释一下,如果有理解不对的地方,请各位同学留言指正。

连贯性(Coherence)和孤儿规则(Orphan rules)两者之间是有关联的。

我们先解释一下连贯性,连贯性指的是Trait实现的连贯性。
rust语言规范是这样写的:“A trait implementation is considered incoherent if either the orphan rules check fails or there are overlapping implementation instances.”
如果孤儿规则检查失败或存在重叠的实现实例,则认为trait的实现是不连贯的。

存在重叠的实现实例,这个很好理解,所以理解了孤儿规则,也就理解了连贯性

下面是孤儿规则在rust语言规范中的定义:
孤儿规则
给定一个 impl<P1..=Pn> Trait<T1..=Tn> for T0 ,仅当以下至少一项为真时,这个 impl 才有效:

  • Trait 是一个 本地 trait
  • 满足以下所有条件:
    • T0..=Tn至少有一个类型是本地类型 。这里我们把第一个本地类型定义为Ti
    • No uncovered type parameters P1..=Pn may appear in T0..Ti (excluding Ti)。 P1..=Pn中的未覆盖的类型参数不能出现在 T0..Ti (不包括 Ti )中; 因为这一条比较难翻译,所以附上了英文。

我来解释一下。
一、如果trait是本地trait,那就直接满足孤儿规则了。本地trait的意思是这个trait是在当前的crate里定义的。
二、如果trait是不是本地trait。那就要同时满足两个条件:

  1. 类型T0..=Tn要至少有一个类型是本地类型。当然,一个impl可能会有多个本地类型,我们第一个本地类型定义为Ti

  2. P1..=Pn中的未覆盖的类型参数不能出现在 T0..Ti (不包括 Ti )中。
    这一条是比较难理解的,如果理解了这一条,我们就理解了孤儿规则了。
    什么是未覆盖的类型呢?
    规范里的定义是:A type which does not appear as an argument to another type. 一个类型如果它不是做为其它类型的参数而出现,那它就是未覆盖的类型
    举个例子,类型T就是未覆盖的类型,但是Vec<T>中的T就不是未覆盖的类型了,就是覆盖了的类型,因为它做为Vec的参数出现了,不是单独出现的。

    我们再来看看规范中的说明:P1..=Pn中的未覆盖的类型参数不能出现在 T0..Ti(不包括 Ti ) 中。需要注意是 T0..Ti,规范中可没要求是T0..=Tn,这一点要注意。

但是这样我们还是难以理解,下面我用代码来解释一下。

请试着编译下面的代码:

struct Entry<K, V> {key: K,value: V
}impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K {fn eq(&self, other: &Entry<K, V>) -> bool {self.eq(&other.key)}
}

如果你在rust playground里编译,会报下面的错误:

   Compiling playground v0.0.1 (/playground)
error[E0210]: type parameter `K` must be covered by another type when it appears before the first local type (`Entry<K, V>`)--> src/lib.rs:6:6|
6 | impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K {|      ^ type parameter `K` must be covered by another type when it appears before the first local type (`Entry<K, V>`)|= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the lastFor more information about this error, try `rustc --explain E0210`.
error: could not compile `playground` (lib) due to previous error

请看编译器给出的信息,其中:

= note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local, and no uncovered type parameters appear before that first local type

这不就是孤儿规则嘛。

我们来详细分析一下。
实现一个trait的语法是这样的impl<P1..=Pn> Trait<T1..=Tn> for T0
在上面的例子里,实现的代码是这样的impl<K: PartialEq, V> PartialEq<Entry<K, V>> for K {
我们可以得出:
P1 = K,P2=V
trait是PartialEq
T0 = K
T1 = Entry<K, V>
Ti是第一个本地类型,所以Ti=T1。

规范是这样规定的: P1..=Pn中的未覆盖的类型参数不能出现在 T0..Ti(不包括 Ti )
在本例中:
P1..=Pn 就是 [K,V]。
T0..Ti 就是[K,Entry<K, V>]
注意P1也就是K,出现在了T0..Ti中,而K又是一个未覆盖的类型(uncovered type),所以违反了孤儿规则,代码编译报错。

通过这个例子,我想大家就彻底搞明白了孤儿规则,以后碰到也不会觉得奇怪了。当然,不明白也没问题,如果你违反了规则,编译器会报错的。

本文为原创,转载请注明出处。
本文同时发在我的个人网站上:https://www.renhl.com/posts/2024/01/26/explaining_rust_coherence_and_orphan_rules_in_detail/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/728475.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qml中toolbox控件、ComboBox控件、PlainText实现及美化

一. 内容简介 qml中toolbox控件、ComboBox控件、PlainText实现及美化 二. 软件环境 2.1vsCode 2.2Anaconda version: conda 22.9.0 2.3pytorch 安装pytorch(http://t.csdnimg.cn/GVP23) 2.4QT 5.14.1 新版QT6.4,&#xff0c;6.5在线安装经常失败&#xff0c;而5.9版本…

[蓝桥杯 2019 省 B] 等差数列

题目链接 [蓝桥杯 2019 省 B] 等差数列 题目描述 数学老师给小明出了一道等差数列求和的题目。但是粗心的小明忘记了一部分的数列&#xff0c;只记得其中 N N N 个整数。 现在给出这 N N N 个整数&#xff0c;小明想知道包含这 N N N 个整数的最短的等差数列有几项&#x…

亚马逊运营要使用什么海外代理IP?

代理IP作为网络活动的有力工具&#xff0c;同时也是跨境电商的必备神器。亚马逊作为跨境电商的头部平台&#xff0c;吸引了大量的跨境电商玩家入驻&#xff0c;想要做好亚马逊&#xff0c;养号、测评都需要代理IP的帮助。那么应该使用什么代理IP呢&#xff1f;如何使用&#xf…

复杂系统未来演化很难准确预测

复杂系统的未来演化很难准确预测。这是由于复杂系统包含大量相互作用的组成部分&#xff0c;其行为和发展受到多种因素的影响&#xff0c;包括内部动力、外部环境变化以及意外事件等。此外&#xff0c;复杂系统通常呈现非线性关系&#xff0c;即系统的变化可能以不可预测的方式…

JS-02-javaScript快速入门

一、javaScript代码的编写位置 JavaScript代码可以直接嵌在网页的任何地方&#xff0c;但是一般&#xff0c;我们用如下编写方式。 1-1、直接写到HTML文件中 通常我们都把JavaScript代码放到<head>中&#xff0c;由<script>...</script>包含的代码就是Java…

【深度学习】1. 深度学习概述

感知器模型 人脑中的神经元:一个神经元通常具有多个树突&#xff0c;主要用来接受传入信息;而轴突只有一条&#xff0c;轴突尾端有许多轴突末梢可以给其他多个神经元传递信息。轴突末梢跟其他神经元的树突产生连接&#xff0c;从而传递信号。 而在计算机的神经网络中&#xff…

985硕的4家大厂实习与校招经历专题分享(part2)

我的个人经历&#xff1a; 985硕士24届毕业生&#xff0c;实验室方向:CV深度学习 就业&#xff1a;工程-java后端 关注大模型相关技术发展 校招offer: 阿里巴巴 字节跳动 等10 研究生期间独立发了一篇二区SCI 实习经历:字节 阿里 京东 B站 &#xff08;只看大厂&#xff0c;面试…

【leetcode刷刷】455.分发饼干 、376. 摆动序列 、53. 最大子序和

455.分发饼干 376. 摆动序列 其实贪心的想法&#xff0c;做过一次的话就不会很难想了。但这道题需要考虑的特殊情况比较复杂&#xff0c;包括平台什么的。最左边和最右边也需要考虑&#xff1a;最左边&#xff0c;添加一个平台。 可以假设&#xff0c;数组最前面还有一个数字…

Mysql - is marked as crashed and should be repaired

概述 上周发生了一个Mysql报错的问题&#xff0c;今天有时间整理一下产生的原因和来龙去脉&#xff0c;Mysql的版本是5.5,发生错误的表存储引擎都是MyISAM,产生的报错信息是Table xxxxxx is marked as crashed and should be repaired。 定位问题 产生的后果是Nginx服务没有…

Unity骚操作: Exception堆栈追踪

Exception堆栈追踪 上代码 try{SaveData saveData SaveLoadManager.Load(migrate: false);if (saveData ! null){Version v new Version(saveData.gameVersion);Version v2 new Version(Cheats.version);if (v < v2){SaveLoadManager.MigrationBackupLocalSave();SaveL…

C++入门知识点

文章目录 一、C的域作用限定符1.1全局域1.2限定域作用范围 二、C的命名空间域2.1单个命名空间的变量访问和单个不同命名空间的相同变量名的访问2.2命名空间的嵌套调用 三、C的流插入、流提取操作符四、C的缺省参数4.1函数的全缺省4.1函数的部分缺省 五、C的函数重载5.1函数重载…

【操作系统学习笔记】文件管理1.5

【操作系统学习笔记】文件管理1.5 参考书籍: 王道考研 视频地址: Bilibili 逻辑结构 VS 物理结构 逻辑结构: 从用户角度看&#xff0c;由创建文件的用户自己设计的 无结构文件 // 在用户看来是一篇连续的空间 FILE *fp fopen("test.txt", "r"); if (fp …

【算法集训】基础算法:模拟

一、基本理解 顾名思义&#xff0c;就是题目要求做什么&#xff0c;代码中就跟着做就可以。 二、题目练习 1252. 奇数值单元格的数目 根据题目要求列出如下代码。需要注意填充列和行的时候注意下标。 int oddCells(int m, int n, int** indices, int indicesSize, int* in…

this关键字

this关键字 this 是 Java 的一个关键字&#xff0c;表示某个对象 this 可以出现在构造方法、实例方法中&#xff0c;但不可以出现在类方法中 出现在构造方法中&#xff0c;代表使用该构造方法创建的对象出现在实例方法中&#xff0c;代表正在调用该方法的当前对象 一、构造…

Docker-容器网络互联

目录 1 前言 2 常用指令 3 实现容器互联 3.1 自定义网络 3.2 让容器连接创建的网络 3.2.1 容器创建后连接网络 3.2.2 容器创建时连接网络 3.3 尝试使用容器名访问(测试) 1 前言 在默认情况下&#xff0c;docker中的容器都是连接到一个虚拟的网桥上的&#xff0c;这为独…

关于yolov8的DFL模块(pytorch以及tensorrt)

先看代码 class DFL(nn.Module):"""Integral module of Distribution Focal Loss (DFL).Proposed in Generalized Focal Loss https://ieeexplore.ieee.org/document/9792391"""def __init__(self, c116):"""Initialize a convo…

Spring MVC PathVariableMethodArgumentResolver原理解析

在Spring MVC中&#xff0c;PathVariableMethodArgumentResolver是一个非常重要的组件&#xff0c;它负责解析URL路径中的变量并将其绑定到处理器方法的参数上。通过PathVariable注解&#xff0c;开发者可以方便地从URL中提取参数值&#xff0c;并传递给后端逻辑进行处理。本文…

【Web前端入门学习】—CSS

目录 CSS简介CSS语法CSS三种导入方式CSS选择器元素选择器&#xff08;标签选择器&#xff09;类选择器ID选择器通用选择器子元素选择器后代选择器&#xff08;包含选择器&#xff09;并集选择器&#xff08;兄弟选择器&#xff09;伪类选择器伪元素选择器 CSS常用属性盒子模型网…

电脑工作电压是多少你要看看光驱电源上面标的输入电压范围

要确定电脑的工作电压&#xff0c;必须查看电源上标注的输入电压范围。 国内法规规定民用220V电压范围为10%-15%&#xff0c;也就是说通信220V电压正常范围为187--242V&#xff0c;供电设备一般为180V。 --250V电压范围&#xff0c;即正常情况下电脑电源电压不低于187V即可工作…

css相邻元素边框重合问题,解决方案

1、如下图所示&#xff0c;在给元素设置边框后&#xff0c;相邻元素会出现重合的问题 2、解决方案 给每个元素设置margin-top以及margin-left为负的边框 <div style"width: 300px;display: flex;flex-wrap: wrap;margin-top: 50px;"><div style"border…