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