匹配人体工学遇到参考模式会怎么办?
What will match ergonomics do when encounters reference pattern?
看过the rfc 2005,知道操纵的过程是一个反复的操作。我说 encounters reference pattern
,我不是在谈论在第一次迭代时遇到参考模式,如下所示:
let x = &String;
// The binding mode is `move`, so x is of type `&String`
但有些情况下 binding mode
在之前的 non-reference pattern
迭代中移动到 ref/ref mut
,然后遇到 reference pattern
.
我仔细阅读了rfc,发现了这句话The *default binding mode* only changes when matching a reference with a non-reference pattern.
,这是否意味着reference pattern
不会对匹配过程做任何事情,但是有人告诉我reference pattern
会将绑定模式重置为默认值 move
(参见案例 2)。
有两种情况“正确”的推论似乎相互冲突:
Correct means that the inferred type is the same as the one inferred by the compiler, but I don't know if the inferring process is also correct, which is the reason why I post this question.
// case 1
let (a, b) = &(&String, &String); // a and b are of type &&String
// case 2
let (&a, &b) = &(&String, &String); // a and b are of type String
案例 1 的推论:
首先,我们将 &(&String, &String)
与 (a, b)
进行匹配,而 (a, b)
是 non-reference pattern
,因此我们取消引用 &(&String, &String)
并设置 binding mode
从 move(default one)
到 ref
。然后我们将 (&String, &String)
与 (a, b)
匹配,使用 ref
绑定模式, a
和 b
是 &&String
.
类型
Why did it stop at matching (&String, &String)
against (a, b)
, shouldn't we continue to match &String
against a
and b
respectively?
If we continue, matching &String
against a
, a
is reference pattern
, what should we do now?
案例 2 的推论:
首先,我们将 &(&String, &String)
与 (&a, &b)
进行匹配,(&a, &b)
是 non-reference pattern
,因此我们取消引用 &(&String, &String)
并将 binding mode
设置为ref
。然后我们匹配(&String, &String)
对(&a, &b)
,这基本上是匹配&String
对&a
,&a
是reference pattern
,所以我们将绑定模式重置为 move
,使 a
成为 String
.
类型
矛盾:
情况2,当遇到引用模式时,我们所做的是将绑定模式重置为默认move
。但是在情况 1 中(如果我们没有在那一点停止,保持 &String
与 a
匹配),a
也是 reference pattern
,如果我们仍然将绑定模式重置为移动,那么 a 的类型将是 &String
而不是 &&String
.
还有一个问题,就是when should this inferring algorithm stop
?在情况 1 中,如果算法 应该 在该点停止,那么一切都有意义。
看来我找到了答案。有几件事需要澄清:
match ergonomics
只涵盖了我们匹配non-reference pattern
对reference
的情况,所以这个问题的标题是错误的,match ergonomics
遇到reference pattern
什么都没有。 match ergonomics
的算法是这样的:
fn match_ergonomics() {
if (the reference we are matching is `&xx`) {
binding_mode = `ref`
} else if (the reference we are matching is `&mut xx`) {
if (binding_mode == `ref`) {
binding_mode = `ref`;
} else {
binding_mode = `ref mut`;
}
}
}
default binding mode
是为match ergonomics
引入的概念,但这并不是match ergonomics
涵盖的情况所独有的,它已经融入了整个rust匹配系统。
reference pattern
的概念可能会造成混淆。在 rfc
:
A reference pattern is any pattern which can match a reference without coercion. Reference patterns include bindings, wildcards (_
), const
s of reference types, and patterns beginning with &
or &mut
.
而在 Rust 参考中,它只是以 &/&mut
开头的模式。
匹配是一个递归的过程,对于这个递归的每一个过程,根据我们遇到的pattern有几种情况,其中包括match ergonomics
种情况
其实有两种情况我们会改变DBD,一种是匹配non-reference pattern
对reference
,另一种是匹配&[mut] pat
对reference
.
matching
against
change to DBM
non-ref pattern
reference
set to ref
or ref mut
&[mut] pat
reference
set to move
匹配算法
// The terminologies we are using in this algorithm come from rust reference
If no `default binding mode` is set, set the `default binding mode` to `move`.
If the pattern is an identifier pattern:
If we have explicit `ref`:
bind by reference;
else if we have explicit `ref mut`:
bind by mutable reference;
else:
// When explicit `ref/ref mut` are absent
// default binding mode decides how to bind
If the binding mode is `move`, bind directly.
If the binding mode is `ref`, bind by immutable reference.
If the binding mode is `ret mut`, bind by mutable reference.
If the pattern has an inner pattern, repeat this process with that pattern.
else if the pattern is a `&[mut]` reference pattern:
// matching `&[mut]` against non-reference triggers
// a compiler error
Ensure that we are matching against a `&[mut]` reference.
Dereference the scrutinee expression.
Set the binding mode to `move`.
Repeat this process with the inner pattern.
else if the pattern is any kind of destructuring pattern:
Set `T` to the type implied by the pattern.
Ensure that we are matching against a `T` value or `&[mut] T` reference.
// cases covered by match ergonomics
If we are matching against a `&T` reference:
Dereference the scrutinee expression.
Set the binding mode to `ref`.
else if we are matching against a `&mut T` reference:
Dereference the scrutinee expression.
If the binding mode is `move`, set the binding mode to `ref mut`.
else
destructure the value;
Repeat this process for all fields in the pattern.
案例 1 和案例 2 的推断
// case 1
let (a, b) = &(&String, &String); // a and b are of type &&String
第一个过程:我们将 (a, b)
与&(&String, &String)
进行匹配,这进入了案例 3(任何其他类型的解构模式)。 &(&String, &String)
是一个 &T
,因此取消引用并将 default binding mode
设置为 ref
。
第二步:我们正在匹配(a, b)
和(&String, &String)
,这基本上是匹配a
和&String
。 a
是一个标识符模式,它进入案例 1。我们没有明确的 ref/ref mut
并且 default binding mode
是 ref
,所以通过不可变引用绑定,使 a
类型 &&String
.
所有模式都匹配,递归结束。
// case 2
let (&a, &b) = &(&String, &String); // a and b are of type String
第一个过程:我们将 (&a, &b)
与 &(&String, &String)
进行匹配,这进入了案例 3。取消引用并将 default binding mode
设置为 ref
第二步:我们正在匹配(&a, &b)
和(&String, &String)
,这基本上是匹配&a
和&String
。 &String
是一个 reference pattern
,所以我们进入情况 2,并将 default binding mode
设置为 move
、&a = &String
,因此 a 的类型为 String
所有模式都匹配,递归结束。
算法可能不是那么准确,欢迎懂这方面的人来编辑这个答案。
看过the rfc 2005,知道操纵的过程是一个反复的操作。我说 encounters reference pattern
,我不是在谈论在第一次迭代时遇到参考模式,如下所示:
let x = &String;
// The binding mode is `move`, so x is of type `&String`
但有些情况下 binding mode
在之前的 non-reference pattern
迭代中移动到 ref/ref mut
,然后遇到 reference pattern
.
我仔细阅读了rfc,发现了这句话The *default binding mode* only changes when matching a reference with a non-reference pattern.
,这是否意味着reference pattern
不会对匹配过程做任何事情,但是有人告诉我reference pattern
会将绑定模式重置为默认值 move
(参见案例 2)。
有两种情况“正确”的推论似乎相互冲突:
Correct means that the inferred type is the same as the one inferred by the compiler, but I don't know if the inferring process is also correct, which is the reason why I post this question.
// case 1
let (a, b) = &(&String, &String); // a and b are of type &&String
// case 2
let (&a, &b) = &(&String, &String); // a and b are of type String
案例 1 的推论:
首先,我们将 &(&String, &String)
与 (a, b)
进行匹配,而 (a, b)
是 non-reference pattern
,因此我们取消引用 &(&String, &String)
并设置 binding mode
从 move(default one)
到 ref
。然后我们将 (&String, &String)
与 (a, b)
匹配,使用 ref
绑定模式, a
和 b
是 &&String
.
Why did it stop at matching
(&String, &String)
against(a, b)
, shouldn't we continue to match&String
againsta
andb
respectively?If we continue, matching
&String
againsta
,a
isreference pattern
, what should we do now?
案例 2 的推论:
首先,我们将 &(&String, &String)
与 (&a, &b)
进行匹配,(&a, &b)
是 non-reference pattern
,因此我们取消引用 &(&String, &String)
并将 binding mode
设置为ref
。然后我们匹配(&String, &String)
对(&a, &b)
,这基本上是匹配&String
对&a
,&a
是reference pattern
,所以我们将绑定模式重置为 move
,使 a
成为 String
.
矛盾:
情况2,当遇到引用模式时,我们所做的是将绑定模式重置为默认move
。但是在情况 1 中(如果我们没有在那一点停止,保持 &String
与 a
匹配),a
也是 reference pattern
,如果我们仍然将绑定模式重置为移动,那么 a 的类型将是 &String
而不是 &&String
.
还有一个问题,就是when should this inferring algorithm stop
?在情况 1 中,如果算法 应该 在该点停止,那么一切都有意义。
看来我找到了答案。有几件事需要澄清:
match ergonomics
只涵盖了我们匹配non-reference pattern
对reference
的情况,所以这个问题的标题是错误的,match ergonomics
遇到reference pattern
什么都没有。match ergonomics
的算法是这样的:fn match_ergonomics() { if (the reference we are matching is `&xx`) { binding_mode = `ref` } else if (the reference we are matching is `&mut xx`) { if (binding_mode == `ref`) { binding_mode = `ref`; } else { binding_mode = `ref mut`; } } }
default binding mode
是为match ergonomics
引入的概念,但这并不是match ergonomics
涵盖的情况所独有的,它已经融入了整个rust匹配系统。reference pattern
的概念可能会造成混淆。在rfc
:A reference pattern is any pattern which can match a reference without coercion. Reference patterns include bindings, wildcards (
_
),const
s of reference types, and patterns beginning with&
or&mut
.而在 Rust 参考中,它只是以
&/&mut
开头的模式。匹配是一个递归的过程,对于这个递归的每一个过程,根据我们遇到的pattern有几种情况,其中包括
match ergonomics
种情况其实有两种情况我们会改变DBD,一种是匹配
non-reference pattern
对reference
,另一种是匹配&[mut] pat
对reference
.matching against change to DBM non-ref pattern reference set to ref
orref mut
&[mut] pat reference set to move
匹配算法
// The terminologies we are using in this algorithm come from rust reference
If no `default binding mode` is set, set the `default binding mode` to `move`.
If the pattern is an identifier pattern:
If we have explicit `ref`:
bind by reference;
else if we have explicit `ref mut`:
bind by mutable reference;
else:
// When explicit `ref/ref mut` are absent
// default binding mode decides how to bind
If the binding mode is `move`, bind directly.
If the binding mode is `ref`, bind by immutable reference.
If the binding mode is `ret mut`, bind by mutable reference.
If the pattern has an inner pattern, repeat this process with that pattern.
else if the pattern is a `&[mut]` reference pattern:
// matching `&[mut]` against non-reference triggers
// a compiler error
Ensure that we are matching against a `&[mut]` reference.
Dereference the scrutinee expression.
Set the binding mode to `move`.
Repeat this process with the inner pattern.
else if the pattern is any kind of destructuring pattern:
Set `T` to the type implied by the pattern.
Ensure that we are matching against a `T` value or `&[mut] T` reference.
// cases covered by match ergonomics
If we are matching against a `&T` reference:
Dereference the scrutinee expression.
Set the binding mode to `ref`.
else if we are matching against a `&mut T` reference:
Dereference the scrutinee expression.
If the binding mode is `move`, set the binding mode to `ref mut`.
else
destructure the value;
Repeat this process for all fields in the pattern.
案例 1 和案例 2 的推断
// case 1
let (a, b) = &(&String, &String); // a and b are of type &&String
第一个过程:我们将 (a, b)
与&(&String, &String)
进行匹配,这进入了案例 3(任何其他类型的解构模式)。 &(&String, &String)
是一个 &T
,因此取消引用并将 default binding mode
设置为 ref
。
第二步:我们正在匹配(a, b)
和(&String, &String)
,这基本上是匹配a
和&String
。 a
是一个标识符模式,它进入案例 1。我们没有明确的 ref/ref mut
并且 default binding mode
是 ref
,所以通过不可变引用绑定,使 a
类型 &&String
.
所有模式都匹配,递归结束。
// case 2
let (&a, &b) = &(&String, &String); // a and b are of type String
第一个过程:我们将 (&a, &b)
与 &(&String, &String)
进行匹配,这进入了案例 3。取消引用并将 default binding mode
设置为 ref
第二步:我们正在匹配(&a, &b)
和(&String, &String)
,这基本上是匹配&a
和&String
。 &String
是一个 reference pattern
,所以我们进入情况 2,并将 default binding mode
设置为 move
、&a = &String
,因此 a 的类型为 String
所有模式都匹配,递归结束。
算法可能不是那么准确,欢迎懂这方面的人来编辑这个答案。