rustinlinetraitsdefault-implementation

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?


Solution

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

    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