Re: Request: a more logical static array behavior

2013-08-15 Thread Maxim Fomin

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:


Static array types are somewhat magical in D; they can do 
something that no other non-subtype type can do: static arrays 
can implicitly convert to another type during type deduction. 
More specifically, e.g. int[3] can implicitly convert to int[] 
during type deduction.


I don't understand why are you surprising that int[3] can be 
implicitly converted to int[] during type deduction. There is 
nothing special about it since it can be converted in other 
contexts too.



Here's an example of this:

module test;

enum Ret { static_array, dynamic_array, input_range }

Ret foo(T)(T[3] sa) // [1]
if (is(T == uint))
{
return Ret.static_array;
}

Ret foo(T)(T[] da) // [2]
{
return Ret.dynamic_array;
}

enum uint[3] saUints = [0, 0, 0];
enum char[3] saChars = [0, 0, 0];
static assert(foo(saUints) == Ret.static_array);  // [3]
static assert(foo(saChars) == Ret.dynamic_array); // [4]

---
[3]: A perfect match is found in the first overload of 'foo' 
[1] when its template type parameter 'T' is deduced to be an 
int. Then, the type of the function parameter 'sa' is exactly 
the same as the type of the argument 'saUints'.


[4]: No perfect match is found. But, because 'saChars' is a 
static array, the compiler gives all 'foo' overloads the 
benefit of the doubt, and also checks if a perfect match could 
be found if 'saChars' were first converted to a dynamic array, 
int[] that is. Then, a perfect match is found for int[] in the 
second overload of 'foo' [2] when 'T' is deduced to be an int.


Compiler is integral entity. There is no providing benefits to 
doubt. What actually happens is checking in 
TypeSArray::deduceType that base type of T[N] is base type of 
T[]. This check gives true since type 'int' is equal to 'int'. 
And resulted match is not a perfect match, but conversion match. 
Also actual conversion happens later in some completely unrelated 
to type deduction compiler part.



Now, let's add to the previous example:

import std.range;

Ret bar(T)(T[3] sa) // [5]
if (is(T == uint))
{
return Ret.static_array;
}

Ret bar(R)(R r) // [6]
if (std.range.isInputRange!R)
{
return Ret.input_range;
}

static assert(bar(saUints) == Ret.static_array); // [7]
static assert(bar(saChars) == Ret.input_range);  // [8]

---
[7]: This is effectively the same as [3]
[8]: This line throws a compile-time error: template test.bar 
does not match any function template declaration. Compare this 
to [4]: for some reason, the compiler doesn't give the second 
overload of 'bar' [6] the benefit of the doubt and check to see 
if the call to 'bar' could be made if 'saChars' were first 
converted to int[]. Were the compiler to consider this implicit 
conversion as it does in [4], then it would see that the second 
overload of 'bar' [6] could in fact be called, and the code 
would compile.


Compiler doesn't give the benefit to doubt as there are no 
hints here about dynamic array. Taking into account general case, 
when A - B and B -C you are asking A -C. And if B and C can 
convert to other types as well, than you could end up with 
exponentially increasing trees of what R may be or in situations 
where int[3] is converted to some ranged struct S { void 
popFront(){ } ... }


In other way, int[3] cannot be directly converted to R if int[3] 
- int[] and int[] - R holds. Also,as Jonathan said, there is 
safety aspect of this issue.



Thus, my point is this:
Shouldn't this magical property of static arrays (implicitly 
converting to dynamic array during type deduction) extend to 
all type deduction situations?


I guess you mean making two steps conversion. I think it is a bad 
idea.





Re: Request: a more logical static array behavior

2013-08-15 Thread monarch_dodra
On Thursday, 15 August 2013 at 02:30:54 UTC, Jonathan M Davis 
wrote:

On Thursday, August 15, 2013 02:57:25 Tommi wrote:

Thus, my point is this:
Shouldn't this magical property of static arrays (implicitly
converting to dynamic array during type deduction) extend to 
all

type deduction situations?


No. If anything, we should get rid of the implicit conversion 
from a static
array to a dynamic one. It's actually unsafe to do so. It's 
just like if you
implicitly converted a local variable to the address of that 
local variable
when you passed it to a function that accepted a pointer. IMHO, 
it never
should have been allowed in the first place. At least with 
taking the address
of a local variable, the compiler treats it as @system. The 
compiler doesn't

currently do that with taking the slice of a static array.

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

If you want a dynamic array from a static one, then slice it. 
That works just
fine with templated functions, and makes what you want 
explicit. Also, making
it so that IFTI instantiated templates with the dynamic array 
type when given
a static array would make it so that you would have to 
explicitly instantiate
any templates where you actually wanted to pass a static array, 
which is a

definite negative IMHO.

At this point, I don't really expect that it'll be changed so 
that static
arrays do not implicitly convert to dynamic ones (much as it 
would be ideal to
make that change), but I really don't think that we should do 
anything to make

the problem worse by adding yet more such implicit conversions.

- Jonathan M Davis


+1


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi
On Thursday, 15 August 2013 at 02:30:54 UTC, Jonathan M Davis 
wrote:

On Thursday, August 15, 2013 02:57:25 Tommi wrote:

Thus, my point is this:
Shouldn't this magical property of static arrays (implicitly
converting to dynamic array during type deduction) extend to 
all

type deduction situations?


No. If anything, we should get rid of the implicit conversion 
from a static
array to a dynamic one. It's actually unsafe to do so. It's 
just like if you
implicitly converted a local variable to the address of that 
local variable
when you passed it to a function that accepted a pointer. IMHO, 
it never
should have been allowed in the first place. At least with 
taking the address
of a local variable, the compiler treats it as @system. The 
compiler doesn't

currently do that with taking the slice of a static array.

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

If you want a dynamic array from a static one, then slice it. 
That works just
fine with templated functions, and makes what you want 
explicit. Also, making
it so that IFTI instantiated templates with the dynamic array 
type when given
a static array would make it so that you would have to 
explicitly instantiate
any templates where you actually wanted to pass a static array, 
which is a

definite negative IMHO.

At this point, I don't really expect that it'll be changed so 
that static
arrays do not implicitly convert to dynamic ones (much as it 
would be ideal to
make that change), but I really don't think that we should do 
anything to make

the problem worse by adding yet more such implicit conversions.

- Jonathan M Davis


Now I feel like these three different notions are getting 
somewhat conflated:

1) memory safety
2) implicit conversion
3) implicit conversion during type deduction

Memory safety
-
If the following code is treated as @system code (which it is):

void getLocal(int* p) { }

void main()
{
int n;
getLocal(n);
}

...then the following code should be treated as @system code as 
well (which it currently isn't):


void getLocal(int[] da) { }

void main()
{
int[5] sa;
getLocal(sa[]); // Notice the _explicit_ conversion
}

...There's no two ways about it. But implicit conversion has 
nothing to do with this. If you want to disallow implicit 
conversion because it's a bug prone programming construct, then 
you have a valid reason to do so (and it would be fine by me). 
But if you want to disallow implicit conversion from static array 
to a slice because it's not _always_ memory safe, then you're 
doing it for the wrong reason: e.g. the following code is memory 
safe even though we're using the implicit conversion:


void getGlobal(int[] da) { }
int[5] gsa;

void main()
{
getGlobal(gsa); // implicit conversion
}

Like I said: implicit conversion doesn't really have anything to 
do with the potential memory safety issues.


Implicit conversion VS Implicit conversion during type deduction

I don't think that you failed to see the distinction between 
these two things, but because someone might, I'll talk about this 
a bit more.


This is regular implicit conversion (nothing weird or magical 
about it):


void foo(int[] da) { }
int[3] sa;
foo(sa); // implicit conversion

This is implicit conversion during type deduction (totally weird 
and magical):


void foo(T)(T[] da) { }
int[3] sa;
foo(sa); // implicit conversion during type deduction

That above example about implicit conversion during type 
deduction is like writing the following C++ code and having it 
actually compile:


template typename T
struct DynamicArray { };

template typename T
struct StaticArray {
operator DynamicArrayT() const
{
return DynamicArrayT{};
}
};

template typename T
void foo(DynamicArrayT da) { }

void bar(DynamicArrayint da) { }

int main(int argc, char *argv[])
{
StaticArrayint sa;
foo((DynamicArrayint)sa); // OK: explicit conversion
bar(sa); // OK: regular implicit conversion
foo(sa); // Error: No matching function call to 'foo'
return 0;
}

It is this implicit conversion during type deduction that makes 
D's static arrays' behavior illogical and inconsistent (because 
it doesn't happen in all type deduction contexts). Whereas 
regular implicit conversion may be a dangerous or an unsafe 
programming tool, there's nothing illogical about it.


I don't want to increase the number of implicit conversions. All 
I'm trying to do is make D's static arrays behave more logically. 
And there are two ways to do this:
1) make static arrays free to implicitly convert to dynamic array 
in all type deduction situations
2) disallow static arrays from implicitly converting during type 
deduction


Notice that in order to make static arrays' behavior logical, 
there's no need to disallow them from implicitly converting to 
dynamic arrays in the general sense (just during type deduction).


Re: Request: a more logical static array behavior

2013-08-15 Thread Dicebot
On Thursday, 15 August 2013 at 02:30:54 UTC, Jonathan M Davis 
wrote:
No. If anything, we should get rid of the implicit conversion 
from a static
array to a dynamic one. It's actually unsafe to do so. It's 
just like if you
implicitly converted a local variable to the address of that 
local variable

when you passed it to a function that accepted a pointer.


scope, scope, scope!

;)


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi

On Thursday, 15 August 2013 at 07:16:01 UTC, Maxim Fomin wrote:

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:


Static array types are somewhat magical in D; they can do 
something that no other non-subtype type can do: static arrays 
can implicitly convert to another type during type deduction. 
More specifically, e.g. int[3] can implicitly convert to int[] 
during type deduction.


I don't understand why are you surprising that int[3] can be 
implicitly converted to int[] during type deduction. There is 
nothing special about it since it can be converted in other 
contexts too.


I don't expect int[3] to implicitly convert to int[] during type 
deduction for the same reason that I don't expect int to 
implicitly convert to long during type deduction (even though I 
know that int implicitly converts to long in all kinds of other 
contexts):


void getLong(T)(T arg)
if (is(T == long))
{
}

void main()
{
int n;
getLong(n); // int doesn't implicitly convert to long
}

On Thursday, 15 August 2013 at 07:16:01 UTC, Maxim Fomin wrote:

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:

[..]
Here's an example of this:

module test;

enum Ret { static_array, dynamic_array, input_range }

Ret foo(T)(T[3] sa) // [1]
if (is(T == uint))
{
   return Ret.static_array;
}

Ret foo(T)(T[] da) // [2]
{
   return Ret.dynamic_array;
}

enum uint[3] saUints = [0, 0, 0];
enum char[3] saChars = [0, 0, 0];
static assert(foo(saUints) == Ret.static_array);  // [3]
static assert(foo(saChars) == Ret.dynamic_array); // [4]

---
[3]: A perfect match is found in the first overload of 'foo' 
[1] when its template type parameter 'T' is deduced to be an 
int. Then, the type of the function parameter 'sa' is exactly 
the same as the type of the argument 'saUints'.


[4]: No perfect match is found. But, because 'saChars' is a 
static array, the compiler gives all 'foo' overloads the 
benefit of the doubt, and also checks if a perfect match could 
be found if 'saChars' were first converted to a dynamic array, 
int[] that is. Then, a perfect match is found for int[] in the 
second overload of 'foo' [2] when 'T' is deduced to be an int.


Compiler is integral entity. There is no providing benefits to 
doubt. What actually happens is checking in 
TypeSArray::deduceType that base type of T[N] is base type of 
T[]. This check gives true since type 'int' is equal to 'int'. 
And resulted match is not a perfect match, but conversion match.


Agreed.

Also actual conversion happens later in some completely 
unrelated to type deduction compiler part.


I know implicit conversion happens at a later stage (not during 
type deduction). But I don't have any other words to describe it 
other than saying implicit conversion during type deduction. If 
you can provide me some more exact language, please do.


On Thursday, 15 August 2013 at 07:16:01 UTC, Maxim Fomin wrote:

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:

[..]
Now, let's add to the previous example:

import std.range;

Ret bar(T)(T[3] sa) // [5]
if (is(T == uint))
{
   return Ret.static_array;
}

Ret bar(R)(R r) // [6]
if (std.range.isInputRange!R)
{
   return Ret.input_range;
}

static assert(bar(saUints) == Ret.static_array); // [7]
static assert(bar(saChars) == Ret.input_range);  // [8]

---
[7]: This is effectively the same as [3]
[8]: This line throws a compile-time error: template test.bar 
does not match any function template declaration. Compare 
this to [4]: for some reason, the compiler doesn't give the 
second overload of 'bar' [6] the benefit of the doubt and 
check to see if the call to 'bar' could be made if 'saChars' 
were first converted to int[]. Were the compiler to consider 
this implicit conversion as it does in [4], then it would see 
that the second overload of 'bar' [6] could in fact be called, 
and the code would compile.


Compiler doesn't give the benefit to doubt as there are no 
hints here about dynamic array.


Why would the compiler need a hint? The compiler knows that the 
static array can implicitly convert to dynamic array, so it 
should be able to check if the function could be called with the 
argument first implicitly converted to a dynamic array.


Taking into account general case, when A - B and B -C you are 
asking A -C. And if B and C can convert to other types as 
well, than you could end up with exponentially increasing trees 
of what R may be or in situations where int[3] is converted to 
some ranged struct S { void popFront(){ } ... }
In other way, int[3] cannot be directly converted to R if 
int[3] - int[] and int[] - R holds. Also,as Jonathan said, 
there is safety aspect of this issue.


No, I'm not asking A - C, I'm just asking that int[3] convert to 
int[]. I don't understand where you get this exponential 
increase. Since they are both built-in types, there can't be any 
increase: int[3] can never implicitly convert to some 
user-defined struct S, and int[] can never implicitly convert to 

Re: Request: a more logical static array behavior

2013-08-15 Thread Maxim Fomin

On Thursday, 15 August 2013 at 12:12:59 UTC, Tommi wrote:


Implicit conversion VS Implicit conversion during type deduction

I don't think that you failed to see the distinction between 
these two things, but because someone might, I'll talk about 
this a bit more.


This is regular implicit conversion (nothing weird or magical 
about it):


void foo(int[] da) { }
int[3] sa;
foo(sa); // implicit conversion

This is implicit conversion during type deduction (totally 
weird and magical):


void foo(T)(T[] da) { }
int[3] sa;
foo(sa); // implicit conversion during type deduction



Please stop spreading this misconveption. There is *no*
conversion during type deduction. There is *a check* whether base
type of static array is same as base type of dynamic array which
happens to be true in this case. *Conversion* happens in
completely related compiler part.

And there is no special about it during template type deduction.
This (meaning that base type of int[N] array is same as base type
of int[] array) happens or could happen in any stage of compiling
proccess. How C++ does it is irrelevant to what D does.


Re: Request: a more logical static array behavior

2013-08-15 Thread Artur Skawina
On 08/15/13 14:44, Tommi wrote:
[...]
 No, I'm not asking A - C, I'm just asking that int[3] convert to int[].

From you earlier post:

  Ret bar(R)(R r) // [6]
  if (std.range.isInputRange!R)
  {
  return Ret.input_range;
  }

You'd like to be able to call 'bar' with a static array. Currently
you can't, because 'R' becomes a /static array/, hence not a input range.

Note that

  Ret baz(R)(R[] r) // [6]
  if (std.range.isInputRange!(R[]))
  {
  return Ret.input_range;
  }

/would/ work. This case works, because 'baz' expects a dynamic array
and static arrays implicitly convert to dynamic ones - so if there is
no better fitting overload then the static-dynamic conversion will be
done.

To make your case work, it would be necessary to first deduce R==int[3],
then try instantiating the template, and if this fails retry with whatever
int[3] implicitly converts to (int[] in this case).
The only alternative is making the static-dynamic array conversion
/mandatory/ when deducing types - which is not a good idea either.

The implicit int[3] - int[] conversion should not exist.

artur


Re: Request: a more logical static array behavior

2013-08-15 Thread Maxim Fomin

On Thursday, 15 August 2013 at 12:44:09 UTC, Tommi wrote:


I don't expect int[3] to implicitly convert to int[] during 
type deduction for the same reason that I don't expect int to 
implicitly convert to long during type deduction (even though I 
know that int implicitly converts to long in all kinds of other 
contexts):


void getLong(T)(T arg)
if (is(T == long))
{
}

void main()
{
int n;
getLong(n); // int doesn't implicitly convert to long
}



OK,

void getLong(T)(T arg)
if (is(T : long))
{

}

void main()
{
int n;
getLong(n); // int is implicitly convertible to long
}

now you have implicit conversion from int to long during type 
deduction.


Also actual conversion happens later in some completely 
unrelated to type deduction compiler part.


I know implicit conversion happens at a later stage (not during 
type deduction). But I don't have any other words to describe 
it other than saying implicit conversion during type 
deduction. If you can provide me some more exact language, 
please do.


There is a test whether base types are equal (which happens in 
many stages, including type deduction) and conversion which 
happens in later stage.


Compiler doesn't give the benefit to doubt as there are no 
hints here about dynamic array.


Why would the compiler need a hint? The compiler knows that the 
static array can implicitly convert to dynamic array, so it 
should be able to check if the function could be called with 
the argument first implicitly converted to a dynamic array.




Because I was speaking about general case. In this case yes, dmd 
can know beforehand that T[N] can be converted to T[]. In general 
case which can involve alias this (including multiple alias this) 
the problem can be more complex.


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi

On Thursday, 15 August 2013 at 13:25:58 UTC, Maxim Fomin wrote:

On Thursday, 15 August 2013 at 12:12:59 UTC, Tommi wrote:


Implicit conversion VS Implicit conversion during type 
deduction


I don't think that you failed to see the distinction between 
these two things, but because someone might, I'll talk about 
this a bit more.


This is regular implicit conversion (nothing weird or magical 
about it):


void foo(int[] da) { }
int[3] sa;
foo(sa); // implicit conversion

This is implicit conversion during type deduction (totally 
weird and magical):


void foo(T)(T[] da) { }
int[3] sa;
foo(sa); // implicit conversion during type deduction



Please stop spreading this misconveption. There is *no*
conversion during type deduction. There is *a check* whether 
base

type of static array is same as base type of dynamic array which
happens to be true in this case. *Conversion* happens in
completely related compiler part.


I've been saying implicit conversion during type deduction, but 
I seriously doubt that anyone who knows what type deduction is, 
would think that actual implicit conversion somehow happens 
during that.


(Type deduction is simply figuring out what the actual type of a 
templated type is given a certain context).


But, from now on, I'll use the phrase checking for implicit 
conversions during type deduction instead of implicit 
conversion during type deduction.


On Thursday, 15 August 2013 at 13:25:58 UTC, Maxim Fomin wrote:

And there is no special about it during template type deduction.
This (meaning that base type of int[N] array is same as base 
type
of int[] array) happens or could happen in any stage of 
compiling

proccess. How C++ does it is irrelevant to what D does.


I agree that what C++ does is irrelevant to what D does (I never 
said it was). I used an example of C++ code to make a point which 
_is_ relevant to D. Since you seemed to miss the point, I'm going 
to translate that previous C++ example code D code now to get my 
point across:


struct DynamicArray(T) { }

struct StaticArray(T, size_t n)
{
DynamicArray!T opImplicitCast() const
{
return DynamicArray!T();
}
}

void foo(T)(DynamicArray!T da) { }

void bar(DynamicArray!int da) { }

void main()
{
StaticArray!(int, 5) sa;
bar(sa); // OK: implicit conversion
foo(cast(DynamicArray!int) sa); // OK: explicit conversion
foo(sa); // Error: No matching function call to 'foo'
}

Don't try to compile that, it won't work because I used the 
opImplicitCast operator which is a future feature of D (it 
provides an implicit conversion for used defined types). How do I 
know it's a future feature of D? Don't ask... okay, you got me... 
I'm a time traveller.


Now, to fulfill my promise of being excruciatingly explicit: What 
said before about being a time traveller, it was a joke. My point 
is that D could have an implicit cast operator in the future. And 
if it did have it, then it would become obvious to everybody why 
it is that a static array, such as:


int[5]

...is magical, that is, it is fundamentally different from:

StaticArray!(int, 5)

...in that whereas the above code example would _not_ compile, 
this next example would (and it does) compile:


void foo(T)(T[] da) { }

void bar(int[] da) { }

void main()
{
int[5] sa;
bar(sa); // OK: implicit conversion
foo(cast(int[]) sa); // OK: explicit conversion
foo(sa); // OK !!! (compare to the previous example)
}


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi

On Thursday, 15 August 2013 at 13:50:45 UTC, Maxim Fomin wrote:

On Thursday, 15 August 2013 at 12:44:09 UTC, Tommi wrote:


I don't expect int[3] to implicitly convert to int[] during 
type deduction for the same reason that I don't expect int to 
implicitly convert to long during type deduction (even though 
I know that int implicitly converts to long in all kinds of 
other contexts):


void getLong(T)(T arg)
if (is(T == long))
{
}

void main()
{
   int n;
   getLong(n); // int doesn't implicitly convert to long
}



OK,

void getLong(T)(T arg)
if (is(T : long))
{

}

void main()
{
int n;
getLong(n); // int is implicitly convertible to long
}

now you have implicit conversion from int to long during type 
deduction.


No it's not:

void getLong(T)(T arg)
if (is(T : long))
{
static assert(is(typeof(arg) == int));
}

void main()
{
int n;
getLong(n); // int is _not_ implicitly converted to long
}


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi

On Thursday, 15 August 2013 at 13:53:17 UTC, Artur Skawina wrote:

On 08/15/13 14:44, Tommi wrote:
[...]
No, I'm not asking A - C, I'm just asking that int[3] convert 
to int[].



From you earlier post:


  Ret bar(R)(R r) // [6]
  if (std.range.isInputRange!R)
  {
  return Ret.input_range;
  }

You'd like to be able to call 'bar' with a static array. 
Currently
you can't, because 'R' becomes a /static array/, hence not a 
input range.


Note that

  Ret baz(R)(R[] r) // [6]
  if (std.range.isInputRange!(R[]))
  {
  return Ret.input_range;
  }

[..]


To be exact, I want either of the following options (but not both 
of them):


1) I want to be able to call 'bar' with a static array

OR

2) I want to _not_ be able to call 'baz' with a static array

Either one of those options is fine by me. All I want is make D's 
static arrays behave logically (and either one of those options 
would do it).


Re: Request: a more logical static array behavior

2013-08-15 Thread Maxim Fomin

On Thursday, 15 August 2013 at 14:32:29 UTC, Tommi wrote:


No it's not:

void getLong(T)(T arg)
if (is(T : long))
{
static assert(is(typeof(arg) == int));
}

void main()
{
int n;
getLong(n); // int is _not_ implicitly converted to long
}


Yes, because during type deduction there was constraint test that 
checked whether int is convertible to long which is the same 
story as in static-dynamic array case.


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi

On Thursday, 15 August 2013 at 14:53:08 UTC, Maxim Fomin wrote:

On Thursday, 15 August 2013 at 14:32:29 UTC, Tommi wrote:


No it's not:

void getLong(T)(T arg)
if (is(T : long))
{
   static assert(is(typeof(arg) == int));
}

void main()
{
   int n;
   getLong(n); // int is _not_ implicitly converted to long
}


Yes, because during type deduction there was constraint test 
that checked whether int is convertible to long which is the 
same story as in static-dynamic array case.


The code snippet above is not the same thing as what happens in 
the static-dynamic array case. In the above code snippet the type 
deduction for 'T' during the instantiation of 'getLong' has 
already finished by the time the template constraint is evaluated 
(how could the template constraint be evaluated if the actual 
type for 'T' hadn't already been deduced?). So, the compiler 
doesn't consider the implicit conversion from int to long 
_during_ type deduction, but after it.


The only time when the compiler is willing to consider the 
possible implicit conversions during type deduction is with 
static arrays: hence... magic.


Re: Request: a more logical static array behavior

2013-08-15 Thread Tommi

On Thursday, 15 August 2013 at 15:07:23 UTC, Tommi wrote:
The only time when the compiler is willing to consider the 
possible implicit conversions during type deduction is with 
static arrays: hence... magic.


Barring this special case which I mentioned in my original post:

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:

NOTE:
Subtypes can implicitly convert to their supertype during type 
deduction, there's nothing magical about that.


Here's an example of that:

class SuperClass(T) { }

class SubClass(T) : SuperClass!T { }

struct Supertype(T) { }

struct Subtype(T)
{
Supertype!T s;
alias s this;
}

void foo(T)(SuperClass!T superc) { }

void bar(T)(Supertype!T supert) { }

void main()
{
SubClass!int subc;
foo(subc); // OK

Subtype!int subt;
bar(subt); // OK
}

Although, it might be a bit misleading to call that implicit 
conversion, because nothing is actually converted: it's just that 
an entity is interpreted as something else, which it also is.


Re: Request: a more logical static array behavior

2013-08-14 Thread Tommi

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:

...


And half the time I say converted to int[] I mean converted to 
uint[] and the other half of the time I mean converted to 
char[]. Sorry about that.


Re: Request: a more logical static array behavior

2013-08-14 Thread Tommi

On Thursday, 15 August 2013 at 01:05:54 UTC, Tommi wrote:

On Thursday, 15 August 2013 at 00:57:26 UTC, Tommi wrote:

...


And half the time I say converted to int[] I mean converted 
to uint[] and the other half of the time I mean converted to 
char[]. Sorry about that.


Actually that's not true either. Whenever I say 'int' after the 
examples start, just think 'char'.


Re: Request: a more logical static array behavior

2013-08-14 Thread Jonathan M Davis
On Thursday, August 15, 2013 02:57:25 Tommi wrote:
 Thus, my point is this:
 Shouldn't this magical property of static arrays (implicitly
 converting to dynamic array during type deduction) extend to all
 type deduction situations?

No. If anything, we should get rid of the implicit conversion from a static 
array to a dynamic one. It's actually unsafe to do so. It's just like if you 
implicitly converted a local variable to the address of that local variable 
when you passed it to a function that accepted a pointer. IMHO, it never 
should have been allowed in the first place. At least with taking the address 
of a local variable, the compiler treats it as @system. The compiler doesn't 
currently do that with taking the slice of a static array.

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

If you want a dynamic array from a static one, then slice it. That works just 
fine with templated functions, and makes what you want explicit. Also, making 
it so that IFTI instantiated templates with the dynamic array type when given 
a static array would make it so that you would have to explicitly instantiate 
any templates where you actually wanted to pass a static array, which is a 
definite negative IMHO.

At this point, I don't really expect that it'll be changed so that static 
arrays do not implicitly convert to dynamic ones (much as it would be ideal to 
make that change), but I really don't think that we should do anything to make 
the problem worse by adding yet more such implicit conversions.

- Jonathan M Davis