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 impl
s 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