编译器可以对trait方法的默认实现进行内联吗?

时间:2018-09-02 21:15:12

标签: rust inline traits default-implementation

我知道该特征的方法没有主体,因此没有内联的内容。但是,有没有办法这样标记其默认实现?

trait Magnitude {
    fn square_magnitude( &self ) -> f64;

    #[inline]
    fn magnitude( &self ) -> f64 {
        self.square_magnitude().sqrt()
    }
}

实现类型的特征时,我是否需要重写整个方法主体并用#[inline]标记此impl的方法,而不是像上面那样仅标记特征的方法?

1 个答案:

答案 0 :(得分:3)

如果我正确理解了这个问题,那么您在问两件事:

  • 编译器是否会内联调用magnitude
  • 即使square_magnitude的代码本身未声明为magnitude,即使square_magnitude的代码本身未声明为inline,编译器仍能够在square_magnitude中内联对trait Magnitude { fn square_magnitude( &self ) -> f64; #[inline] fn magnitude( &self ) -> f64 { self.square_magnitude().sqrt() } } struct Vector { x: f64, y: f64 } impl Magnitude for Vector { #[inline] fn square_magnitude (&self) -> f64 { self.x*self.x + self.y*self.y } } pub fn test (x: f64, y: f64) -> f64 { let v = Vector { x: x, y: y }; v.magnitude() } 的调用可以在特征中使用吗?

关于第一个,没有理由没有。至于第二个答案是肯定的,编译器将能够内联这两个函数,因为在生成代码时,这两个函数的源都可用。可以在disassembly中看到:

-O

使用rustc v1.28.0和选项example::test: mulsd xmm0, xmm0 mulsd xmm1, xmm1 addsd xmm1, xmm0 xorps xmm0, xmm0 sqrtsd xmm0, xmm1 ret 编译:

impl Magnitude for Vector {
    fn square_magnitude (&self) -> f64 {
        self.x*self.x + self.y*self.y
    }
}

但是请注意,compiler will not inline square_magnitude inside magnitude if square_magnitude is not declared inline itself

<example::Vector as example::Magnitude>::square_magnitude:
        movsd   xmm1, qword ptr [rdi]
        movsd   xmm0, qword ptr [rdi + 8]
        mulsd   xmm1, xmm1
        mulsd   xmm0, xmm0
        addsd   xmm0, xmm1
        ret

example::test:
        mulsd   xmm0, xmm0
        mulsd   xmm1, xmm1
        addsd   xmm1, xmm0
        xorps   xmm0, xmm0
        sqrtsd  xmm0, xmm1
        ret

生成:

$WORKON_HOME