Re: Iterating over 0..T.max

2011-03-10 Thread Magnus Lie Hetland

On 2011-03-09 21:24:57 +0100, Kai Meyer said:

I don't see how that works in dmd2, and I don't have much experience 
with dmd1, so I'll admit that this may be different on dmd1.


Derp. I didn't mean bool -- I was talking about byte. (Which should 
make quite a bit more sense, given that I'm talking about a limit of 
256... :D)


And, for the record, I'm using DMD 2.052 (OS X).

Just replace bool with byte in your program, and it should compile. 
Sorry for the brain fart ;)


--
Magnus Lie Hetland
http://hetland.org



Re: Iterating over 0..T.max

2011-03-10 Thread bearophile
Magnus Lie Hetland:

 Derp. I didn't mean bool -- I was talking about byte. (Which should 
 make quite a bit more sense, given that I'm talking about a limit of 
 256... :D)

Please show a complete minimal program that gives you problem. (I have failed 
to reproduce your problem on Windows).

Bye,
bearophile


Re: Iterating over 0..T.max

2011-03-10 Thread Steven Schveighoffer
On Thu, 10 Mar 2011 07:50:21 -0500, bearophile bearophileh...@lycos.com  
wrote:



Magnus Lie Hetland:


Derp. I didn't mean bool -- I was talking about byte. (Which should
make quite a bit more sense, given that I'm talking about a limit of
256... :D)


Please show a complete minimal program that gives you problem. (I have  
failed to reproduce your problem on Windows).



void main()
{
auto a = new ubyte[256];
foreach(ubyte i, ref e; a) e = i;
}

I think you should file this as a bug Magnus, I see no reason why this  
should result in an infinite loop.


Probably the reason is because the compiler rewrites this as:

for(ubyte i = 0; i  a.length; i++)

where what it should do is:

for(size_t _i = 0; _i  a.length; _i++)
{
auto i = cast(ubyte) _i;
...
}

or just fail to compile if you use anything that can't hold a size_t as an  
index type.


-Steve


Re: Iterating over 0..T.max

2011-03-10 Thread bearophile
Steven Schveighoffer:

 void main()
 {
  auto a = new ubyte[256];
  foreach(ubyte i, ref e; a) e = i;
 }

http://d.puremagic.com/issues/show_bug.cgi?id=5725

Bye,
bearophile


Iterating over 0..T.max

2011-03-09 Thread Magnus Lie Hetland

In a (template) data structure I'm working on, I had the following thinko:

   auto a = new T[n];
   foreach (T i, ref e; a) {
   e = i;
   }

Then I instantiated it with T=bool, and n=256. Infinite loop, of course 
-- the problem being that i wraps around to 0 after the last iteration. 
Easily fixed, and not that much of a problem (given that I caught it) 
-- I'll just use e = cast(T) i. (Of course, even with that solution, 
I'd get wrap problems if n=257, but I just want to make sure I allow 
T.max as a size.)


But I'm wondering: given D's excellent valua range propagations and 
overflow checking, would it be possible to catch this special case 
(i.e., detect when the array can be too long for the index type)? Or 
are any other safeguards possible to prevent this sort of thing?


--
Magnus Lie Hetland
http://hetland.org



Re: Iterating over 0..T.max

2011-03-09 Thread Kai Meyer

On 03/09/2011 09:09 AM, Magnus Lie Hetland wrote:

In a (template) data structure I'm working on, I had the following thinko:

auto a = new T[n];
foreach (T i, ref e; a) {
e = i;
}

Then I instantiated it with T=bool, and n=256. Infinite loop, of course
-- the problem being that i wraps around to 0 after the last iteration.
Easily fixed, and not that much of a problem (given that I caught it) --
I'll just use e = cast(T) i. (Of course, even with that solution, I'd
get wrap problems if n=257, but I just want to make sure I allow T.max
as a size.)

But I'm wondering: given D's excellent valua range propagations and
overflow checking, would it be possible to catch this special case
(i.e., detect when the array can be too long for the index type)? Or are
any other safeguards possible to prevent this sort of thing?



I don't see how that works in dmd2, and I don't have much experience 
with dmd1, so I'll admit that this may be different on dmd1. I get 
compilation errors with your code:


import std.stdio;

void main()
{
make_new!(bool)(256);
}

void make_new(T)(size_t n)
{
auto a = new T[n];
foreach (T i, ref e; a) {
e = i;
}
}

This gives me:
tmax.d(12): Error: operation not allowed on bool 'i'
tmax.d(5): Error: template instance tmax.make_new!(bool) error instantiating

As far as I understand, a foreach over an array makes the first value 
(i) a uint for the index, and the second value (e) a copy of the value 
in the array (in our case a bool).


import std.stdio;

void main()
{
make_new!(bool)(1);
}

void make_new(T)(size_t n)
{
auto a = new T[n];
writef(%s\n, typeof(a).stringof);
foreach (i,e; a) {
writef(%s\n, typeof(i).stringof);
writef(%s\n, typeof(e).stringof);
}
}

/*
Output:
bool[]
uint
bool
*/



But to the question about boundaries, 'i' is a uint (size_t), and on a 
4GB machine, I can't call auto a = new bool[size_t.max];. The program 
segfaults. size_t.max / 2 for a size gives me Memory allocation 
failed. size_t.max / 4 works fine.


I'm not sure how to get a program to do what you describe.