The following code fails:
static assert(-("foo".length) < 0);
Comment #1 by schveiguy — 2013-05-16T06:37:28Z
This is expected, array length is an unsigned property. unsigned math results in unsigned result.
You are basically saying:
static assert(-3u < 0)
0 is promoted to unsigned, and 0xff_ff_ff_fd is compared to it.
Comment #2 by sibaqexozequgaba — 2013-05-16T10:36:20Z
Should a negative unsigned number even compile?
As far as I know, Visual C++ issues a warning in that case.
Comment #3 by schveiguy — 2013-05-16T11:11:38Z
(In reply to comment #2)
> Should a negative unsigned number even compile?
Debatable, but since it compiles in C, and is frequently used (-1u is 0xffffffff), I think it will continue to compile.
> As far as I know, Visual C++ issues a warning in that case.
But still compiles, right? C is full of questionable, yet valid, behavior.
Comment #4 by sibaqexozequgaba — 2013-05-16T11:25:00Z
Why would you ever do -1u?
We don't talk about implicitly converting -1 to unsigned, right? That's a different case.
Comment #5 by schveiguy — 2013-05-16T11:44:46Z
(In reply to comment #4)
> Why would you ever do -1u?
Shortcut.
Comment #6 by sibaqexozequgaba — 2013-05-16T11:58:25Z
> We don't talk about implicitly converting -1 to unsigned, right? That's a different case.
^ Am I missing something? ^
We're not talking about:
func:
void SetText(char* text, uint len);
call:
SetText(text, -1);
^ here -1 is a special constant meaning e.g. calculate the len of a null terminated string.
We're talking about:
uint len = strlen(text);
// ...
Func(-len); // Why would you ever need this?
Comment #7 by schveiguy — 2013-05-16T12:44:36Z
(In reply to comment #6)
> We're talking about:
> uint len = strlen(text);
> // ...
> Func(-len); // Why would you ever need this?
What about Func(1 - len)
The compiler can't cover every case. If you want to propose something to make this illegal, go ahead, but I doubt you will get traction.
Comment #8 by luka8088 — 2013-05-16T12:49:27Z
(In reply to comment #6)
> > We don't talk about implicitly converting -1 to unsigned, right? That's a different case.
> ^ Am I missing something? ^
>
> We're not talking about:
> func:
> void SetText(char* text, uint len);
> call:
> SetText(text, -1);
> ^ here -1 is a special constant meaning e.g. calculate the len of a null
> terminated string.
>
> We're talking about:
> uint len = strlen(text);
> // ...
> Func(-len); // Why would you ever need this?
The original issue was:
auto offset = text1.length - text2.length;
func(offset);
and offset turned out to be around 4294967291
I was thinking, setting a uint to a negative value is kind of an overflow,
should it maybe be treated the same way like array bounds and be checked by
druntime (with optional disabling in production release)?
Comment #9 by sibaqexozequgaba — 2013-05-16T12:57:40Z
(In reply to comment #8)
> The original issue was:
>
> auto offset = text1.length - text2.length;
> func(offset);
>
> and offset turned out to be around 4294967291
>
> I was thinking, setting a uint to a negative value is kind of an overflow,
> should it maybe be treated the same way like array bounds and be checked by
> druntime (with optional disabling in production release)?
Well, that's probably something the compiler can't warn about. Not statically, that's for sure.
You can use a custom type which checks for bound overflows, and fallback to regular int for release builds.
Comment #10 by luka8088 — 2013-05-16T13:07:39Z
(In reply to comment #9)
> (In reply to comment #8)
> > The original issue was:
> >
> > auto offset = text1.length - text2.length;
> > func(offset);
> >
> > and offset turned out to be around 4294967291
> >
> > I was thinking, setting a uint to a negative value is kind of an overflow,
> > should it maybe be treated the same way like array bounds and be checked by
> > druntime (with optional disabling in production release)?
>
> Well, that's probably something the compiler can't warn about. Not statically,
> that's for sure.
> You can use a custom type which checks for bound overflows, and fallback to
> regular int for release builds.
Yeah, I could, but should that maybe be in druntime?
Also...
void main () {
auto a = 5 - 10u; // 4294967291u
auto b = 5u - 10; // 4294967291u
}
Why are they both unsigned?
I will take this to the forum.
Comment #11 by schveiguy — 2013-05-16T13:43:31Z
(In reply to comment #8)
> The original issue was:
>
> auto offset = text1.length - text2.length;
> func(offset);
>
> and offset turned out to be around 4294967291
>
> I was thinking, setting a uint to a negative value is kind of an overflow,
> should it maybe be treated the same way like array bounds and be checked by
> druntime (with optional disabling in production release)?
No. Just change func's parameter to an int.
Comment #12 by luka8088 — 2013-05-16T13:48:38Z
(In reply to comment #11)
> (In reply to comment #8)
> > The original issue was:
> >
> > auto offset = text1.length - text2.length;
> > func(offset);
> >
> > and offset turned out to be around 4294967291
> >
> > I was thinking, setting a uint to a negative value is kind of an overflow,
> > should it maybe be treated the same way like array bounds and be checked by
> > druntime (with optional disabling in production release)?
>
> No. Just change func's parameter to an int.
http://dpaste.dzfl.pl/611c13d7
Yeah, it is easy to solve when you add a writeln and see that unsigned is causing the issue. =)
Btw: http://forum.dlang.org/thread/[email protected]