In mutagen, I use specialization to mutate
binary operations where possible. Basically, I replace a + b with
::mutagen::AddSub::add(a, b, mutation_count) Alas, it fails in the presence
of shift operations, because type inference fails.
I've reduced the problem to a very simple test case:
use std::ops::Shl;
fn main() {
println!("{}", 1u32.shl(2) * 3);
}
This fails with error[E0277]: cannot multiply i32 to u32. This appears to
happen because std::ops::Shl is implemented for all sorts of integers, and
while those impls always return the self type (but not Self, as I see from
the source), typeck may not see through them, and coming up empty, defaulting
to i32. If you replace the 1u32.shl(2) with (1u32 << 2), it works.
So forwarding std::ops::Shl/Shr won't work either using a custom trait
(as in pub trait AddSub) or using a wrapper type for the left-hand side of
the operation. In both cases, the type inference fails to see the equality of
Self and Self::Output for integer shifts, despite knowing Self.
Is this a bug? Is there a workaround? What causes it?
This is not a bug. The reason for this is some special binary operations handling for non (or semi-)inferred types in typeck.
A workaround is to fix the return type of the expression by using an if-expression where one branch is the original binary operation and the other is the mutated operation, e.g.
(if ::mutagen::now(42) {
::mutagen::ShlShr::shl(left, right)
} else {
left << right
})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With