Today I was trying to implement (Minisat's) Lit
(Literal) type that is a 32-bit sized data structure that merges a 31-bit value (representing a VarRef
) and a 1-bit sign-like type for space optimization.
For this I have wrote a tuple-struct that has consists of a single private u32
type member.
Access to the intern value is given by the following methods:
struct VarRef(pub u32);
enum Sign{ Pos, Neg }
struct Lit(u32);
impl Lit {
pub fn new<V: Into<VarRef>, S: Into<Sign>>(var: V, sign: S) -> Self
where V: Into<VarRef>, S: Into<Sign> {..}
pub fn var(&self) -> VarRef {..}
pub fn sign(&self) -> Sign {..}
pub fn negate(&self) -> Self {..}
}
The internal bit-structure was to put the sign-bit as the most-valueable-bit.
The var
, sign
and negate
methods were not a problem at all.
However, I had type inference problems in the new
method that tries to merge the given
parameters var
and sign
into the single u32
.
My first try was the obvious:
pub fn new<V: Into<VarRef>, S: Into<Sign>>(var: V, sign: S) -> Self
where V: Into<VarRef>,
S: Into<Sign>
{
it(var.into().into() + (sign.into().into() << 31))
}
There I use the implemented From
trait to cast the given val
into a VarRef
which itself is a tuple-struct of a single u32
and cast that to a u32
.
The sign
parameter was treated similarly but with the conversions to Sign
and u32
with a left-bit-shift of 31 bits.
On compiling the compiler stated the following:
types/lit.rs:21:18: 21:22 error: unable to infer enough type information about
_; type annotations or generic parameter binding required [E0282] types/lit.rs:21 Lit(var.into().into() + (sign.into().into() << 31)) ^~~~
The solution to this was:
pub fn new<V: Into<VarRef>, S: Into<Sign>>(var: V, sign: S) -> Self
where V: Into<VarRef>,
S: Into<Sign>
{
let v: VarRef = var.into();
let s: Sign = sign.into();
let vi: u32 = v.into();
let si: u32 = s.into();
Lit(vi + si << 31)
}
Which is equivalent to what I am doing above with just the added type information that the compiler was asking for.
However, I find this kind of frustrating that the compiler isn't able to infer this information.
Questions
- What are the reasons for that?
- Am I doing something wrong in the current implementation?
- Is my usage of the From trait too elaborated?
Regards