pointers, functions, and uniform call syntax

Artur Skawina art.08.09 at gmail.com
Thu Sep 6 03:29:29 PDT 2012


On 09/06/12 00:50, Era Scarecrow wrote:
> On Wednesday, 5 September 2012 at 11:01:50 UTC, Artur Skawina wrote:
>> On 09/04/12 20:19, Era Scarecrow wrote:
>>>  I ask you, how do you check if it's a null pointer? &s?
>>
>> Yes, obviously. If you need to do that manually.
> 
>  But you shouldn't have to.
> 
>>>   int getx(ref S s)
>>>   //How does this make sense?? it looks wrong and is misleading
>>>   in {assert(&s); }
>>>   body {return s.x); }
>>
>> It looks correct and is perfectly obvious. But see below - you don't need to do this manually - the compiler does it for you when calling methods and could handle the UFCS case too.
> 
>  How I'm understanding references in D (And perhaps I'm repeating myself in two different topics) is they point to live variables (IE guaranteed pointers), and remains this way until you return from that function. 

The struct example I gave previously (quoted below) shows how easily you can end
up with a null reference in D; refs are *not* guaranteed to be live. It's not
just about pointers:

   class C { int i; auto f() { return i; } }
   int main() {
      C c;
      return c.f();
   }

Here you won't even get an assert error, just a segfault. But the pointer-to-class
(reference type in general, but so far there are only classes) model chosen in D is
wrong; this probably contributes to the confusion about refs, because they behave
differently for classes. Let's ignore classes for now, they're "special".

>  This is entirely valid and simplifies things. Remember in D we want the language to 'do the right thing', but if you make references where it works to 'sometimes works' then it becomes a problem (pointers 'sometimes' work and are not @safe, while ref is @safe). Checking the address of a reference shouldn't be needed, since it should be dereferenced at where it was called at if need be (throwing it there).

Pointers *are* @safe, it's just certain operations on them that are not.

>  Would you REALLY want to mark every single function that uses ref as @trusted? 

No idea why you think that would be needed.

>>>  More importantly, if it's now a possibility do we have to start adding checks everywhere?
>>>
>>>   int getx(S *s)
>>>   in {assert(s); } //perfectly acceptable check, we know it's a pointer
>>>   body {return s.x); }
> 
>>    struct S { int i; auto f() { return i; } }
>>    int main() {
>>       S* s;
>>       return s.f();
>>    }
>>
>> This program will assert at runtime (and (correctly) segfault in a release-build). The compiler inserts not-null-this checks for "normal" methods in non-release mode, and could also do that before invoking any UFCS "method". So you wouldn't need to check for '!!&this' yourself.
> 
>  I thought those checks weren't added (via the compiler) since if it causes a seg fault the CPU would catch it and kill the program on it's own (just add debugging flags); If you added the checks they would do the same thing (More buck for the same bang).

The checks happen for structs, and should be configurable, but right now
are not, which sometimes causes trouble.


On 09/06/12 08:18, Era Scarecrow wrote:
> On Wednesday, 5 September 2012 at 11:01:50 UTC, Artur Skawina wrote:
>> On 09/04/12 20:19, Era Scarecrow wrote:
>>>  I ask you, how do you check if it's a null pointer? &s?
>>
>> Yes, obviously. If you need to do that manually.
>>
>>>   int getx(ref S s)
>>>   //How does this make sense?? it looks wrong and is misleading
>>>   in {assert(&s); }
>>>   body {return s.x); }
>>
>> It looks correct and is perfectly obvious. But see below - you don't need to do this manually - the compiler does it for you when calling methods and could handle the UFCS case too.
> 
>  I've been thinking about this; It would definitely be the wrong thing to do. The assert would _Always_ succeed. The address you get would be of the pointer/reference for the stack (the pointer 

No, that's not how ref args work. '&s' will give you the address of the
object (eg struct). A reference type like 'class' has another (internal)
level of indirection so in that case you would get a pointer to the
class-reference. But that's how classes work internally, the 'object' in
that case is just the  internal pointer to the "real" class data. Taking
the address of an argument gives you a pointer to it in every case.

artur


More information about the Digitalmars-d mailing list