What are some ways to get more strict type-checking?

Devin lee.hastings at outlook.com
Mon May 6 02:02:52 UTC 2019


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.


More information about the Digitalmars-d-learn mailing list