kbec
kbec

Reputation: 3465

Can compiler do a default implementation's inlining of the trait's method?

I understand that the trait's method doesn't have a body, so there is nothing to inline. But is there any sense to mark its default implementation like this?

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

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

Do I need to rewrite whole method body and mark this impl's method with #[inline] when implementing the trait for type rather than marking just trait's method as above?

Upvotes: 0

Views: 291

Answers (1)

Jmb
Jmb

Reputation: 23443

If I understand the question correctly, you are asking two things:

  • Will the compiler inline calls to magnitude?
  • Will the compiler be able to inline the call to square_magnitude inside magnitude if square_magnitude is itself declared inline even though the code for square_magnitude is not available in the trait?

As to the first, there is no reason why it couldn't. As to the second the answer is yes, the compiler will be able to inline both functions because by the time it generates the code, the source for both functions is available. This can be seen in the disassembly:

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()
}

Compiled with rustc v1.28.0 and option -O:

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

Note however that the compiler will not inline square_magnitude inside magnitude if square_magnitude is not declared inline itself:

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

Generates:

<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

Upvotes: 4

Related Questions