【问题标题】:When does type binding happen in Rust?Rust 什么时候发生类型绑定?
【发布时间】:2018-08-27 04:08:30
【问题描述】:

据我所知:在 C 语言中,变量的“类型”是在编译时绑定的,而该变量的值是在运行时绑定的。

例如,在int a = 10; 中,类型int 在编译期间绑定到变量a,而实际值10 在运行期间绑定(或分配)给它。

但在 Rust 中,我们有 let a = 2;。在这里,类型(比如 Rust 中任何整数类型的 i32)何时绑定到 a

我正在构建一个前端 Rust 编译器,目前正在编写解析器阶段。此时,我应该为这些变量分配什么类型?

【问题讨论】:

    标签: rust programming-languages computer-science


    【解决方案1】:

    类型绑定在编译时执行。这是必要的,这样编译器才能发出正确的机器指令(例如,x86_64 处理器不会将两个 i32s 相乘,就像它将两个 i64s 相乘一样)。

    许多动态类型语言,例如 Python 或 Lua,将携带类型信息以及值(不是变量),并在运行时根据每个操作数的类型分派操作。另一方面,静态类型语言,例如 C 或 Rust,通常会丢弃大部分类型信息。这不是必需的,因为执行操作所需的机器指令是直接在可执行文件中发出的(这使得静态类型程序比可比较的动态类型程序更快)。

    我们可以通过让编译器告诉我们类型错误(这称为类型检查)来证明类型绑定是在编译时完成的。这是一个例子:

    fn squared(x: f64) -> f64 {
        x * x
    }
    
    fn main() {
        let a = 2i32;
        println!("{}", squared(a));
    }
    

    编译它会得到以下输出:

    error[E0308]: mismatched types
     --> src/main.rs:7:28
      |
    7 |     println!("{}", squared(a));
      |                            ^ expected f64, found i32
    

    Rust 编译器可以根据使用情况推断许多变量的类型(类似于 auto 在 C++ 中的工作方式)。当它不能时,它会给出一个错误。例如:

    fn main() {
        let a;
    }
    

    给出这个输出:

    error[E0282]: type annotations needed
     --> src/main.rs:2:9
      |
    2 |     let a;
      |         ^
      |         |
      |         cannot infer type for `_`
      |         consider giving `a` a type
    

    当编译器遇到错误时,它会停止并且不会生成可运行的可执行文件。由于我们的程序没有可执行形式,因此没有“运行时”,因此上述情况发生在编译时。

    【讨论】:

    • 值得指出的是,“编译时间”实际上是由许多个步骤组成的。词法分析、解析、类型推断、去糖、内联、单态化、优化、机器代码生成(可能还有数十或数百个其他步骤)都发生在“编译时”期间。知道类型是在编译时分配的,就好像说印度洋中有一滴水:它比“在海洋中”更具体,但仍有很多空间需要覆盖。
    • 好的,如果我正在为 Rust 编写解析器,那么我应该为变量添加一些虚拟类型并继续前进吗?
    • @RahulBharadwaj 为什么不看看 rustc 本身 does it 是怎样的?你可以看到它有一个特殊的类型Infer,它只是为源代码中不明确的那种类型而设计的。稍后,当编译器开始检查类型时,所有的 Infer 都会被实际类型替换。
    • 好的,谢谢你的建议。我去看看。
    猜你喜欢
    • 2012-03-17
    • 2013-02-09
    • 2017-02-18
    • 2018-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    相关资源
    最近更新 更多