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?
If I understand the question correctly, you are asking two things:
magnitude
?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