Recently, I poorly refactored some code, which introduced an
obvious bug. But to my astonishment, the broken code compiled
without any warnings or notifications. A minimum example is
shown below:
alias ID = uint;
struct Data
{
ID id;
this(ID id)
{
this.id = id;
}
}
// Forgot to refactor a function to return its
// loaded data, rather than a success/fail bool
bool load_data()
{
// some processing
return true;
}
int main()
{
// Very obviously a bug,
// but it still compiles
Data d = load_data();
return 0;
}
So I'm assigning a boolean value to a struct with one uint field.
The compiler interprets the attempted assignment as calling the
constructor with one argument, and then converts the boolean to a
uint to match the function overload. So in effect, my struct is
implicitly convertible from a bool.
My question is basically... how do I make this not compile? What
methods do I have to prevent this sort of crazy implicit
conversion? I'm not familiar enough with the language to know my
options. I think there are a few:
* Enable more warnings. DMD seems to only have "-w", which I
believe is enabled through dub. Are there more pedantic settings
that would catch this conversion?
* Change "ID" from an alias to a struct of some sort. I've been
trying to find similar issues, and I saw once suggested that a
person could make a struct with one member and conversions to and
from different types. I've also seen "alias X this;" a lot. But
my main issues is stopping these conversions, and everything I've
seen is about enabling automatic conversion. Ideally, I would
have something that's convertible TO a uint when needed, but
can't be converted FROM other data types.
* Replace the constructor with a static function. This happened
because D implicitly converted my assignment into a constructor
call. If I just don't have constructors, and instead define a
static function to build instances of the struct, I could then
have more control over assignment and avoid this more easily.
If anyone has other options, I would really want to hear them. I
know for a fact these types of issues are going to crop up in my
project, and I want to nip them in the bud before the become
harder to track down.