Implicit cast to immutable

Daniel Murphy yebblies at nospamgmail.com
Wed Oct 19 18:39:47 PDT 2011


"Steven Schveighoffer" <schveiguy at yahoo.com> wrote in message 
news:op.v3lug2q2eav7ka at localhost.localdomain...
> On Tue, 18 Oct 2011 02:40:12 -0400, Daniel Murphy
> <yebblies at nospamgmail.com> wrote:
>
>> "Steven Schveighoffer" <schveiguy at yahoo.com> wrote in message
>> news:op.v3h06olweav7ka at localhost.localdomain...
>>>
>>> That sounds like an incorrect restriction.  The implicit cast to 
>>> immutable
>>> should depend on whether the function being *called* qualifies, not if 
>>> the
>>> function you are calling *from* qualifies.
>>>
>>
>> I think you've misunderstood what I'm saying.  The patch I made 
>> implemented
>> two ways to implicly convert to immutable: the result of a pure function
>> returning immutable and a return statement inside a pure function.
>>
>> 1)
>> int[] fun() { return new int[]; }
>> immutable x = fun(); // conversion happens here
>>
>> 2)
>> immutable(int[]) fun() { return new int[]; } // conversion happens here
>> immutable x  = fun();
>
> Neither of those is relevant, since they do not contain parameters (I'm 
> assuming you meant them both to be pure).
>

Yeah, they were supposed to be pure.  I was just demonstrating that 
conversion happens at the return statement, or the call site, but only 
currently for strongly pure functions.

>>> Qualifying means the return type should be mutable, and cannot be 
>>> derived
>>> from the parameters without requiring casts.  The easiest way to do this
>>> is to ensure the parameters are all const, immutable, or implicitly cast
>>> to immutable.  You could do funky things like assume for instance an 
>>> int[]
>>> cannot possibly be implicit-casted to a char[], so therefore int[]
>>> foo(char[] data) pure can be implicitly casted to immutable, but that
>>> might be flirting with dangerous situations.
>>>
>>> The one exception should be allocating memory, which should always
>>> qualify, even though it's not a pure function.
>>>
>>
>> This is valid, but becomes very complicated with complex return types.  I
>> doubt this will ever make it into the language.
>
> No, it's not complicated, at least in my view.  The rules are:
>
> 1. if the pure function parameters are only immutable or
> implicitly-convertible-to-immutable, the result is safe to cast to
> immutable, regardless of what happens inside the function, or the type of
> the result.
> 2. if the pure function parameters contain any mutable data that is
> mutable and *not* implicitly convertible to mutable, and the result is
> only safe to cast to immutable if it can already implicitly cast to
> immutable.
> 3. if the pure function parameters are implicitly castible to immutable,
> immutable, or are const, then:
>       a) if the return type is implicitly castable to immutable, obviously
> it can be cast.
>       b) if the return type is not implicitly castable to immutable, but
> contains only mutable references, then it's implicitly castable to
> immutable.
>       c) otherwise, it cannot be implicitly cast.
>
> You do not need the function body to determine this, and the decision
> should be made by the compiler at the call site.
>
> Your case 2 where the conversion happens at the return statement is
> already covered.
>
>> I've got the beginnings of a patch to enable a sort of 'pure expression',
>> such as new, array.dup and array concatenation expressions.  The result 
>> of a
>> call to a const-pure function using immutable arguments can be converted 
>> to
>> immutable, while calling it with mutable or const arguments cannot, 
>> without
>> searching the return type for anything the arguments can implicitly 
>> convert
>> to (or create).
>>
>> Eg. I can't see a great way to detect situations like this:
>>
>> struct S { const void* p; }
>
> This struct could only be cast to immutable under my rule 1 above.  It
> does not implicitly cast to immutable.
>
>> S[] fun(int[] arr)
>> {
>>     return [ S(arr.ptr) ];
>> }
>> immutable x = fun([1, 2, 3]);
>
> Invalid.  arr is not implicitly castable to immutable and is mutable, so
> the result must already be implicitly castable (which it is not).  This
> falls under rule 2 above, and fails the test.
>
> -Steve

Ok, I think I meant to make fun pure and fun's parameter 'in', so it would 
fall under rule 3 but be rejected by 3b as it contains a const member.

It's not always simple to determine if an aggregate contains non-mutable 
members.  An example would be a class when you only have a base class 
reference.
Another problem (which we're already seeing with the existing conversions) 
is that when you screw it up the conversion fails, but doesn't give you any 
hint as to why it failed.  Making the rules more complicated is just going 
to make this worse. 




More information about the Digitalmars-d-learn mailing list