Re: Automatic invariant generation

2017-07-10 Thread Jonathan M Davis via Digitalmars-d
On Monday, July 10, 2017 11:26:43 AM MDT Walter Bright via Digitalmars-d 
wrote:
> On 7/9/2017 6:37 PM, Jonathan M Davis via Digitalmars-d wrote:
> > For some assertions, having more than a file and line number is nice
> > (e.g. if you have messages for your pre-condition assertions, then you
> > can make it so that when it fails, the programmer doesn't even need to
> > look at the source code),
>
> He always needs to look at the source code. Asserts are for BUGS, and to
> fix bugs, you gotta look at the code. If asserts are being used as a
> substitute for input/environment errors, they're misused.
>
> In 40 years of asserts, I can't think of ever not visiting the file/line
> where it failed as the first thing I did to debug it.

Yes, assertions are used for catching bugs, but when they're used for DbC,
the bug is in the caller, and if it's clear from the message that the caller
violated a pre-condition as well as what that pre-condition was, then there
really is no need for the programmer to look at the source code of the
function being called. They just need to look at their code that's calling
it and figure out how they screwed up and passed a bad value. Essentially,
with pre-conditions, it's really the caller's code that's being tested, not
the code where the assertion itself is.

Assertions which test the code that they're actually in, on the other hand,
pretty much always require that you look at that code to figure out what's
going on.

- Jonathan M Davis



Re: Automatic invariant generation

2017-07-10 Thread Walter Bright via Digitalmars-d

On 7/9/2017 4:37 AM, Steven Schveighoffer wrote:

On 7/9/17 7:00 AM, Walter Bright wrote:

On 7/9/2017 3:37 AM, Steven Schveighoffer wrote:


Yet, here is an example of where we have effectively added a null pointer 
exception. > At the very least, this should be eliminated on Linux

and just use the signal handling null pointer error mechanism!


You're a few years late, as pretty much nobody agreed with me that the 
operating system handling of it was plenty.


I think you misunderstand, we have etc.linux.memoryerror that can actually throw 
an error on a null pointer using the signal handler.


Windows creates a exception, too, on null seg faults.


I have a suggestion: eliminate this feature, and add a -npe switch to the 
compiler that errors on any null pointer usage. Asserts will be sprinkled in 
everywhere, but may be useful to someone debugging a nasty null pointer segfault 
somewhere.


It's just redundant to add these.



Re: Automatic invariant generation

2017-07-10 Thread Walter Bright via Digitalmars-d

On 7/9/2017 6:37 PM, Jonathan M Davis via Digitalmars-d wrote:

For some assertions, having more than a file and line number is nice (e.g.
if you have messages for your pre-condition assertions, then you can make it
so that when it fails, the programmer doesn't even need to look at the
source code),


He always needs to look at the source code. Asserts are for BUGS, and to fix 
bugs, you gotta look at the code. If asserts are being used as a substitute for 
input/environment errors, they're misused.


In 40 years of asserts, I can't think of ever not visiting the file/line where 
it failed as the first thing I did to debug it.


Re: Automatic invariant generation

2017-07-10 Thread Nicholas Wilson via Digitalmars-d

https://github.com/dlang/dmd/pull/6982


Re: Automatic invariant generation

2017-07-09 Thread Jonathan M Davis via Digitalmars-d
On Sunday, July 9, 2017 4:00:33 AM MDT Walter Bright via Digitalmars-d 
wrote:
> On 7/9/2017 3:37 AM, Steven Schveighoffer wrote:
> > Wait, you have stated many many times, a segfault is good enough, it's
> > not worth the added cost to do null pointer exceptions (a position I'm
> > completely in agreement with).
>
> That's right.
>
> > Yet, here is an example of where we have effectively added a
> > null pointer exception. > At the very least, this should be eliminated
> > on Linux and just use the signal handling null pointer error mechanism!
>
> You're a few years late, as pretty much nobody agreed with me that the
> operating system handling of it was plenty.

What I don't understand about this is that it's not like we have these sort
of checks in general - just in this weirdly specific case. I could
understand that argument if we were doing null pointer checks in general,
but we're not, and you clearly haven't given in to the push for that.

In _C++_, I have literally only seen a null this pointer inside a member
function twice in my career (and the second time it happened, I had to
explain what was happening to my coworkers - some of them being quite
knowledgeable - because they didn't even think that it was possible to call
a function with a null pointer and not have it blow up at the call site). I
have never seen this problem in D. I would be _very_ surprised if you
couldn't just remove this check, and no one would complain because they hit
this problem and didn't get an assertion.

> > Note that there is a significant difference between this situation
> > (where you are *adding* an extra check), and the argument to add
> > messages to asserts (where you are *already* asserting).
>
> It's not really different. It's the desire for ever more messages. I've
> long advocated that a file/line is quite sufficient, but I seem to be in
> a tiny minority of 1. Now 2. :-)

For some assertions, having more than a file and line number is nice (e.g.
if you have messages for your pre-condition assertions, then you can make it
so that when it fails, the programmer doesn't even need to look at the
source code), but for many, many assertions, having a message doesn't do
much for you IMHO. You need to look at the code anyway, and if it's
asserting an internal thing rather than DbC, then it's usually really not
the sort of thing where a message is going to help particularly. In such
cases, the only real benefit that I see from having an error message that
does more than tell you where the assertion was and what the call stack was
is that if you have a message, and there are several assertions in the same
area of code, then when an assertion fails, you're less likely to mistake
one assertion for another if the source you're looking at doesn't exactly
match the build that the person reporting the issue was using (and that
mismatch isn't always obvious if you're not just building and running your
code locally).

So, to an extent at least, I agree with you, but a number of folks do seem
to think that messages that add no information are better than no messages
for some reason, and unfortunately, there's now a PR to outright require
messages for all assertions in Phbos:

https://github.com/dlang/phobos/pull/5578

- Jonathan M Davis



Re: Automatic invariant generation

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 8:04 AM, Timon Gehr wrote:

On 09.07.2017 13:57, Steven Schveighoffer wrote:
3. Classes are where you might see this issue, as people declare a 
class and try to use it without allocating one all the time. But in 
this case, when you are calling a virtual function, the segfault 
occurs before the assert can ever be used.


What about final member functions?


It's possible one has a final class, and does experience this. But it's 
not likely -- most people don't think about virtual by default, and just 
have virtual functions.


Or the final member functions are called after attempting to access 
members or virtual functions.


Or you just learn not to leave class instances uninitialized (most 
have), and you never see the error.


I'll also note that dmd 2.050 still segfaults even for final functions. 
2.060 doesn't. I didn't test in between. So at least as far back as 
2.050, this was a wasted assert.


-Steve


Re: Automatic invariant generation

2017-07-09 Thread Timon Gehr via Digitalmars-d

On 09.07.2017 13:57, Steven Schveighoffer wrote:
3. Classes are where you might see this issue, as people declare a class 
and try to use it without allocating one all the time. But in this case, 
when you are calling a virtual function, the segfault occurs before the 
assert can ever be used.


What about final member functions?


Re: Automatic invariant generation

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 7:45 AM, Nicholas Wilson wrote:

On Sunday, 9 July 2017 at 11:37:55 UTC, Steven Schveighoffer wrote:

On 7/9/17 7:00 AM, Walter Bright wrote:

On 7/9/2017 3:37 AM, Steven Schveighoffer wrote:


Yet, here is an example of where we have effectively added a null 
pointer exception. > At the very least, this should be eliminated on 
Linux

and just use the signal handling null pointer error mechanism!


You're a few years late, as pretty much nobody agreed with me that 
the operating system handling of it was plenty.


I think you misunderstand, we have etc.linux.memoryerror that can 
actually throw an error on a null pointer using the signal handler.


I have a suggestion: eliminate this feature, and add a -npe switch to 
the compiler that errors on any null pointer usage. Asserts will be 
sprinkled in everywhere, but may be useful to someone debugging a 
nasty null pointer segfault somewhere.


I think the generated assert(this !is null) has its place, it is useful 
to catch a null this as early as possible but not by default. Perhaps 
debug mode (as in the compiler switch) or a switch of its own.


I'd argue it's not useful at all. I've seen segfaults many many many 
times when debugging D code. I've never seen this error show up. Even 
when developing RedBlackTree (which is full of null pointers to structs 
on every leaf). And it makes sense why too:


1. Structs are generally allocated on the stack, or an array, or inside 
another type. Very rarely would you have a struct pointer that you 
didn't initialize (and was therefore null).
2. Often times, you are using a struct's data members, so you get a 
segfault before ever trying to call a method on it.
3. Classes are where you might see this issue, as people declare a class 
and try to use it without allocating one all the time. But in this case, 
when you are calling a virtual function, the segfault occurs before the 
assert can ever be used.


That being said, if people depend on it for some reason, switching it to 
an opt-in feature would be fine with me. In that case, I suggest just 
going whole-hog, and instrumenting all pointers.


-Steve


Re: Automatic invariant generation

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 7:10 AM, Walter Bright wrote:

On 7/7/2017 7:26 AM, Steven Schveighoffer wrote:

And since when did we care about null pointers causing segfaults?


Remember Tony Hoare's "The Billion Dollar Mistake"? That added a lot of 
fuel to the fire that a null pointer seg fault is supposed to be avoided 
at all costs, leading to wanting a softer, friendlier assert message 
instead.


I strongly disagree with Hoare - the billion dollar C mistake is having 
arrays relentlessly decay to pointers, leading to endless buffer 
overflow bugs. Seg faults aren't malware vectors.


But this isn't that. This is asserting a certain type of pointer (the 
this pointer), which is almost NEVER null, isn't null. It's so 
ineffective, I've never seen it trigger in 10 years. It's basically the 
worst possible place to deviate from the rule of "we don't do null 
pointer exceptions".



Can anyone vouch for this feature?


I'm sure if you're willing to spend a while searching this n.g. 
database, you'll find a lot.


I've seen a lot of people argue on the n.g. that null pointer checks 
should be added for every pointer dereference. I've NEVER seen anyone 
argue that upon every member function call, the compiler should verify 
`this` isn't null. Of course, why would they? it's already there :P


I'm seeing a large swath of well-known people arguing in this thread 
that it shouldn't work this way, and 0 people defending it.


-Steve


Re: Automatic invariant generation

2017-07-09 Thread Nicholas Wilson via Digitalmars-d
On Sunday, 9 July 2017 at 11:37:55 UTC, Steven Schveighoffer 
wrote:

On 7/9/17 7:00 AM, Walter Bright wrote:

On 7/9/2017 3:37 AM, Steven Schveighoffer wrote:


Yet, here is an example of where we have effectively added a 
null pointer exception. > At the very least, this should be 
eliminated on Linux

and just use the signal handling null pointer error mechanism!


You're a few years late, as pretty much nobody agreed with me 
that the operating system handling of it was plenty.


I think you misunderstand, we have etc.linux.memoryerror that 
can actually throw an error on a null pointer using the signal 
handler.


I have a suggestion: eliminate this feature, and add a -npe 
switch to the compiler that errors on any null pointer usage. 
Asserts will be sprinkled in everywhere, but may be useful to 
someone debugging a nasty null pointer segfault somewhere.


-Steve


I think the generated assert(this !is null) has its place, it is 
useful to catch a null this as early as possible but not by 
default. Perhaps debug mode (as in the compiler switch) or a 
switch of its own.


Re: Automatic invariant generation

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 7:00 AM, Walter Bright wrote:

On 7/9/2017 3:37 AM, Steven Schveighoffer wrote:


Yet, here is an example of where we have effectively added a null 
pointer exception. > At the very least, this should be eliminated on 
Linux

and just use the signal handling null pointer error mechanism!


You're a few years late, as pretty much nobody agreed with me that the 
operating system handling of it was plenty.


I think you misunderstand, we have etc.linux.memoryerror that can 
actually throw an error on a null pointer using the signal handler.


I have a suggestion: eliminate this feature, and add a -npe switch to 
the compiler that errors on any null pointer usage. Asserts will be 
sprinkled in everywhere, but may be useful to someone debugging a nasty 
null pointer segfault somewhere.


-Steve


Re: Automatic invariant generation

2017-07-09 Thread Nicholas Wilson via Digitalmars-d

On Sunday, 9 July 2017 at 11:13:02 UTC, Walter Bright wrote:

On 7/7/2017 7:08 AM, Nicholas Wilson wrote:
It is certainly unacceptable in the long run to demand that if 
users wish to use DCompute that they can't have asserts _in 
the code running in the host_.


One thing you can do is replace:

assert(i > 3);

with:

if (!(i > 3)) assert(0);

which won't be removed with -release, and the only bloat will 
be a lovely HLT instruction.


Of course I could do that for _my_ code , but I am not every end 
user, and even if I was doing the above is not a good use of my 
time.


And this wouldn't be so bad if it were code that I or someone 
else had written, but the fact that the compiler inserts it and I 
didn't ask for it and, save from hacking the compiler, I can't 
make it do otherwise.


Re: Automatic invariant generation

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/7/2017 7:08 AM, Nicholas Wilson wrote:
It is certainly unacceptable in the 
long run to demand that if users wish to use DCompute that they can't have 
asserts _in the code running in the host_.


One thing you can do is replace:

assert(i > 3);

with:

if (!(i > 3)) assert(0);

which won't be removed with -release, and the only bloat will be a lovely HLT 
instruction.


Re: Automatic invariant generation

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/7/2017 7:26 AM, Steven Schveighoffer wrote:

And since when did we care about null pointers causing segfaults?


Remember Tony Hoare's "The Billion Dollar Mistake"? That added a lot of fuel to 
the fire that a null pointer seg fault is supposed to be avoided at all costs, 
leading to wanting a softer, friendlier assert message instead.


I strongly disagree with Hoare - the billion dollar C mistake is having arrays 
relentlessly decay to pointers, leading to endless buffer overflow bugs. Seg 
faults aren't malware vectors.




Can anyone vouch for this feature?


I'm sure if you're willing to spend a while searching this n.g. database, you'll 
find a lot.


Re: Automatic invariant generation

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 3:37 AM, Steven Schveighoffer wrote:
Wait, you have stated many many times, a segfault is good enough, it's not worth 
the added cost to do null pointer exceptions (a position I'm completely in 
agreement with).


That's right.


Yet, here is an example of where we have effectively added a 
null pointer exception. > At the very least, this should be eliminated on Linux

and just use the signal handling null pointer error mechanism!


You're a few years late, as pretty much nobody agreed with me that the operating 
system handling of it was plenty.



Note that there is a significant difference between this situation (where you 
are *adding* an extra check), and the argument to add messages to asserts (where 
you are *already* asserting).


It's not really different. It's the desire for ever more messages. I've long 
advocated that a file/line is quite sufficient, but I seem to be in a tiny 
minority of 1. Now 2. :-)



Also noted, even if you inline, the assert is still there. Those who want to 
keep asserts (particularly for safety reasons), will pay this penalty.


Yup. Though at one point I advocated an option to replace the assert fails with 
a HLT instruction.



I've been using D for 10 years, and have never triggered this assert. But I've 
apparently paid for it that entire time.


It's always worth looking at the assembler output now and then.

---
The thing is, the bloat from all these messages and checks has caused DMD to be 
compiled with -release. Oops, that let through a few bugs.




Re: Automatic invariant generation

2017-07-09 Thread Nicholas Wilson via Digitalmars-d
On Sunday, 9 July 2017 at 10:37:53 UTC, Steven Schveighoffer 
wrote:

On 7/9/17 5:14 AM, Walter Bright wrote:

On 7/7/2017 7:31 AM, Nicholas Wilson wrote:
asserts that the this pointer is not null, apparently which 
is annoying because you'd crash anyway. I suppose you might 
get a nicer error message but it doesn't add much.


If I recall correctly, the nicer message was the reason. (It 
was a long time ago.)


This kind of thing has been asked for, a lot. The current 
thread entitled:


"All asserts need to have messages attached! Explicit as 
possible!"


is representative.


Wait, you have stated many many times, a segfault is good 
enough, it's not worth the added cost to do null pointer 
exceptions (a position I'm completely in agreement with). Yet, 
here is an example of where we have effectively added a null 
pointer exception. At the very least, this should be eliminated 
on Linux and just use the signal handling null pointer error 
mechanism!


Note that there is a significant difference between this 
situation (where you are *adding* an extra check), and the 
argument to add messages to asserts (where you are *already* 
asserting). For the record, I also don't agree that all asserts 
need messages.


Also noted, even if you inline, the assert is still there. 
Those who want to keep asserts (particularly for safety 
reasons), will pay this penalty.


In things like smart pointer wrappers or converters, many 
things are properties. inlining these is supposed to boil down 
to simply accessing the right field, with zero added cost. That 
is also a lie.


Or factoring out pieces of a function into more modular member 
functions. Now you are compounding the asserts. When calling 
another member function from within one, there is no reason to 
re-assert `this !is null`.


We need to get rid of this feature, or at least make it 
optional (and by optional, I mean opt-in). And no, having 
-release remove all asserts is not the same as having the 
ability to eliminate asserts I never wrote or wanted. At least 
the assert shouldn't appear in virtual functions (which will 
never fail because the vlookup will segfault before it ever 
gets there).


I've been using D for 10 years, and have never triggered this 
assert. But I've apparently paid for it that entire time.


-Steve


In C++, but I recently ran across this problem debugging LLVM and 
wasted a good while trying to figure out what was causing the 
crash. This would have been a useful feature (actually if i had 
been comping in debug mode I would have hit that informative 
assert but I was too stubborn to recompile), so it does have its 
place but I think on by default is not it and certainly if it is 
not under my control.


The most annoying part is that the struct will _never_ be passed 
by pointer, its a struct that contains a struct that contains a 
pointer, POD if ever there was. In the older models of OpenCL you 
can't have pointers to pointers _at all_ so by definition the 
assert will never be triggered.


Re: Automatic invariant generation

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 5:14 AM, Walter Bright wrote:

On 7/7/2017 7:31 AM, Nicholas Wilson wrote:
asserts that the this pointer is not null, apparently which is 
annoying because you'd crash anyway. I suppose you might get a nicer 
error message but it doesn't add much.


If I recall correctly, the nicer message was the reason. (It was a long 
time ago.)


This kind of thing has been asked for, a lot. The current thread entitled:

"All asserts need to have messages attached! Explicit as possible!"

is representative.


Wait, you have stated many many times, a segfault is good enough, it's 
not worth the added cost to do null pointer exceptions (a position I'm 
completely in agreement with). Yet, here is an example of where we have 
effectively added a null pointer exception. At the very least, this 
should be eliminated on Linux and just use the signal handling null 
pointer error mechanism!


Note that there is a significant difference between this situation 
(where you are *adding* an extra check), and the argument to add 
messages to asserts (where you are *already* asserting). For the record, 
I also don't agree that all asserts need messages.


Also noted, even if you inline, the assert is still there. Those who 
want to keep asserts (particularly for safety reasons), will pay this 
penalty.


In things like smart pointer wrappers or converters, many things are 
properties. inlining these is supposed to boil down to simply accessing 
the right field, with zero added cost. That is also a lie.


Or factoring out pieces of a function into more modular member 
functions. Now you are compounding the asserts. When calling another 
member function from within one, there is no reason to re-assert `this 
!is null`.


We need to get rid of this feature, or at least make it optional (and by 
optional, I mean opt-in). And no, having -release remove all asserts is 
not the same as having the ability to eliminate asserts I never wrote or 
wanted. At least the assert shouldn't appear in virtual functions (which 
will never fail because the vlookup will segfault before it ever gets 
there).


I've been using D for 10 years, and have never triggered this assert. 
But I've apparently paid for it that entire time.


-Steve


Re: Automatic invariant generation

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/7/2017 7:31 AM, Nicholas Wilson wrote:
asserts that the this pointer is not null, apparently which is annoying because 
you'd crash anyway. I suppose you might get a nicer error message but it doesn't 
add much.


If I recall correctly, the nicer message was the reason. (It was a long time 
ago.)

This kind of thing has been asked for, a lot. The current thread entitled:

"All asserts need to have messages attached! Explicit as possible!"

is representative.


Automatic precondition generation (Was: Re: Automatic invariant generation)

2017-07-08 Thread Timon Gehr via Digitalmars-d

On 07.07.2017 16:17, Jonathan M Davis via Digitalmars-d wrote:

On Friday, July 7, 2017 1:38:13 PM MDT Stefan Koch via Digitalmars-d wrote:

On Friday, 7 July 2017 at 13:34:20 UTC, Steven Schveighoffer

wrote:

On 7/7/17 4:21 AM, Nicholas Wilson wrote:

The compiler seems to inset an `assert(this !is null, "null
this");` into my struct.
which is for all intents and purposes.
struct Foo {

  Bar b;

}

struct Bar {

  void* ptr;

}


What? When is this invariant called? I've never heard of a
hidden invariant being added to structs, structs are supposed
to be free of such things.

I would call such a thing a bug.

-Steve


It was added because someone VIP demanded it I guess.
you can see the assert being added using -vcg-ast ;)


What does it even do? I don't see how it makes any sense for _anything_ to
have an invariant if it's not explicitly declared.


It is not an implicit invariant, it is an implicit precondition of a 
member function. (The 'this' reference is not part of the state, it is a 
function argument.)




And honestly, I'm of the
opinion that invariants with structs are borderline useless, because they're
run even before opAssign, meaning that if you ever need to use = void;


A struct that has public methods that can accept an uninitialized 
instance does not have an invariant.

That does not mean invariants are useless for structs in general.


or use emplace,


Why would the invariant be called if you use emplace? There are no 
public member functions involved.



then you're screwed if you have an invariant, because it's
bound to fail due to the object not having been initialized previously. > Unfortunately, I couldn't get Walter to agree that it made sense to 

not call

the invariant prior to opAssign being called


It does not always make sense, and when it does make sense, it is not 
limited to opAssign, so maybe we can have an explicit way to disable 
invariant calls for member functions that do not rely on the object 
invariant. (For non-operator overloads there is an obvious workaround: 
just forward to a private member function using UFCS.)



- which is why SysTime no
longer has an invariant (it was blowing up in people's code due to emplace
IIRC).


The only way this can be a problem is if they emplace a state that does 
not satisfy the invariant and then call opAssign. Was your invariant 
satisfied in the init state?



As such, it seems that much more stupid for structs to get any kind
fo invariant automatically.

- Jonathan M Davis



That's not what is happening though.


Re: Automatic invariant generation

2017-07-07 Thread Jonathan M Davis via Digitalmars-d
On Friday, July 7, 2017 2:31:42 PM MDT Nicholas Wilson via Digitalmars-d 
wrote:
> On Friday, 7 July 2017 at 14:17:34 UTC, Jonathan M Davis wrote:
> > What does it even do?
>
> asserts that the this pointer is not null, apparently which is
> annoying because you'd crash anyway. I suppose you might get a
> nicer error message but it doesn't add much.
>
> > I don't see how it makes any sense for _anything_ to have an
> > invariant if it's not explicitly declared.
>
> Worse I can't even @disable it because thats a syntax error.
>
> > And honestly, I'm of the opinion that invariants with structs
> > are borderline useless, because they're run even before
> > opAssign, meaning that if you ever need to use = void; or use
> > emplace, then you're screwed if you have an invariant, because
> > it's bound to fail due to the object not having been
> > initialized previously.
>
> Huh, I didn't know that.

I was not pleased to find out about it either, and the result is that I tend
to think that invariants have no business being in structs, much as it would
be desriable for them to be there.

> That does seems to be purpose defeating zealotry.

It's desirable when the object is supposed to be in a good state, because
then you know that when you do the assignment, you'll catch if something
broke the invariant before the assignment. But it's completely undesirable
when the object was purposely uninitialized, and since you can't choose
whether the invariant is run or not, IMHO, _not_ running it would be better,
but I was not persuasive enough:

https://issues.dlang.org/show_bug.cgi?id=5058

I was discussing this issue with someone at dconf, and as a result of that
conversation, I've considered writing a DIP that would allow you to
explicitly skip calling an invariant on a specific assignment (since in
theory, you should know when you're assigning to an unitialized object), but
I haven't had the time to think it through completely, let alone put
together a DIP that might actually be persuasive.

- Jonathan M Davis



Re: Automatic invariant generation

2017-07-07 Thread ketmar via Digitalmars-d

Steven Schveighoffer wrote:


On 7/7/17 4:26 PM, ketmar wrote:

Steven Schveighoffer wrote:


On 7/7/17 2:27 PM, ketmar wrote:

ketmar wrote:

yeah, this is annoying. while checking for "null this" in *class* 
method may look hacky
tbh, i see nothing wrong in checking for "null this" even in class 
methods, but this is a completely different story.


In *final* methods maybe. Virtual methods are going to crash anyway 
before they get to that point.
i meant "in manual checking", i.e. "i think that compiler-inserted 
`assert` is not necessary at all". sorry for writing indecipherable 
engrish. ;-)


My statement still applies ;)


yeah ;-)


Re: Automatic invariant generation

2017-07-07 Thread Steven Schveighoffer via Digitalmars-d

On 7/7/17 4:26 PM, ketmar wrote:

Steven Schveighoffer wrote:


On 7/7/17 2:27 PM, ketmar wrote:

ketmar wrote:

yeah, this is annoying. while checking for "null this" in *class* 
method may look hacky
tbh, i see nothing wrong in checking for "null this" even in class 
methods, but this is a completely different story.


In *final* methods maybe. Virtual methods are going to crash anyway 
before they get to that point.


i meant "in manual checking", i.e. "i think that compiler-inserted 
`assert` is not necessary at all". sorry for writing indecipherable 
engrish. ;-)


My statement still applies ;)

-Steve


Re: Automatic invariant generation

2017-07-07 Thread ketmar via Digitalmars-d

Steven Schveighoffer wrote:


On 7/7/17 2:27 PM, ketmar wrote:

ketmar wrote:

yeah, this is annoying. while checking for "null this" in *class* 
method may look hacky
tbh, i see nothing wrong in checking for "null this" even in class 
methods, but this is a completely different story.


In *final* methods maybe. Virtual methods are going to crash anyway 
before they get to that point.


i meant "in manual checking", i.e. "i think that compiler-inserted `assert` 
is not necessary at all". sorry for writing indecipherable engrish. ;-)


Re: Automatic invariant generation

2017-07-07 Thread Steven Schveighoffer via Digitalmars-d

On 7/7/17 2:27 PM, ketmar wrote:

ketmar wrote:

yeah, this is annoying. while checking for "null this" in *class* 
method may look hacky


tbh, i see nothing wrong in checking for "null this" even in class 
methods, but this is a completely different story.


In *final* methods maybe. Virtual methods are going to crash anyway 
before they get to that point.


e.g.:

class C
{
void foo() {}
final void bar() {}
}
void main()
{
C c;
version(segfault) c.foo();
version(asserts) c.bar();
}

using -vcg-ast (BTW, I really like this feature!) shows that the assert 
is still put inside foo, even though it will never trigger!


In older versions of dmd, both segfault, I think maybe because the 
virtual invariant is attempted before calling either.


-Steve


Re: Automatic invariant generation

2017-07-07 Thread ketmar via Digitalmars-d

ketmar wrote:

yeah, this is annoying. while checking for "null this" in *class* method 
may look hacky


tbh, i see nothing wrong in checking for "null this" even in class methods, 
but this is a completely different story.


Re: Automatic invariant generation

2017-07-07 Thread ketmar via Digitalmars-d

Steven Schveighoffer wrote:

Hm... it doesn't look like an invariant, it just looks like an inserted 
assert inside every function.


An incorrect assert, IMO:

struct Foo
{
 int x;
 void foo() {}
}

void main()
{
Foo *foo;
foo.foo(); // shouldn't assert, wouldn't crash anyway.
}


yeah, this is annoying. while checking for "null this" in *class* method 
may look hacky, i see nothing wrong in "null this" for struct method. tbh, 
i patched that assert (the whole invariant thingy, actually) away long time 
ago, and only remembered about it recently, when my code spit that error in 
vanilla. real PITA, 'cause adding useless checks for "if this struct 
pointer isn't null, then assign what struct method will assign on null, and 
don't forget to sync it when i'll change method, and no, you cannot assert 
in ternaly without deprecated comma, and... no, that code won't be 
converted to 'normal D'."


Re: Automatic invariant generation

2017-07-07 Thread Nicholas Wilson via Digitalmars-d
On Friday, 7 July 2017 at 14:26:57 UTC, Steven Schveighoffer 
wrote:
Hm... it doesn't look like an invariant, it just looks like an 
inserted assert inside every function.




Ahh, thats why I get duplicate asserts when I add an assert.

And since when did we care about null pointers causing 
segfaults?


Can anyone vouch for this feature?

-Steve


Not me.




Re: Automatic invariant generation

2017-07-07 Thread Nicholas Wilson via Digitalmars-d

On Friday, 7 July 2017 at 14:17:34 UTC, Jonathan M Davis wrote:

What does it even do?


asserts that the this pointer is not null, apparently which is 
annoying because you'd crash anyway. I suppose you might get a 
nicer error message but it doesn't add much.


I don't see how it makes any sense for _anything_ to have an 
invariant if it's not explicitly declared.


Worse I can't even @disable it because thats a syntax error.

And honestly, I'm of the opinion that invariants with structs 
are borderline useless, because they're run even before 
opAssign, meaning that if you ever need to use = void; or use 
emplace, then you're screwed if you have an invariant, because 
it's bound to fail due to the object not having been 
initialized previously.


Huh, I didn't know that. That does seems to be purpose defeating 
zealotry.



Unfortunately, I couldn't get Walter to
agree that it made sense to not call the invariant prior to 
opAssign being called - which is why SysTime no longer has an 
invariant (it was blowing up in people's code due to emplace 
IIRC). As such, it seems that much more stupid for structs to 
get any kind fo invariant automatically.


- Jonathan M Davis


Re: Automatic invariant generation

2017-07-07 Thread Steven Schveighoffer via Digitalmars-d

On 7/7/17 9:38 AM, Stefan Koch wrote:

On Friday, 7 July 2017 at 13:34:20 UTC, Steven Schveighoffer wrote:

On 7/7/17 4:21 AM, Nicholas Wilson wrote:
The compiler seems to inset an `assert(this !is null, "null this");` 
into my struct.

which is for all intents and purposes.
struct Foo {
 Bar b;
}

struct Bar {
 void* ptr;
}


What? When is this invariant called? I've never heard of a hidden 
invariant being added to structs, structs are supposed to be free of 
such things.


I would call such a thing a bug.



It was added because someone VIP demanded it I guess.


Nope, it's really REALLY old (version 0.167):

https://github.com/dlang/dmd/commit/43a336d81c38817ae545becf02b7459836025c60


you can see the assert being added using -vcg-ast ;)



Hm... it doesn't look like an invariant, it just looks like an inserted 
assert inside every function.


An incorrect assert, IMO:

struct Foo
{
int x;
void foo() {}
}

void main()
{
   Foo *foo;
   foo.foo(); // shouldn't assert, wouldn't crash anyway.
}

And since when did we care about null pointers causing segfaults?

Can anyone vouch for this feature?

-Steve


Re: Automatic invariant generation

2017-07-07 Thread Jonathan M Davis via Digitalmars-d
On Friday, July 7, 2017 1:38:13 PM MDT Stefan Koch via Digitalmars-d wrote:
> On Friday, 7 July 2017 at 13:34:20 UTC, Steven Schveighoffer
>
> wrote:
> > On 7/7/17 4:21 AM, Nicholas Wilson wrote:
> >> The compiler seems to inset an `assert(this !is null, "null
> >> this");` into my struct.
> >> which is for all intents and purposes.
> >> struct Foo {
> >>
> >>  Bar b;
> >>
> >> }
> >>
> >> struct Bar {
> >>
> >>  void* ptr;
> >>
> >> }
> >
> > What? When is this invariant called? I've never heard of a
> > hidden invariant being added to structs, structs are supposed
> > to be free of such things.
> >
> > I would call such a thing a bug.
> >
> > -Steve
>
> It was added because someone VIP demanded it I guess.
> you can see the assert being added using -vcg-ast ;)

What does it even do? I don't see how it makes any sense for _anything_ to
have an invariant if it's not explicitly declared. And honestly, I'm of the
opinion that invariants with structs are borderline useless, because they're
run even before opAssign, meaning that if you ever need to use = void; or
use emplace, then you're screwed if you have an invariant, because it's
bound to fail due to the object not having been initialized previously.
Unfortunately, I couldn't get Walter to agree that it made sense to not call
the invariant prior to opAssign being called - which is why SysTime no
longer has an invariant (it was blowing up in people's code due to emplace
IIRC). As such, it seems that much more stupid for structs to get any kind
fo invariant automatically.

- Jonathan M Davis



Re: Automatic invariant generation

2017-07-07 Thread Nicholas Wilson via Digitalmars-d
On Friday, 7 July 2017 at 13:34:20 UTC, Steven Schveighoffer 
wrote:

On 7/7/17 4:21 AM, Nicholas Wilson wrote:
The compiler seems to inset an `assert(this !is null, "null 
this");` into my struct.

which is for all intents and purposes.
struct Foo {
 Bar b;
}

struct Bar {
 void* ptr;
}


What? When is this invariant called? I've never heard of a 
hidden invariant being added to structs, structs are supposed 
to be free of such things.


I would call such a thing a bug.

-Steve


I am missing a couple of methods on Foo in that example that in 
turn call the invariant.
That at least can be disable with -release, which while certainly 
not desirable is not a blocker _for me at the moment_. It is 
certainly unacceptable in the long run to demand that if users 
wish to use DCompute that they can't have asserts _in the code 
running in the host_.


However at the moment I'm have more trouble with 
https://forum.dlang.org/thread/ayanaomqklqvknzrl...@forum.dlang.org any help appreciated.


Re: Automatic invariant generation

2017-07-07 Thread Stefan Koch via Digitalmars-d
On Friday, 7 July 2017 at 13:34:20 UTC, Steven Schveighoffer 
wrote:

On 7/7/17 4:21 AM, Nicholas Wilson wrote:
The compiler seems to inset an `assert(this !is null, "null 
this");` into my struct.

which is for all intents and purposes.
struct Foo {
 Bar b;
}

struct Bar {
 void* ptr;
}


What? When is this invariant called? I've never heard of a 
hidden invariant being added to structs, structs are supposed 
to be free of such things.


I would call such a thing a bug.

-Steve


It was added because someone VIP demanded it I guess.
you can see the assert being added using -vcg-ast ;)



Re: Automatic invariant generation

2017-07-07 Thread Steven Schveighoffer via Digitalmars-d

On 7/7/17 4:21 AM, Nicholas Wilson wrote:
The compiler seems to inset an `assert(this !is null, "null this");` 
into my struct.

which is for all intents and purposes.
struct Foo {
 Bar b;
}

struct Bar {
 void* ptr;
}


What? When is this invariant called? I've never heard of a hidden 
invariant being added to structs, structs are supposed to be free of 
such things.


I would call such a thing a bug.

-Steve


Re: Automatic invariant generation

2017-07-07 Thread Nemanja Boric via Digitalmars-d

On Friday, 7 July 2017 at 08:21:50 UTC, Nicholas Wilson wrote:
The compiler seems to inset an `assert(this !is null, "null 
this");` into my struct.

which is for all intents and purposes.
struct Foo {
Bar b;
}

struct Bar {
void* ptr;
}

I tried disabling the invariant but it complained that 
invariant requires a function body.
Is there a way to disable the implicit generations of 
invariants for my code other than -release? Like for a 
particular subset of files (separate invocations of the 
compiler is not an acceptable approach.


The reason being that I do not support global variables (of any 
kind) at the moment in dcompute and the insertion of the string 
literal to the assert breaks that.


Related: https://github.com/dlang/DIPs/blob/master/DIPs/DIP1006.md


Re: Automatic invariant generation

2017-07-07 Thread Stefan Koch via Digitalmars-d

On Friday, 7 July 2017 at 08:35:28 UTC, Nicholas Wilson wrote:

On Friday, 7 July 2017 at 08:24:22 UTC, Stefan Koch wrote:

On Friday, 7 July 2017 at 08:21:50 UTC, Nicholas Wilson wrote:

[...]


Looks like you'd need to do your own hack to disable this 
particular assert.

When it's used in a dcompute-context.


Problem is it gets decided wy before.


You should be able to hack around it.
LDC should be able to given you a hit when it hits this.
It's the first thing that gets put in the method.
So it has a fixed location.
Hence you can treat is it specially.


Re: Automatic invariant generation

2017-07-07 Thread Nicholas Wilson via Digitalmars-d

On Friday, 7 July 2017 at 08:24:22 UTC, Stefan Koch wrote:

On Friday, 7 July 2017 at 08:21:50 UTC, Nicholas Wilson wrote:

[...]


Looks like you'd need to do your own hack to disable this 
particular assert.

When it's used in a dcompute-context.


Problem is it gets decided wy before.


Re: Automatic invariant generation

2017-07-07 Thread Stefan Koch via Digitalmars-d

On Friday, 7 July 2017 at 08:21:50 UTC, Nicholas Wilson wrote:
The compiler seems to inset an `assert(this !is null, "null 
this");` into my struct.

which is for all intents and purposes.
struct Foo {
Bar b;
}

struct Bar {
void* ptr;
}

I tried disabling the invariant but it complained that 
invariant requires a function body.
Is there a way to disable the implicit generations of 
invariants for my code other than -release? Like for a 
particular subset of files (separate invocations of the 
compiler is not an acceptable approach.


The reason being that I do not support global variables (of any 
kind) at the moment in dcompute and the insertion of the string 
literal to the assert breaks that.


Looks like you'd need to do your own hack to disable this 
particular assert.

When it's used in a dcompute-context.


Automatic invariant generation

2017-07-07 Thread Nicholas Wilson via Digitalmars-d
The compiler seems to inset an `assert(this !is null, "null 
this");` into my struct.

which is for all intents and purposes.
struct Foo {
Bar b;
}

struct Bar {
void* ptr;
}

I tried disabling the invariant but it complained that invariant 
requires a function body.
Is there a way to disable the implicit generations of invariants 
for my code other than -release? Like for a particular subset of 
files (separate invocations of the compiler is not an acceptable 
approach.


The reason being that I do not support global variables (of any 
kind) at the moment in dcompute and the insertion of the string 
literal to the assert breaks that.