www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Implicit type conversions with data loss

reply "ctrl" <vlad.z.4096 gmail.com> writes:
I don't want them to be performed at all. How do I disable this 
'feature'?

For example, take a look at this code:

import std.stdio;
void main() {
	int x = -1;
	uint b = x;
	writeln(b);
}

It outputs 4294967295, but I want a compile-time error instead. 
Any suggestions?
(compiler version dmd 2.059)
Jun 05 2012
next sibling parent "Paul D. Anderson" <paul.d.removethis.anderson comcast.andthis.net> writes:
On Tuesday, 5 June 2012 at 18:06:15 UTC, ctrl wrote:
 I don't want them to be performed at all. How do I disable this 
 'feature'?

 For example, take a look at this code:

 import std.stdio;
 void main() {
 	int x = -1;
 	uint b = x;
 	writeln(b);
 }

 It outputs 4294967295, but I want a compile-time error instead. 
 Any suggestions?
 (compiler version dmd 2.059)

I doubt that a 'feature' that's been in D and it's predecessors for such a long time is going to be easy to disable. Probably the best you can do is to work with it: add an assert, perhaps, or define a new type that checks for this condition. Paul
Jun 05 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
ctrl:

 I don't want them to be performed at all. How do I disable this 
 'feature'?

 For example, take a look at this code:

 import std.stdio;
 void main() {
 	int x = -1;
 	uint b = x;
 	writeln(b);
 }

 It outputs 4294967295, but I want a compile-time error instead. 
 Any suggestions?
 (compiler version dmd 2.059)

D is designed to be a safe language, maybe it will be used for industrial processes that require a significant amount of safety. So D tries to _statically_ refuse value conversions that cause data loss. But for practical reasons (this mean to avoid the introduction of too many casts, that are even more dangerous) this rule is not adopted in some cases. As example D allows you to assign doubles<==float, that causes some precision loss. An int and uint are represented with 32 bits, so casting one to the other doesn't cause data loss, but the range of the numbers they represent is different, so in general their conversion is unsafe. Languages as Ada, Delphi, C# and few others (C/C++ too, with a new Clang feature) know that overflow of fixnums is a very common source of bad bugs, so they offer optional run-time tests to assignments and numerical operations. D too will eventually need those. In the meantime you can do this, that's not so fast (the inlined tests in Ada/C#/Delphi are far faster): import std.stdio, std.conv; void main() { int x = -1; auto b = to!uint(x); writeln(b); } Or you can add an assert/enforce, or you can create a small struct that represent safely assignable uints, etc. No solution is good. Bye, bearophile
Jun 05 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
 Languages as Ada, Delphi, C# and few others (C/C++ too, with a 
 new Clang feature) know that overflow of fixnums is a very 
 common source of bad bugs, so they offer optional run-time 
 tests to assignments and numerical operations. D too will 
 eventually need those.

A little example of the difficulties involved: http://blog.regehr.org/archives/721 Bye, bearophile
Jun 05 2012
prev sibling next sibling parent "Thiez" <thiezz gmail.com> writes:
On Tuesday, 5 June 2012 at 22:17:57 UTC, bearophile wrote:
 Or you can add an assert/enforce, or you can create a small 
 struct that represent safely assignable uints, etc. No solution 
 is good.

 Bye,
 bearophile

Surely structs could work? struct safeType(T) { T value; } Define all operations that you can safely perform on T on the struct, but only with structs of the same type and on T. It wouldn't be very pretty, but I would work, wouldn't it? Writing the template would be annoying but you'd only have to do it once.
Jun 05 2012
prev sibling next sibling parent Dmitry Olshansky <dmitry.olsh gmail.com> writes:
On 05.06.2012 22:06, ctrl wrote:
 I don't want them to be performed at all. How do I disable this 'feature'?

 For example, take a look at this code:

 import std.stdio;
 void main() {
 int x = -1;
 uint b = x;
 writeln(b);
 }

 It outputs 4294967295, but I want a compile-time error instead. Any
 suggestions?
 (compiler version dmd 2.059)

There is no information lost. Try casting it back to int. -- Dmitry Olshansky
Jun 05 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Wednesday, June 06, 2012 10:07:04 Dmitry Olshansky wrote:
 On 05.06.2012 22:06, ctrl wrote:
 I don't want them to be performed at all. How do I disable this 'feature'?
 
 For example, take a look at this code:
 
 import std.stdio;
 void main() {
 int x = -1;
 uint b = x;
 writeln(b);
 }
 
 It outputs 4294967295, but I want a compile-time error instead. Any
 suggestions?
 (compiler version dmd 2.059)

There is no information lost. Try casting it back to int.

int <-> uint is a narrowing conversion in _both_ directions, and doesn't lose data in _either_ direction, which I find rather funny. In any case, if you want to do such a conversion while checking to make sure that the value will fit in the type being converted to, you can use std.conv.to: auto x = to!uint(-1); //this wil throw auto y = to!int(uint.max); //this will throw But the only way to statically prevent such conversions is to wrap your integers in structs. In some ways, making implicit conversions between signed and unsigned types would be nice, but you need to convert one to the other often enough, that all of the necessary casting could get quite annoying, and if you're using an explicit cast rather than std.conv.to, you actually get _less_ safety, because the cast will work even if the current implicit conversion wouldn't. For example, int x = -1; //illegal, except in cases where the compiler can statically determine that //the conversion won't be truncated (which it could determine in this case, //but not in the general case). ushort y = x; //Legal regardless of the value of x. ushort z = cast(ushort)x; So, while disallowing the implicit conversion would have some benefits, there's a good chance that it would ultimately cause far more problems than it would solve. - Jonathan M Davis
Jun 05 2012
prev sibling next sibling parent "renoX" <renozyx gmail.com> writes:
On Tuesday, 5 June 2012 at 18:06:15 UTC, ctrl wrote:
 I don't want them to be performed at all. How do I disable this 
 'feature'?

 For example, take a look at this code:

 import std.stdio;
 void main() {
 	int x = -1;
 	uint b = x;
 	writeln(b);
 }

 It outputs 4294967295, but I want a compile-time error instead. 
 Any suggestions?
 (compiler version dmd 2.059)

You want a sane language: use a different language, most C-derived language have insane semantic for integers.. Have you tried Ada? BR, renoX
Jun 06 2012
prev sibling next sibling parent "ctrl" <vlad.z.4096 gmail.com> writes:
Thanks for your answers.

 You want a sane language: use a different language, most 
 C-derived language have insane semantic for integers..
 Have you tried Ada?

I want a language with metaprogramming and compile-time computations.
Jun 06 2012
prev sibling parent "renoX" <renozyx gmail.com> writes:
On Thursday, 7 June 2012 at 03:19:18 UTC, ctrl wrote:
 Thanks for your answers.

 You want a sane language: use a different language, most 
 C-derived language have insane semantic for integers..
 Have you tried Ada?

I want a language with metaprogramming and compile-time computations.

A google search reported that it was an explicit requirement of Ada to not have macros or the like to simplify debugging.. The only language that I know who has what you want and a sane integer semantic (very rare) is Nimrod ( http://nimrod-code.org/ ). I've learned about Nimrod only a few weeks ago, it seems to be an interesting language, but its OO syntax is "too simple" ( http://forum.nimrod-code.org/t/3 ). renoX
Jun 07 2012