Rust中有哪些规则,类似于规则,在此处描述了http://en.cppreference.com/w/cpp/language/eval_order for C++?
现在我从经验上发现,
1)函数的参数按直接顺序进行评估
2)所有带副作用的内置操作(=,+ =, - =等)返回单位,因此很难(但可能)编写表达式,在C++中显示UB.
一个例子:
let mut a = 1i;
let b = 2i;
let c = 3i;
let d = (a = b) == (a = c); // What is a? (a is actually 3)
Run Code Online (Sandbox Code Playgroud)
3)似乎函数调用按照C++中的顺序进行排序
4)似乎内置操作被排序,就好像它们是函数(方法)调用一样,即评估顺序与运算符优先级相关联
我的结论是否正确?什么是确切的评估模型?
我不相信它已被明确定义,我对手册的轻击没有发现任何东西.但是,我可以保证这些东西不会是未定义的行为(Rust明确地避免UB外部unsafe代码),如果它只是"从左到右",即你推断的顺序,我会感到惊讶.虽然,#6268的分辨率可能导致最后评估接收器的方法(或者可能不是,这只是一种可能性).
我打开#15300.
顺便说一句,如果你正在研究这个问题,你可以让编译器按照精确的评估顺序拆分出漂亮的控制流图(注意.这是所有内部API,所以不能依赖它,比编译编译器更可能崩溃,并没有隐藏编译器实现细节:它主要是为工作的人设计的rustc).
正如@pnkfelix指出的那样,编译器没有使用CFG进行代码生成(截至2014-07-02),这意味着CFG不能保证完全准确.
例如,采用@ ChrisMorgan的一个例子的精简版:
fn foo(_: (), x: int) -> int {
x
}
fn main() {
let mut a = 1;
{ // A
a * foo(a = 3, a)
};
}
Run Code Online (Sandbox Code Playgroud)
我们希望编译器在某个块(即{ ... })中拆分语句/表达式的控制流图,这可以通过--pretty flowgraph=<nodeid>编译器的选项来完成,但为此我们需要拥有感兴趣的块的ID.在这种情况下,我们想要的块是A.要获得id编译rustc --pretty expanded,identified(请注意,只使用identified是一个无意义的遗物:现在只在宏扩展后才分配id):
#![feature(phase)]
#![no_std]
#![feature(globs)]
#[phase(plugin, link)]
extern crate std = "std#0.11.0-pre";
extern crate native = "native#0.11.0-pre";
use std::prelude::*;
fn foo(_ /* pat 7 */: (), x /* pat 11 */: int) -> int { (x /* 15 */) } /*
block 14 */ /* 4 */
fn main() {
let mut a /* pat 22 */ = (1 /* 23 */);
({
((a /* 28 */) *
((foo /* 30
*/)(((a /* 32 */) = (3 /* 33 */) /* 31 */), (a /* 34 */)) /*
29 */) /* 27 */)
} /* block 26 */ /* 25 */);
} /* block 18 */ /* 16 */
Run Code Online (Sandbox Code Playgroud)
很多肮脏的内部垃圾,但我们需要的是在评论中/* block 26 */.rustc --pretty flowgraph=26给出一个点文件,呈现如下.您可以参考上面标识符的注释源来准确地处理每个表达式(id = ..位):

(对不起,显然这段代码没有分支,因此只是一长串操作.)
FWIW,表达式评估为9,而我期待3(并且控制流程图确认aLHS上的隔离正在RHS之后进行评估,包括a = 3那里).我已经在#15300上提出了这个问题(e:现在将其分离为评估顺序中的一个奇怪的差异).
| 归档时间: |
|
| 查看次数: |
302 次 |
| 最近记录: |