名称解析从trait实现静态方法时的错误



以下是教程中稍作修改的示例:

use std::f64::consts::PI;
trait Awesome {
  fn how_awesome() -> int;
}
struct Circle { radius: f64 }
impl Circle {
    fn area(&self) -> f64 { self.radius * self.radius * PI }
    fn new(area: f64) -> Circle { Circle { radius: (area / PI).sqrt() } }
}

impl Awesome for Circle {
    fn how_awesome() -> int { 5 }
}
fn main() {
    let c = Circle::new(42.5); // fine
    let c2 = Circle::how_awesome(); // error: unresolved name `Circle::how_awesome`.
}

它可以比这更奇怪:

struct Point {
  x: f64,
  y: f64
}
impl Awesome for Point {
    fn how_awesome() -> int { 3 }
}
fn main() {
    let p = Point::how_awesome();
}

导致

ERROR:rustc::middle::resolve: !!! (resolving module in lexical scope) module wasn't actually a module!
type.rs:41:11: 41:25 error: unresolved name
type.rs:41   let p = Point::how_awesome();
                     ^~~~~~~~~~~~~~
type.rs:41:11: 41:25 error: use of undeclared module `Point`
type.rs:41   let p = Point::how_awesome();
                     ^~~~~~~~~~~~~~
ERROR:rustc::middle::resolve: !!! (resolving module in lexical scope) module wasn't actually a module!
type.rs:41:11: 41:25 error: unresolved name `Point::how_awesome`.
type.rs:41   let p = Point::how_awesome(); 
                     ^~~~~~~~~~~~~~

我使用相当新鲜的每晚:

rustc 0.11.0-pre-nightly (db5ca23 2014-05-14 01:06:24 -0700)
host: x86_64-unknown-linux-gnu

搜索这个问题绝对没有任何问题。

目前,所有方法都有其trait的作用域,包括静态方法。在实现统一函数调用语法(UFCS)之前,您需要在trait本身上调用它们:

let p = Awesome::how_awesome();

然而,编译器需要一些方法来确定应该使用哪个trait的实现,即一些方法来推断for的RHS上的类型以找到特定的impl。如前所述,how_awesome方法根本没有提到这个Self类型,所以编译器没有办法仅仅推断它(就像Default trait的default方法一样,它可以像let x: Type = Default::default();一样使用)。

应该有一种手动指定它的方法,但我们目前没有。这也是UFCS RFC所涵盖的内容,目前唯一的方法是像

这样的hack:
struct Point {
  x: f64,
  y: f64
}
trait Awesome {
    fn how_awesome(_ignored: Option<Self>) -> int;
}
impl Awesome for Point {
    fn how_awesome(_ignore: Option<Point>) -> int { 0 }
}
fn main() {
    let p = Awesome::how_awesome(None::<Point>);
}

我提交了#14225关于Point::how_awesome的丑陋错误。

最新更新