Re: Manu's `shared` vs the @trusted promise

2018-10-22 Thread ag0aep6g via Digitalmars-d

On Monday, 22 October 2018 at 11:24:27 UTC, Dukc wrote:
Frankly, this does not sound credible. According to this 
rationale, array access should be @system too, because it 
relies on the array not giving direct access to its length to 
the user, which would also in itself be @safe.


Arrays are a language builtin. As far as I'm aware, there isn't 
actually an struct defined in DRuntime for arrays. But maybe I'm 
wrong. If there is, and if it uses a plain size_t for the length 
member, then it is breaking the strong @trusted promise, yes.


But having existing exceptions to the rule doesn't mean that the 
rule is void. We could identify the existing exceptions as bugs 
and try to fix them. Or we could say that they're a necessary 
evil, but we don't want to add more evil.


On the other hand, D could of course embrace a weaker 
@trusted/@safe. That would be up to Walter and Andrei, I guess. 
As far as I can tell from the other `shared` thread, Walter 
currently favors a strong @trusted.


Re: Manu's `shared` vs the @trusted promise

2018-10-22 Thread ag0aep6g via Digitalmars-d

On 22.10.18 11:40, Manu wrote:

On Mon, Oct 22, 2018 at 2:21 AM ag0aep6g via Digitalmars-d
 wrote:

[...]

I don't agree. I prefer the stronger @trusted. As far as I know, the
stronger one is the current one.


The current one has the critical weakness that it causes **EVERY
USER** to write unsafe code, manually casting things to shared.


You're conflating @trusted with `shared`. As I've tried to show, your 
version of `shared` probably doesn't need the weaker @trusted. It can 
work with the stronger one.


And I'm not trying to defend the current `shared` in any way.


You're here spouting some fantasy


With these snarky asides, you're making it difficult to argue for your side.


Re: Manu's `shared` vs the @trusted promise

2018-10-22 Thread ag0aep6g via Digitalmars-d

On 22.10.18 11:33, Manu wrote:

On Sun, Oct 21, 2018 at 3:05 PM ag0aep6g via Digitalmars-d
 wrote:

[...]

It's @trusted, not @safe... so I don't think you can say "It's invalid
because we can even possibly write an Atomic.badboy" (I would agree to
that statement if it were @safe).
That's the thing about @trusted, you have to trust the engineer to
confirm contextual correctness.


Your definition of @trusted is weaker than mine. I think the one I gave 
is the one that's in the spec and the one that Walter and Timon work with.



But semantics aside, how and why did you add code to this module? Do
you usually add code to druntime or phobos?
Assuming you did add code to this module, are you telling me that you
don't understand what Atomic() does, and you also did not understand
the rules of `shared`? You can't be trusted to write threadsafe code
if you don't understand `shared`s rules.
My point is, do you genuinely believe this is a high-risk? When did
you last rewrite Atomic(T) because you didn't like the one in
druntime? Have you ever heard of a case of that?

I mean, I understand it's _possible_ to violate incr()'s promise, and
that's why it's @trusted, and not @safe. But what's the probability of
that happening by accident... and would you *honestly* make an
argument that this unlikely scenario is more likely to occur than any
of your 900 high-level engineers making any sort of mistake with
respect to the *use* of shared's current rules, which require unsafe
interaction at every call, by every end-user?
Most users don't modify druntime.[...]
I agree the situation you fear is technically possible, but I think
it's very unlikely,


You're arguing with probability while the other camp is entrenched in 
fundamentals. The goal is a very strong @safe. All @safe code must be 
compiler-verifiable safe. With the weaker @trusted, that doesn't hold 
when the @safe code is next to @trusted code. So the weaker @trusted is 
unacceptable.


By the way, can you dial down the confrontational rhetoric, please? I'm 
pretty much trying to help get your point across here. I don't need 
snarky questions/remarks about my ability to write thread-safe code. 
Even if I can't write correct code, it's besides the point.



and in balance to the risks associated with shared
today, which is completely unsafe at the user-facing level, and also
completely unregulated (you can access members freely)...


I think most agree it's bad that `shared` data can currently be accessed 
freely without casting, without atomics, without synchronization. I know 
that I agree.


[...]

I've said on at least 5 other occasions, I'm sure there are a whole
lot of options we can explore to assist and improve the probability
that the ground-level author doesn't make a mistake (although I am
quite confident you'd be wasting your time, because they won't make a
mistake like this anyway).
That conversation has nothing to do with the validity of the rules
though, which is what the other 400 post thread is about.


The perception is that one has to break the (stronger) @trusted promise 
in order to do anything with your version of `shared`. And that's 
perceived as bad.


So you have to show that breaking the @trusted promise is not necessary. 
I've tried to show that. Or you have to show that a weaker @trusted is 
preferable to the stronger one. Convincing people of that would be a 
hard task, I think.



If you *do* trust the 5-10 @trusted functions in the library; Is my
scheme sound?


If you can implement them without breaking the (strong) @trusted 
promise, then I guess so. If you can't, then no (arguably, depending on 
how @trusted is defined).


[...]

We can fuss about the details until the cows come home, but I'm
finding it impossible to get everyone on the same page in the first
place.


I think we're making progress right here. It seems to me that there are 
two slightly different definitions of @trusted floating around. Ideally, 
everyone would agree which one is correct (or more useful). Things might 
fall into place then.


Re: Manu's `shared` vs the @trusted promise

2018-10-22 Thread ag0aep6g via Digitalmars-d

On 22.10.18 10:39, Simen Kjærås wrote:

On Sunday, 21 October 2018 at 22:03:00 UTC, ag0aep6g wrote:

[...]

It's invalid only if Atomic.badboy exists.


I don't agree. I prefer the stronger @trusted. As far as I know, the 
stronger one is the current one.


Essentially, since the module is the unit of encapsulation, it also 
needs to be the unit of programmer responsibility.




[...]


struct Atomic
{
    shared/*!*/ int x;

    void incr() shared @trusted { /* ... */ }

    /* Now this gets rejected by the compiler: */
    void badboy() @safe { ++x; } /* compiler error  */
}


With a `shared int x` there's no way that @safe code might access it, 
so the @trusted promise is kept.


It's clearly better to mark x as shared, yes. However, I fail to see how 
this is significantly different from the above - J. Random Newbie can 
still open that file, remove the 'shared' qualifier on x, and rewrite 
badboy to be thread-unsafe. If we're going to assume that bad actors 
have write-access to all files, there's no end to the trouble that can 
be had.


It's not about bad actors, it's about mistakes and finding them. Of 
course, you can still makes mistakes with the stronger @trusted, but 
they will be in @trusted code.


In the example, if anything's wrong you know that the mistake must be in 
`incr`, because it's the only @trusted function. You don't even have to 
look at the @safe code. The compiler can check that it's ok.


Manu's `shared` vs the @trusted promise

2018-10-21 Thread ag0aep6g via Digitalmars-d
It took me a while to understand Manu's idea for `shared`, and I suspect 
that it was/is the same for others. At the same time, Manu seems 
bewildered about the objections. I'm going to try and summarize the 
situation. Maybe it can help advance the discussion.



(1) How Does Manu's `shared` Interact with @trusted?

With Manu's `shared`, there is implicit conversion from non-`shared` to 
`shared`. It would essentially become a language rule. For that rule to 
be sound, any access to `shared` data must be @system. And more 
challengingly, @system/@trusted code must be written carefully with the 
new rule in mind.


(Manu, you might say that the conversion follows from `shared` methods 
being "guaranteed threadsafe", but I think it's easier to reason this 
way. Anyway, potayto potahto.)


The consequence is: In @trusted code, I have to make sure that I have 
exclusive access to any `shared` data that I use. If code that is not 
under my control can obtain a non-`shared` view of the same data, I have 
failed and my @trusted code is invalid.


An example in code (just rehashing code given by Manu):


struct Atomic
{
private int x;

void incr() shared @trusted
{
/* ... atomically increment x ... */
}

/* If this next method is here, the one above is invalid. It's the
responsibility of the author of the @trusted code to make sure
that this doesn't happen. */

void badboy() @safe { ++x; } /* NO! BAD! NOT ALLOWED! */
}



(2) What's Wrong with That?

The @trusted contract says that an @trusted function must be safe when 
called from an @safe function. That calling @safe function might be 
located in the same module, meaning it might have the same level of 
access as the @trusted function.


That means, Atomic.incr is invalid. It's invalid whether Atomic.badboy 
exists or not. It's invalid because we can even possibly write an 
Atomic.badboy. That's my interpretation of the spec, at least.


But according to Manu, Atomic.incr is fine as long as there's no 
Atomic.badbody that messes things up. So it looks like we're expected to 
violate the @trusted contract when dealing with Manu's `shared`. But 
when we routinely have to break the rules, then that's a sign that the 
rules are bad.



(3) Maybe It Can Be Made to Work?

There might be a way to implement Atomic without breaking the @trusted 
promise:



struct Atomic
{
shared/*!*/ int x;

void incr() shared @trusted { /* ... */ }

/* Now this gets rejected by the compiler: */
void badboy() @safe { ++x; } /* compiler error  */
}


With a `shared int x` there's no way that @safe code might access it, so 
the @trusted promise is kept.


Manu, I don't know if marking fields like this is compatible with your 
plans. But it would address the @safe-ty issue, I think.


However, even if it's possible to reconcile Manu's `shared` with @safe 
and @trusted, that doesn't mean it's automatically golden, of course. It 
would be an enormous breaking change that should be well thought-out, 
scrutinized, planned, and executed.


Re: shared - i need it to be useful

2018-10-17 Thread ag0aep6g via Digitalmars-d

On 17.10.18 20:46, Manu wrote:

struct NotThreadsafe
{
   int x;
   void local()
   {
 ++x; // <- invalidates the method below, you violate the other
function's `shared` promise
   }
   void notThreadsafe() shared
   {
 atomicIncrement(&x);
   }
}


In the `shared` method you'd get a nice error when attempting `++x;`, 
because it's not thread-safe. With your proposal, it's just as unsafe in 
`local`, but you don't get any help from the compiler in spotting it. 
`local` is effectively `@trusted` without being marked as such.


Re: shared - i need it to be useful

2018-10-15 Thread ag0aep6g via Digitalmars-d

On 10/15/2018 08:46 PM, Manu wrote:

1. traditional; assert that the object become thread-local by
acquiring a lock, cast shared away
2. object may have shared methods; such methods CAN be called on
shared instances. such methods may internally implement
synchronisation to perform their function. perhaps methods of a
lock-free queue structure for instance, or operator overloads on
`Atomic!int`, etc.

[...]

Assuming the rules above: "can't read or write to members", and the
understanding that `shared` methods are expected to have threadsafe
implementations (because that's the whole point), what are the risks
from allowing T* -> shared(T)* conversion?


As far as I understand, the rule "can't read or write to members" is for 
the compiler, right? I can still read and write members, but I have to 
cast `shared` away and ensure thread-safety myself?


If that's so, then my example from the last thread might still apply:


struct Bob
{
  int* p;
  void doThing() shared
  {
p = &s; /* Might need a cast or two here, and a lock or an atomic 
store or whatever. */

  }
}
shared int s;


When the needed casts etc. are added, is `doThing` allowed? If not, I 
think you have to specify more precisely what a method can and can't do.


If `doThing` is ok, you can't allow T* -> shared(T)*. You'd be allowing 
aliasing an unqualified int* with a shared(int*):



void main()
{
  Bob* b = new Bob;
  shared(Bob)* sb = b; /* You'd allow this line. */
  sb.doThing();
  /* Now the unqualified int* b.p points to the shared int s. */
}



Re: `shared`...

2018-10-01 Thread ag0aep6g via Digitalmars-d

On 10/01/2018 08:47 AM, Nicholas Wilson wrote:
In order to be safe, a mutable parameter can be implicitly cast to 
shared iff the parameter is also scope (that includes the `this` 
reference`). With an implicit cast in place of the explicit cast under 
the new rules it would fail to compile because the `this` reference is 
not scope.


I don't see why it would fail to compile. There's no reason why my 
`doThing` couldn't be marked as `scope`. It doesn't leak anything.


`pure` would break the example. I'm not sure if it would ensure safety, 
though. Can a `pure` method spawn a new thread (that outlives the method 
call)?


Re: `shared`...

2018-09-30 Thread ag0aep6g via Digitalmars-d

On 10/01/2018 04:29 AM, Manu wrote:

struct Bob
{
   void setThing() shared;
}

[...]

void f(ref shared Bob a, ref Bob b)
{
   a.setThing(); // I have a shared object, can call shared method

   b.setThing(); // ERROR
}

This is the bit of the design that doesn't make sense to me...
The method is shared, which suggests that it must handle
thread-safety. My instance `b` is NOT shared, that is, it is
thread-local.

[...]

I feel like I don't understand the design...
mutable -> shared should work the same as mutable -> const... because
surely that's safe?


`shared` isn't analogous to `const`. It's analogous to `immutable`. 
Functions dealing with `shared` data can assume that other threads also 
see the data as `shared`. If you allow calling `shared` methods on 
non-`shared` objects, you're breaking that.


Example:


struct Bob
{
  int* p;
  void doThing() shared
  {
p = &s;
  }
}

shared int s;

void main()
{
  Bob bob;
  (cast(shared Bob)bob).doThing();/* You'd make the cast implicit. */

  import core.thread;
  import core.atomic;
  enum n = 1_000_000;
  auto t = new Thread(() { foreach (i; 0 .. n) atomicOp!"+="(s, 1); });
  t.start();
  foreach (i; 0 .. n) ++*bob.p;
  thread_joinAll();

  import std.stdio;
  writeln(s); /* usually not "200", because of race */
}



Re: Updating D beyond Unicode 2.0

2018-09-29 Thread ag0aep6g via Digitalmars-d

On 09/29/2018 04:19 PM, Shachar Shemesh wrote:

On 29/09/18 16:52, Dukc wrote:

[...]
I know you meant Sarn, but still... can you please be a bit less 
aggresive with our wording?


 From the article (the furthest point I read in it):
When I ask myself what I've found life is too short for, the word that 
pops into my head is "bullshit."


Dukc didn't post that link. sarn did.


Re: Dicebot on leaving D: It is anarchy driven development in all its glory.

2018-09-06 Thread ag0aep6g via Digitalmars-d

On 09/06/2018 12:40 PM, Chris wrote:
To avoid this you have to normalize and recompose any decomposed 
characters. I remember that Mac OS X used (and still uses?) decomposed 
characters by default, so when you typed 'á' into your cli, it would 
automatically decompose it to 'a' + acute. `string` however returns 
len=2 for composed characters too. If you do a lot of string handling it 
will come back to bite you sooner or later.


You say that D users shouldn't need a '"Unicode license" before they do 
anything with strings'. And you say that Python 3 gets it right (or 
maybe less wrong than D).


But here we see that Python requires a similar amount of Unicode 
knowledge. Without your Unicode license, you couldn't make sense of 
`len` giving different results for two strings that look the same.


So both D and Python require a Unicode license. But on top of that, D 
also requires an auto-decoding license. You need to know that `string` 
is both a range of code points and an array of code units. And you need 
to know that `.length` belongs to the array side, not the range side. 
Once you know that (and more), things start making sense in D.


My point is: D doesn't require more Unicode knowledge than Python. But 
D's auto-decoding gives `string` a dual nature, and that can certainly 
be confusing. It's part of why everybody dislikes auto-decoding.


(Not saying that Python is free from such pitfalls. I simply don't know 
the language well enough.)


Re: Dicebot on leaving D: It is anarchy driven development in all its glory.

2018-09-06 Thread ag0aep6g via Digitalmars-d

On 09/06/2018 09:23 AM, Chris wrote:

Python 3 gives me this:

print(len("á"))
1


Python 3 also gives you this:

print(len("á"))
2

(The example might not survive transfer from me to you if Unicode 
normalization happens along the way.)


That's when you enter the 'á' as 'a' followed by U+0301 (combining 
acute accent). So Python's `len` counts in code points, like D's 
std.range does (auto-decoding).


Re: Dicebot on leaving D: It is anarchy driven development in all its glory.

2018-08-23 Thread ag0aep6g via Digitalmars-d

On 08/23/2018 07:28 PM, H. S. Teoh wrote:

On Thu, Aug 23, 2018 at 06:39:32PM +0200, ag0aep6g via Digitalmars-d wrote:

[...]

Regressions aren't being fixed (78 open). Wrong-code don't get fixed
(170!).  Etc., and so on. So why even bother?


I think this is unfair.  Regressions *are* being fixed... but they're
getting reported at a faster rate than they're being fixed.  Wrong-code
bugs also *are* getting fixed... just not as fast as we'd like, but I
think it's unfair to say they aren't getting fixed.


Yeah, it was hyperbole for sure. Of course bugs are being fixed. But it 
feels like it takes longer and longer.


Elsewhere in this thread, Kenji Hara was mentioned. I had a look at my 
bug report history, and before Kenji left, he had managed to fix a third 
of the DMD bugs I had reported by that time. After Kenji's leaving, the 
fix rate dropped significantly and Walter had to step in more often.


So it's very possible that I'm just missing Kenji.


Re: D is dead

2018-08-23 Thread ag0aep6g via Digitalmars-d

On 08/23/2018 10:11 PM, Walter Bright wrote:

On 8/23/2018 5:55 AM, Steven Schveighoffer wrote:

[...]
I think he means, if the range ITSELF doesn't allow copying, it won't 
work with foreach (because foreach makes a copy), but it will work 
with opApply.


     foreach (ref v; collection)

does not make a copy.


It makes a copy of `collection`.

It's up to the programmer whether copying is done 
with it. After all, if one is passing a struct instance around by value 
instead of by ref, there is no escaping copying it. This should not be 
surprising.


It's not obvious that using `collection` in a `foreach` means passing it 
around by value.


Re: Dicebot on leaving D: It is anarchy driven development in all its glory.

2018-08-23 Thread ag0aep6g via Digitalmars-d

On 08/23/2018 05:17 PM, H. S. Teoh wrote:

And the nice thing about D being open source is that should the
situation escalate to the point where the community simply cannot get
along with W&A anymore, forking is always an option.


But forking only happens when the dissenters have enough motivation to 
do it. If they don't, they might just fade away one by one, looking for 
greener pastures elsewhere. That would probably be the worst outcome for 
D: the community shrinks until it's just Walter and Andrei wondering 
where everybody did go.


Now, I don't know if the amount of (quality) contributors is actually 
growing, shrinking, or stagnating. But I do know that I feel the pull 
(push?) away from D myself.


It feels like `@safe` and `shared` won't ever be solid. Auto-decoding 
won't go away. Unsound conversions (e.g., `char` -> `dchar`) won't go 
away. Regressions aren't being fixed (78 open). Wrong-code don't get 
fixed (170!). Etc., and so on. So why even bother?


Currently, I'm toying with ideas for a hobby language of my own. I know 
that it most likely won't go anywhere, but wasting time on that starts 
to feel more rewarding than wasting it on D.


Re: Is @safe still a work-in-progress?

2018-08-23 Thread ag0aep6g via Digitalmars-d

On Thursday, 23 August 2018 at 08:48:15 UTC, Walter Bright wrote:
Being a template doesn't make any difference, except that it 
will helpfully infer these things.


Including the `return` attribute.

Also, since 'this' is passed by 'ref' to struct member 
functions, it cannot escape anyway with dip1000:


  struct S {
int x;
@safe ref int foo() { return x; }
  }

  dmd test -dip1000
  test.d(4): Error: returning this.x escapes a reference to 
parameter this, perhaps annotate with return


If we add the `return` attribute, we can escape a pointer to 
`this`. And since attributes are often inferred, it might come as 
a surprise to the programmer.


However, as far as I understand DIP 1000, it should make sure 
that the returned pointer won't outlive the struct instance. And 
I guess that's why it's ok to infer the `return` attribute?


That depends on DMD not over-estimating the lifetimes of things, 
though. Unfortunately, it does just that. When in doubt, DMD goes 
with infinite (e.g., `malloc`). I think that's a problem.


But I've already demonstrated my ignorance regarding DIP 1000 in 
a long, not very fruitful discussion with Atila on Bugzilla [1], 
so maybe I just don't get it.



[1] https://issues.dlang.org/show_bug.cgi?id=19183


Re: Is there any hope for "lazy" and @nogc?

2018-07-31 Thread ag0aep6g via Digitalmars-d

On 07/31/2018 09:17 AM, Shachar Shemesh wrote:
I'm trying to figure out what's the signature of the built-in assert. It 
does not seem that I can define a similar function myself.


Looks like you can do it with a "lazy variadic function" [1], but it's 
not pretty:



alias Dg = string delegate() @nogc nothrow;

void myAssert(bool cond, Dg[1] msg_dg ...) @nogc nothrow
{
import core.stdc.stdio;
if (!cond)
{
string msg = msg_dg[0]();
printf("%*s\n", msg.length, msg.ptr);
}
}


[1] https://dlang.org/spec/function.html#lazy_variadic_functions


Re: A struct with a tuple as alias this, is kind of confusing

2018-07-27 Thread ag0aep6g via Digitalmars-d

On 07/27/2018 12:19 PM, Yuxuan Shui wrote:

On Friday, 27 July 2018 at 10:17:21 UTC, Yuxuan Shui wrote:

First, it surprised me that I can't index a struct like that. So:

struct A(T...) {
    alias S = T;
    alias S this;
}

alias B = A!(int, double);
B[0] x; // Actually an array

Then, it surprised me again, that I actually can index it, sometimes

static if (!is(B[0] == B[1]))
    pragma(msg, "Works!");

Why is this language like this :(


Oh no, is it just defining arrays in the is() statement, though?


Yup.


But wait, this works:

alias C = A!(1,2,3);
static if (C[0] < C[1])
    pragma(msg, "Ha!");


Looks like DMD decides that `C[0]` and `C[1]` can't be types in that 
situation, so it tries the alias this. That's in line with how alias 
this is supposed to work: only kick in when the code wouldn't compile 
otherwise.


Re: Bug? opIn with associative array keyed on static arrays

2018-07-22 Thread ag0aep6g via Digitalmars-d

On Sunday, 22 July 2018 at 19:42:45 UTC, Peter Alexander wrote:

void main() {
int[int[1]] aa;
aa[[2]] = 1;
assert([2] in aa);
}

---

This assertion fails in 2081.1. Is this a bug?


Definitely. Looks like `[2]` makes a dynamic array (length + 
pointer) and `in` reinterprets it as an `int[1]`.


More examples:


void main()
{
int[int[1]] aa = [[2]: 1];
assert([123, 456] in aa); /* Passes. Shouldn't even compile. 
*/


size_t[] dynarr = [1, 2, 3];
string[size_t[2]] aa2 = [[3, cast(size_t) dynarr.ptr]: 
"Wat."];
assert(*(dynarr in aa2) == "Wat."); /* Passes. Shouldn't even 
compile. */

}



Re: Copy Constructor DIP

2018-07-17 Thread ag0aep6g via Digitalmars-d

On 07/17/2018 03:03 PM, aliak00 wrote:
Can you explain a bit more here? How does having implicit as a compiler 
recognized UDA avoid breaking changes as opposed to it being implemented 
like @nogc/@safe (how are those implemented differently anyway?)


In a UDA `@implicit`, `implicit` is just a normal symbol. So the normal 
lookup rules apply. In particular, you can shadow an imported `implicit` 
with a local one:


--- object.d
enum implicit = 1; /* Actual implementation would be different. */

--- bar.d
/* invisible default `import object` here */
@implicit void f() {}
static assert(__traits(getAttributes, f)[0] == 1);
/* Passes. `object.implicit` is used. */

--- baz.d
/* invisible default `import object` here */
enum implicit = 2;
@implicit void f() {}
static assert(__traits(getAttributes, f)[0] == 2);
/* Passes. The local `implicit` is used. */

You can't do that with `@safe`, because `@safe` is not a UDA, and `safe` 
is not a symbol there. `@safe` is special syntax, recognized as a whole 
by the parser. No symbol lookup is happening.


You can see the difference if you change all occurrences of "implicit" 
to "safe" in that code. Won't work.


As for breakage, baz.d is working code today. With `@implicit` as a UDA, 
it keeps working in the same way. With `@implicit` as a new non-UDA 
attribute, it will change its meaning, and the assert will fail.


Re: Copy Constructor DIP

2018-07-16 Thread ag0aep6g via Digitalmars-d

On 07/16/2018 09:06 PM, Andrei Alexandrescu wrote:

On 7/14/18 11:26 AM, Jacob Carlborg wrote:

[...]
That's easily fixed by implementing a compiler recognized UDA. That 
would mean that it would only be a copy constructor if "implicit" is 
defined in core.attribute. This would also avoid any special syntax in 
the parser. The already existing @selector is implemented like this.


Affirmative. We're going that route, similar to "@safe" and "@nogc".


@safe and @nogc are not compiler recognized UDAs. If you implement 
@implicit like them, then you're not doing what Jacob suggests.


Re: Copy Constructor DIP

2018-07-12 Thread ag0aep6g via Digitalmars-d

On 07/12/2018 03:40 PM, Andrei Alexandrescu wrote:

On 07/10/2018 04:58 PM, Manu wrote:

[...]

1. Explain the need and reasoning behind `@implicit`.


Razvan: I think it would help to explain that the attribute is necessary 
to avoid changing semantics of existing code. Thanks.


You're still potentially changing the semantics of existing code. 
`@implicit` can be a UDA today:



enum implicit = 0;
struct C
{
@implicit this(ref C another) {}
}


Today, that's a normal constructor. With the DIP, it becomes a copy 
constructor.


Re: Normalize void

2018-07-10 Thread ag0aep6g via Digitalmars-d

On 07/10/2018 11:56 AM, Yuxuan Shui wrote:

Possible alternatives:

* struct Void {}. Takes 1 byte, not as ideal
* alias Void = AliasSeq!(). Doesn't work as template argument. i.e.
   SomeTemplate!Void; // actually become SomeTemplate!()


What about `void[0]`? It's a proper type. You can declare a field with 
it. Size is 0.


Re: Anyone can contact Dmitry Olshansky?

2018-07-01 Thread ag0aep6g via Digitalmars-d

On 07/01/2018 08:00 AM, Ali Çehreli wrote:
Apparent from uncharacteristic messages from Dmitry's account to 
multiple destinations recently, I suspect his gmail account has been 
compromised.


Could also be a psychotic episode or some such. The incoherent rambling 
doesn't seem to be just bad English. You've got stuff like "I can save 
the world" in there, which sounds more like mental illness than an 
imposter to me.


Re: tuple of delegates requires explicit type

2018-06-20 Thread ag0aep6g via Digitalmars-d

On Wednesday, 20 June 2018 at 15:19:29 UTC, DigitalDesigns wrote:
See, what the compiler is not doing is realizing that a lambda 
can be implicitly cast to any other lambda with the same 
signature. If it understood that then it should have no problem 
with casting the tuple implicitly.




Tuple!(void function() pure nothrow @nogc @safe)
Tuple!(void delegate())


a function can always be cast to a delegate(delegate is a super 
type as it inherits function in type logic)


Functions (or rather, function pointers) do not convert 
implicitly to delegates in D. `void delegate()` is not a 
supertype of `void function()` in D.


The issue is that a delegate call passes the context pointer in a 
spot where a function call passes a parameter. So a function 
pointer can't just be reinterpreted as a delegate.


The conversion could be made to work by automatically wrapping 
the function in a delegate. Walter is understandibly against that 
because of the performance implication. Alternatively, it might 
be possible to change the delegate ABI so that the parameters are 
passed the same as for function calls. Older thread about that: 
https://forum.dlang.org/post/ofc0lj$2u4h$1...@digitalmars.com


Re: Is this a bug with __traits(derivedMembers)?

2018-06-12 Thread ag0aep6g via Digitalmars-d

On Tuesday, 12 June 2018 at 13:40:45 UTC, bauss wrote:

See the following: https://run.dlang.io/is/uQ21PH

(I have tried with allMembers too.)

It's like it won't pick up the member that is added using a 
mixin at line 22.


```
mixin("ubyte[" ~ to!string(__PADDING_SIZE__) ~ "] __PADDING__" 
~ member  ~ ";");

```


It's because the identifier starts with two underscores. Such 
identifiers are reserved for internal use, and apparently they're 
ignored by some (all?) __traits.


I'm not sure if this can count as a bug, but it doesn't look just 
fine either.


Smaller test case:


struct S
{
int foo, __bar, baz;
}
pragma(msg, __traits(allMembers, S)); /* tuple("foo", "baz") */



Re: Semantic change from 2.078.3 to 2.079.0

2018-05-23 Thread ag0aep6g via Digitalmars-d

On 05/23/2018 11:21 AM, Márcio Martins wrote:
Hi, recently we tried to upgrade DMD from 2.078.3 to 2.080 and found an 
unexpected semantic change.


Consider this program:

import std.traits;
enum X { Y = "z" };
alias T = typeof(X.Y);

pragma(msg, is(T == enum));
pragma(msg, isSomeString!T);
void main() {}`

Output in DMD <= 2.078.3:
true
true

Output in DMD >= 2.079.0:
true
false

This silent change is really nasty, and causing all sorts of breakages.
Was this a bug-fix, and if so, should we expect the new behavior to stick?


In the changelog:

https://dlang.org/changelog/2.079.0.html#std-traits-issomestring


Re: Found on proggit: Krug, a new experimental programming language, compiler written in D

2018-04-26 Thread ag0aep6g via Digitalmars-d

On 04/26/2018 09:11 PM, H. S. Teoh wrote:

Fair enough.  But if that's all there is to it, then why bring it up
here?  Not that I object, mind you, but it just seemed kinda random, why
pick this one hobby project over any other, when there are tons of new
languages out there being made almost every day.


"compiler written in D"


Re: Frustrated with dmd codegen bug

2018-04-24 Thread ag0aep6g via Digitalmars-d

On 04/24/2018 08:53 PM, H. S. Teoh wrote:

Yesterday afternoon I ran into a performance issue in one of my D
projects, and thought, "well, it's simple, just compile with -profile,
identify the hotspot, optimize".  Unfortunately, doing that triggered a
latent codegen bug in -O that randomly causes runtime segfaults,
basically halting all progress.  I spent all morning today to reduce the
code in order to identify the codegen bug:

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


Another one for my collection of bugs related to the bt instruction [1]. 
I have an open PR to fix one of those [2], but maybe the whole 
optimization should just be disabled until the issues are fixed.


[...]

At this point, I'm *seriously* tempted to stop following dmd development
completely and just stick with LDC releases for my D projects. :-(


Very understandable. DMD has too damn many wrong-code bugs.


[1] https://issues.dlang.org/show_bug.cgi?id=18750
[2] https://github.com/dlang/dmd/pull/8142


Re: Feature to get or add value to an associative array.

2018-04-20 Thread ag0aep6g via Digitalmars-d

On Friday, 20 April 2018 at 09:24:26 UTC, Jonathan M Davis wrote:
The compiler assumes that a pointer is valid when determining 
whether code is @safe.

[...]
Basically, it verifies the @safety of pointers when they're 
created and then assumes that they're @safe after that.


Can't it do the same for ref returns? Unsafe stuff like returning 
a ref to a local is already disallowed, just like returning a 
pointer to a local. So the compiler checks the safety on 
creation, at least in some cases.


So, passing around a pointer is perfectly @safe, whereas taking 
the address of a ref return value to get a pointer is not.


It's still not clear to me how taking the address of a ref return 
is necessarily less safe than using a returned pointer. Do you 
maybe have an example in code that shows the difference?


It seems to me that refs and pointers are very much equivalent. I 
should always be able to turn one into the other.


Re: Feature to get or add value to an associative array.

2018-04-20 Thread ag0aep6g via Digitalmars-d

On 04/20/2018 10:24 AM, Nick Treleaven wrote:

On Wednesday, 18 April 2018 at 16:47:50 UTC, ag0aep6g wrote:

You can get a pointer from the ref return:

    Value* p = &aa.slot("key", { inserted = true; return Value.init; });


This is not @safe, even with -dip1000:

Error: cannot take address of ref return of f() in @safe function main


Hm. Do you know why that's not allowed? I can't see how it would be less 
safe than returning a pointer, and I can't find a mention of it in DIP 
1000 [1]. Maybe it's just a case of incomplete/buggy implementation?



[1] https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md


Re: Feature to get or add value to an associative array.

2018-04-18 Thread ag0aep6g via Digitalmars-d

On 04/18/2018 11:41 AM, Nick Treleaven wrote:

How do you implement this if the function returns with ref:

bool inserted;
auto p = aa.slot("key", &inserted);
if (inserted) {
   ...
   // set *p
}
else {
   // read *p
   ...
   // set *p
}


You can get a pointer from the ref return:

Value* p = &aa.slot("key", { inserted = true; return Value.init; });

Then do with the pointer whatever you want.


Re: isInputRange is false for non-copyable types

2018-04-15 Thread ag0aep6g via Digitalmars-d

On 04/16/2018 06:15 AM, Shachar Shemesh wrote:
Input ranges provide no guarantees about copying the range itself. If 
you do it and expect *anything* (which it seems you do), you have a bug. 
If you need to copy the range itself, you absolutely need to require a 
forward range.


A forward range with ref front absolutely promises that both iterations 
reference the same elements.


I find myself sincerely hoping that you are making these examples up in 
order to win this discussion turned into an argument for some reason, 
instead of the way phobos is actually written, because if you're right 
phobos is *broken*.


The good news is that if Phobos is broken, this is a great way to flush 
out the places it's broken. Let's add UTs calling all Phobos functions 
accepting input ranges (as opposed to forward ranges) with non-copyable 
ranges (i.e. - the range itself is non-copyable) and fix the compilation 
errors. This shouldn't take more than a few days to do.


I'm currently attempting something similar: fix Phobos to work with 
RefRange. RefRange is copyable, but assignment is weird. Assignment 
isn't part of the range interface, so I'm replacing it with `move`:


https://issues.dlang.org/show_bug.cgi?id=18657
https://github.com/dlang/phobos/pull/6346

That PR doesn't fix all of Phobos, it's just a start. Going over all of 
Phobos (and getting it merged) might take a while.


Thinking about it, those `move`s probably fix the code for non-copyable 
ranges as well. There might be considerable overlap here.


Re: d2sqlite3 db.run, where lies the bug?

2018-04-11 Thread ag0aep6g via Digitalmars-d

On 04/11/2018 04:08 AM, Ralph Amissah wrote:

Generous, I merely stumbled on it and shouted out, you fixed it. I would be
grateful if you please file the bug and your fix.


There you go: https://github.com/biozic/d2sqlite3/pull/43


Re: d2sqlite3 db.run, where lies the bug?

2018-04-10 Thread ag0aep6g via Digitalmars-d

On 04/10/2018 08:04 PM, Ralph Amissah wrote:

The exact location of problem may be provided in the error statement
"core.exception.UnicodeException@src/rt/util/utf.d(292): invalid
UTF-8 sequence".


[...]

Mock problem string with test code follows (d2sqlite3 required):


[... code ...]

A more minimal test case, reduced from your code:


module d2sqlite3_utf8.issue;
import d2sqlite3;
void main() {
  string[] info_tag = ["pass", "fault"];
auto db = Database(":memory:");
string _sql_statement = `SELECT '’’';`;
db.run(_sql_statement);
db.close;
}


From the exception's stack trace we see that 
`d2sqlite3.internal.util.byStatement(immutable(char)[]).ByStatement.findEnd` 
is the deepest non-Phobos function involved. So that's a good first spot 
to look for a bug. Let's check it out.


https://github.com/biozic/d2sqlite3/blob/2e8211946ae0e09646d561aeae1361a695adcc17/source/d2sqlite3/internal/util.d#L64-L83

And indeed, there's a bug in these lines:


auto tail = sql[pos .. $];
immutable offset = tail.countUntil(';') + 1;
pos += offset;


`pos` is used to slice the string `sql`. That means, `pos` is 
interpreted as a number of UTF-8 code *units*. But then the result of 
`countUntil` is added. `countUntil` counts code *points*. So a number of 
code points is mistaken as a number of code units. That means the next 
slicing can be incorrect and split up a multibyte sequence. And then 
`countUntil` will complain about broken UTF-8.


This can be fixed by letting `countUntil` operate on count code units 
instead:



import std.utf: byCodeUnit;
immutable offset = tail.byCodeUnit.countUntil(';') + 1;


If you want, you can make a bug report or a pull request with the fix. 
Otherwise, if you're not up to that, I can make one.


[...]

   - DMD64 D Compiler v2.074.1


That's rather old. I'd recommend updating if possible.


Re: Deprecating this(this)

2018-04-04 Thread ag0aep6g via Digitalmars-d

On 04/04/2018 12:37 PM, Steven Schveighoffer wrote:
With structs, we have the possibility of initialization via different 
mechanisms: constructor, postblit, .init. All of these are supported by 
the struct member, but currently you can only invoke postblit if you are 
in a postblit. And only at the beginning. I would like to see more 
flexibility for copying.

[...]

For structs, using .init is a valid initialization, so it's completely
different from classes, where a constructor MUST be invoked. Indeed,
there is no mechanism to require calling struct member constructors in 
the owner's ctor.

[...]

To paraphrase your point: We should be able to initialize a member with 
.init or by calling its constructor (over .init). We should not be 
forced to initialize it with its postblit.


Makes sense. But I see one tricky case: Can I also choose to use the 
blitted value of the member without calling its postblit? I'd say that 
can't be allowed.


So the compiler would have to identify that case and reject it. And now 
we're in uncharted territory. As far as I see, this is not something 
that constructors do (struct or class). They happily accept any .init 
value. But postblits can't accept any blitted value. So we can't say: 
"Just do what constructors do." We have to come up with new rules.


But we don't want to come up with new rules, we want to say: "Just do 
what constructors do." So we require the member postblit, and we say 
that the outer postblit operates on the resulting value like a 
constructor operates on .init.


And then we see that it breaks the type system, and that any analog 
behavior of constructors just means that constructors/.init are broken, too.


[...]

struct S
{
 int x;
 this(this) immutable
 {
 x = 42; /* First write. */

[...]

 }
}

struct T
{
 S s;
 this(this) immutable
 {
 s = S(13); /* Second write. Breaking immutable? */


Of course this doesn't compile, because s is considered immutable by 
now.


It doesn't compile, because this(this) is a broken mess currently.

The first write doesn't compile either. Obviously, with a properly 
implemented immutable this(this), you would at least be allowed to write 
once.


With mutable(!) `this(this)`s, both writes are accepted.

What I was saying is that we can't allow postblit to modify data 
that has already been postblitted, because of the reason this example is 
showing.


Still, I'd like to have a more explosive example. The breakage here is 
very localized, and could possibly be defined away somehow. Like: 
"Unique immutable data is considered 'raw' in constructors and postblit 
functions. That means, the data can be mutated. Only when the 
constructor/postblit returns does it become 'cooked' and truly immutable."


[...]



[...]
I don't think you should be able to write to the same field multiple 
times in an immutable/const constructor. If so, that's a bug.


Are you counting .init as a write, or is a constructor allowed to build 
on that?



import std.stdio;
struct S
{
int x = 1;
int y = 3;
this(int dummy) immutable
{
writeln(x); /* 1 */
++x; /* Breaking immutable? */
writeln(x); /* 2 */

++y; /* Breaking immutable even though y hasn't been printed 
yet? */

writeln(y); /* 4 */
}
}
void main()
{
auto s = immutable S(0);
}


I think those increments could be considered breaking immutable. Maybe 
they must be.


If this were to be outlawed, I'd agree a constructors and postblits are 
fundamentally different.


Re: Deprecating this(this)

2018-04-03 Thread ag0aep6g via Digitalmars-d

On 04/03/2018 10:51 PM, Steven Schveighoffer wrote:

On 4/3/18 4:26 PM, ag0aep6g wrote:

[...]
If there's a problem with running two postblits on the same field, 
then I think constructors probably have similar issue. I'm having a 
hard time finding a good example, though. One where we could break 
immutable in an obvious way or some such.


You may NOT want to run a postblit on the member. If all you are going 
to do, for example, is reassign a variable, then running the postblit, 
and then the destructor, just so you can overwrite it is pointless.


Same with class constructors: You may not want to run `super` when 
you're just going to overwrite what it did. But the language doesn't 
give you a choice. It'll be called one way or another.


I'm not saying that imitating how constructors work will make the best 
possible copying mechanism. Something else might be superior in every 
way. It's just that so far the arguments against a constructor-like 
postblit also seem to apply to constructors as they are implemented.


So I'm thinking that a postblit modeled after constructors could work as 
well as they do. But maybe the real takeaway is that constructors don't 
work very well, and shouldn't be imitated.


But more importantly, if the postblit of the member does something crazy 
like stores a reference to itself as an immutable elsewhere, and then 
the compiler allows overwriting, we now have problems.


I'd love to see an example of this in code. The best I can come up with 
would be something like this (doesn't compile):



import std.stdio;

immutable(int)* p;

struct S
{
int x;
this(this) immutable
{
x = 42; /* First write. */
.p = &this.x;
writeln(p, " ", *p); /* Prints some address and 42. */
}
}

struct T
{
S s;
this(this) immutable
{
s = S(13); /* Second write. Breaking immutable? */
writeln(p, " ", *p); /* Same address, but 13. */
}
}

void main()
{
immutable T foo;
immutable bar = foo;
}


But that's essentially the same as the class example I posted. `*p` 
would only change values during the postblit run. Just like a 
constructor chain can write to the same field multiple times.


That's kinda iffy, but I can't find a way to demonstrate some real, 
obvious damage.


I think the better mechanism for immutable copying would be to have a 
copy constructor that starts off with T.init, and is passed the object 
to copy from. That seems to be a direction Andrei is considering.


No objection from me. If Andrei et al. can find a better solution, great.


Re: Deprecating this(this)

2018-04-03 Thread ag0aep6g via Digitalmars-d

On 04/03/2018 08:57 PM, Andrei Alexandrescu wrote:
Well... not really. This is because .init is really an inert state - 
null indirections, no state allocated etc.


.init can have non-null indirections:

struct S { int[] a = [1, 2, 3]; }
static assert(S.init.a.ptr !is null); /* passes */

But maybe it shouldn't. It leads to problems with immutable, because the 
same .init with the same `a` is used for both mutable and immutable 
objects. https://issues.dlang.org/show_bug.cgi?id=10376


As far as I see, a const/immutable postblit working like a constructor 
wouldn't have that particular problem, because the copy is always made 
from another const/immutable object, so there wouldn't be aliasing with 
mutable data.


But there might of course be other problems with indirections, which I 
don't see right now. I'd love to see any examples, though. They probably 
reveal weaknesses in .init/constructors, too.


Makes typechecking easy, and 
calling constructor on top of .init is what happens already. In 
contrast, the postblit situash is very different - the fields already 
contain "interesting" data, allocated resources etc. Calling a 
constructor on top of that is not defined.


Well, the idea would be to define it. But if postblit goes away for 
other reasons anyway (like the atomic copy thing, or another mechanism 
being simply superior), then there's no point in pursuing this, of course.


Re: Deprecating this(this)

2018-04-03 Thread ag0aep6g via Digitalmars-d

On 04/03/2018 05:13 PM, Steven Schveighoffer wrote:
Unfortunately, I found out that it's not just "pre-filled with some 
values". Member postblits are run before the containing postblit.


https://run.dlang.io/is/mt6eGa

So this means, the data that is available to the postblit has already 
been processed.


There's a similar situation with constructors: A constructor can call 
another constructor, which can lead to double initialization of fields.


Example:


class C
{
int x;
this() immutable
{
this(42); /* Initializes x. */
x = 13; /* Breaking immutable, or ok? */
}
this(int x) immutable
{
this.x = x;
}
}


If there's a problem with running two postblits on the same field, then 
I think constructors probably have similar issue. I'm having a hard time 
finding a good example, though. One where we could break immutable in an 
obvious way or some such.


It would only make sense to allow const postblits to have the same 
constructor mechanism if the members all had no postblits.


Less drastically, we could also disallow writing to those fields that 
have their own postblit.


The analog with constructors would be disallowing writing to fields that 
have already been initialized by an implicit `super` call. Actually, 
that seems to be how it works, kinda-sorta:



class C
{
int x;
}

class D : C
{
int y;
this() immutable
{
y = 1; /* accepted */
x = 2; /* Error: cannot modify this.x in immutable function */
}
}


Obviously, DMD doesn't check what C's constructor actually does (because 
it generally can't check that). It just considers initializing x to be 
C's responsibility.


Re: Deprecating this(this)

2018-04-03 Thread ag0aep6g via Digitalmars-d
On Tuesday, 3 April 2018 at 12:52:00 UTC, Andrei Alexandrescu 
wrote:

On 04/03/2018 07:36 AM, ag0aep6g wrote:
For constructors, we say that the first assignment is actually 
initialization. The compiler might or might not put the .init 
value down before calling the constructor. Doesn't matter, 
because the constructor will overwrite it anyway, and nothing 
of value is lost.


What happens in fact is you are guaranteed the .init value is 
there. Much later, well after semantic checking, the backend 
optimizer removes dead assignments on primitive data.


So constructors, including const/immutable ones, basically work 
the same as postblit already? You get an object pre-filled with 
some values, and then you can "initialize" the fields some more 
if you want.


[...]

What if the user code reads the value?

* Often people use this(this) to bump a reference count a la 
"if (pcnt) ++*pcnt;"


Because of the indirection, that can only be done in a mutable 
`this(this)`. Otherwise you violate the const/immutable guarantee 
of the original object.


* People may pass the field by reference to an opaque function. 
What type does the field have?


Fully const. Same as in a constructor.

[...]

In case (1) things can get quite confusing. Inside a postblit,

field = TypeOfField(100);

is a call to the constructor, whereas

field = TypeOfField(field.x + 100);

is a call to the assignment operator.


A const constructor currently accepts both of those. So the 
second one can apparently be considered "initialization" as well? 
Or should a const constructor not be allowed to do that?


Re: Deprecating this(this)

2018-04-03 Thread ag0aep6g via Digitalmars-d

On 04/03/2018 09:39 AM, Kagamin wrote:

On Monday, 2 April 2018 at 14:42:17 UTC, ag0aep6g wrote:
The way it works in a const constructor is that `this.foo = bar;` is 
considered initialization, not assignment.


Do you mean the spec? Andrei complained about implementation.


Andrei complained about both, no? His words: "Too many bugs in design 
and implementation." Design = spec.


I'm also talking about the implementation. `this.foo = bar;` in a 
constructor is at least not normal assignment. If foo has opAssign, that 
won't be called.



Const constructors are already implemented as needed for postblit.


Maybe. But we can't explain the special assignment semantics with it 
being initialization.


Or can we?

For constructors, we say that the first assignment is actually 
initialization. The compiler might or might not put the .init value down 
before calling the constructor. Doesn't matter, because the constructor 
will overwrite it anyway, and nothing of value is lost.


We can do the same with the postblit function: First assignment is 
actually initialization. When the compiler sees that the postblit 
function initializes a field, it can skip that field when blitting. But 
it can also just blit the whole struct, because it doesn't matter if the 
value just gets overwritten.


In other words, a postblit function can either:

1) use the blitted value as a starting point, like a constructor can use 
the .init value, or it can

2) initialize the field itself.

Would make perfect sense to me.


Re: What's up with ddoc on dlang.org?

2018-04-02 Thread ag0aep6g via Digitalmars-d

On 04/02/2018 11:36 PM, Steven Schveighoffer wrote:
Was just perusing dlang's library documentation, and here is the 
description it has for std.experimental.allocator.make:


Dynamically allocates (using ) and then creates in the memory 
allocated an object of type T, using (if any) for its initialization. 
Initialization occurs in the memory allocated and is otherwise 
semantically the same as T(). (Note that using .!(T[]) creates a 
pointer to an (empty) array of Ts, not an array. To use an allocator 
to allocate and initialize an array, use .makeArray!T described below.)


Seems there's a few things missing here? What's happening?


Looks like a mistake that happened with this change:
https://dlang.org/changelog/2.079.0.html#fix18361

PR to fix it:
https://github.com/dlang/dlang.org/pull/2326


Re: Deprecating this(this)

2018-04-02 Thread ag0aep6g via Digitalmars-d

On Monday, 2 April 2018 at 14:24:20 UTC, Nicholas Wilson wrote:
On Monday, 2 April 2018 at 14:07:21 UTC, Steven Schveighoffer 
wrote:

On 4/1/18 10:34 AM, ag0aep6g wrote:

[...]
I'm not so sure if that's fundamental. Can't we just say that 
the copy is head-mutable at the time when the postblit 
function is called, and it only becomes fully const after 
that?

[...]
Yes, precisely what I had been arguing here: 
https://issues.dlang.org/show_bug.cgi?id=18417#c5

[...]
Andrei did post an example where treating the designation as 
mutable, stuffing references to mutable data into is and then 
treating it as immutable leaves you with an immutable reference 
to immutable data.


This one?


int[] sneaky;
struct A
{
private int[] innocent;
this(this)
{
sneaky = innocent;
}
}
void main()
{
immutable a = A([1, 2, 3]);
auto b = a;
sneaky[1] = 42; // oops
import std.stdio;
writeln(a.innocent); // ops
}


That wouldn't be possible if `innocent` were only head-mutable in 
the postblit function, instead of fully mutable as it is 
currently (bug).


`innocent` would be typed as `immutable(int)[]`, and you could 
not assign it to the fully mutable `sneaky`.


However i think that loophole is fixed if you only allow 
assignment to const/immutable from a pure postblit.


Still must be head-mutable only. With fully mutable, you can 
mutate data that is seen as immutable elsewehre, even if the 
postblit function is pure:



struct S
{
int* x;
this(this) pure { *x = 13; }
}
void main()
{
auto s = immutable S(new int(42));
auto s2 = s;
assert(*s.x == 42); /* fails; immutability has been broken */
}


Issue 18357 covers both Andrei's example, and this one.
https://issues.dlang.org/show_bug.cgi?id=18357


Re: Deprecating this(this)

2018-04-02 Thread ag0aep6g via Digitalmars-d

On Monday, 2 April 2018 at 14:01:22 UTC, Kagamin wrote:
On Sunday, 1 April 2018 at 14:31:24 UTC, Andrei Alexandrescu 
wrote:
1. For immutable objects, typechecking in the presence of 
successive modifications of data (first assignment by the 
compiler, then modification by the user) is very difficult if 
not impossible. I don't know how to do it. The single 
initialization model (raw/cooked) used currently in regular 
immutable constructors works reasonably well and is robust.


Do the same as in const constructor.


The way it works in a const constructor is that `this.foo = bar;` 
is considered initialization, not assignment.


In a postblit function, we can't say it's initialization, because 
the field already has a value that can't be ignored.


Re: Did Walter's pure optimization ever make it into dmd?

2018-04-02 Thread ag0aep6g via Digitalmars-d

On 04/02/2018 10:52 AM, Dennis wrote:
```For these examples, I'll use the D programming language compiler that 
is currently under development. (...)

But what if bar is pure?

pure int bar(int);

int foo(int i)
{
     return bar(i) + bar(i);
}

Now the assembler output is:

     push    EAX    ; save argument i on stack
     call    bar    ; call bar(i)
     add EAX,EAX   ; double result
     pop ECX    ; clean stack
     ret  ; return to caller

bar(i) is called only once```

I've checked whether multiple calls to pure functions get optimized, and 
it seems like they *never* do. I've tried different versions of dmd with 
optimizaiton flags on/off, and also LDC/GDC.


The function also needs the `nothrow` attribute. And you have to compile 
with `-O -release`.


https://run.dlang.io/is/GWnUPH


Re: Deprecating this(this)

2018-04-01 Thread ag0aep6g via Digitalmars-d
On Sunday, 1 April 2018 at 14:31:24 UTC, Andrei Alexandrescu 
wrote:
Now, if we fix various bugs in this(this) by virtually 
redefining it, then we'll break a lot of code in a lot of ways. 
To wit, we fixed a small issue and it already created problems: 
https://github.com/dlang/dmd/pull/8032. That didn't contribute 
to the decision but is quite illustrative.


Yeah, I absolutely see value in starting fresh with different 
syntax, even if you were just implementing the same postblit idea 
again.



I found two fundamental flaws with this(this):

1. For immutable objects, typechecking in the presence of 
successive modifications of data (first assignment by the 
compiler, then modification by the user) is very difficult if 
not impossible. I don't know how to do it. The single 
initialization model (raw/cooked) used currently in regular 
immutable constructors works reasonably well and is robust.


I'd think that just letting the const/immutable postblit function 
see head-mutable fields would work.


But maybe that's way harder to implement than writing it down the 
forum. If that's so, then fair enough. I know that I won't be 
able to implement it.


2. For shared objects, the part done by the compiler and the 
part done by this(this) should be synchronized together. This 
makes it impossible for the user to e.g. define a struct that 
gets copied atomically.


Interesting. I've got no armchair expertise on this one.

There'd be an additional issue - this(this) is non-templated, 
which requires combinatorial additions when qualifiers are 
present on the source or destination side.


I think I don't understand this one. Could you give an example in 
code?


Are you saying that we'd need to define all these:

this(this)
this(this) const
this(this) immutable

even if they do the same thing? Wouldn't `this(this) inout` take 
care of this?


Re: Deprecating this(this)

2018-04-01 Thread ag0aep6g via Digitalmars-d

On Sunday, 1 April 2018 at 13:37:43 UTC, Jonathan M Davis wrote:
One issue is that postblit constructors fundamentally don't 
work with const. The problem is that a postblit constructor 
works by copying the object and _then_ mutating it, and you 
can't mutate a const object.


I'm not so sure if that's fundamental. Can't we just say that the 
copy is head-mutable at the time when the postblit function is 
called, and it only becomes fully const after that?


The destination can't be const/immutable already, or you wouldn't 
be able to write there anyway.


Re: Deprecating this(this)

2018-04-01 Thread ag0aep6g via Digitalmars-d

On 04/01/2018 03:08 AM, Andrei Alexandrescu wrote:

On 3/31/18 8:32 PM, H. S. Teoh wrote:

[...]

What exactly is it about this(this) that blocks us from doing that?


See the updated docs. Too many bugs in design and implementation.


Removing this(this) is going to be a huge breaking change far bigger
than, say, removing autodecoding ever will be.


We're not removing it as much as evolving it: we define an alternate 
copying mechanism, and once that is in tip-top shape, we deprecate 
this(this).


Is there a fundamental flaw in the postblit idea, or are you just going 
to give postblit a new syntax, and try to avoid all the issues that 
`this(this)` currently has?


If there's a fundamental flaw, I'd be interested in what it is. I can't 
make it out in your additions to the spec, if it's in there. I can see 
that `this(this)` is  a mess, but it also looks like a lot could be 
fixed. For example, how it interacts with const/immutable is ridiculous, 
but that could probably be fixed.


If you're just going for a clean slate, I can see the appeal. You avoid 
dealing with the hard breakage that fixing `this(this)` would most 
probably bring.


Re: Recursive attribute for virtual functions?

2018-03-27 Thread ag0aep6g via Digitalmars-d

On 03/28/2018 01:34 AM, arturg wrote:

you can call them with __traits(getOverloads, T, "name")[index];

you can overload on types attributes and linkage, but seems like you can 
only merge overloads based on types.


I don't think there's value in allowing overloads that can only be 
called via __traits.


Looks like this is an old issue [1] that is currently being fixed. 
run.dlang.io's "beta" and "nightly" compilers don't accept such 
overloads [2]. But I can't reproduce that locally. The fix has 
apparently been reverted because it needs more work.



[1] https://issues.dlang.org/show_bug.cgi?id=2789
[2] https://run.dlang.io/is/qlyMti


Re: Recursive attribute for virtual functions?

2018-03-27 Thread ag0aep6g via Digitalmars-d

On 03/28/2018 12:19 AM, arturg wrote:

shouldn't it create a overload?


I don't think so. As far as I know, you can't overload on attributes.

[...]

but this works:

class A
{
     void talk() {}
}

class B : A
{
     alias talk = A.talk;
     void talk(int) {}
}


Because different parameters make overloads.


this works also:

class C
{
     void talk()@system {}
     void talk()@safe {}
}


DMD might accept that, but I don't think it works in a meaningful way. 
How do you call the @system one?


Looks like the @safe one will always be called, even from @system code:


import std.stdio;

void talk() @system { writeln("@system"); }
void talk() @safe { writeln("@safe"); }

void main() @system
{
talk(); /* Prints "@safe". */
}



Re: Recursive attribute for virtual functions?

2018-03-27 Thread ag0aep6g via Digitalmars-d

On 03/27/2018 11:10 PM, 12345swordy wrote:

Shouldn't it give a warning then?


I wouldn't mind a warning, or even an error. Putting both @safe and 
@system directly on a function is an error, too.


Re: Recursive attribute for virtual functions?

2018-03-27 Thread ag0aep6g via Digitalmars-d

On 03/27/2018 11:02 PM, 12345swordy wrote:

Then explain this then.
https://run.dlang.io/is/S2KLs5


B.talk is @safe. The compiler ignores the @system attribute on B.talk, 
because A.talk's @safe attribute takes precedence.


Re: Recursive attribute for virtual functions?

2018-03-27 Thread ag0aep6g via Digitalmars-d

On 03/27/2018 10:39 PM, 12345swordy wrote:

class A
{
     @recursive @safe void talk()

[...]

}
class B : A
{
     override void talk() // @safe attribute added by recursive 
attribute and can not be removed

[...]

}


It already works like that. B.talk is @safe, and you can't make it 
@system. You can mark it as @system, that gets overridden by A.talk's @safe.


https://run.dlang.io/is/BlH8bp


Re: Must ranges support `r1 = r2;`?

2018-03-25 Thread ag0aep6g via Digitalmars-d

On 03/25/2018 01:49 AM, Jonathan M Davis wrote:

assignment really isn't part of the range API. I don't think that any of the
range traits even test that assignment works on any level. So, it could be
argued that generic, range-based functions simply shouldn't ever be
assigning one range to another.

So we have to remove all range assignments from generic code. Ugh.

The first three: https://github.com/dlang/phobos/pull/6346


Re: Must ranges support `r1 = r2;`?

2018-03-24 Thread ag0aep6g via Digitalmars-d

On 03/25/2018 12:02 AM, Jonathan M Davis wrote:

auto range2 = range1; // now, range1 can't be used until it's assigned to
range2.popFront();

range1 = range2; // now, range2 can't be used until it's assigned to
range1.popFront();

And I don't think that RefRange violates that.


What RefRange violates is the assumption that range1 gets discarded, and 
that it simply gets overwritten by range2.


Note that `auto range2 = range1;` does not have that problem, because 
it's initialization, not assignment. It doesn't call RefRange's funky 
opAssign.


The various misbehaving Phobos functions assume that assignment works 
the same as initialization. But it doesn't with RefRange.


[...]

As far as save goes, save is supposed to create an independent copy to
iterate, and RefRange's documentation says that that's what it does, meaning
that passing a RefRange to a function that uses the forward range API
probably isn't very useful, but it would do what a forward range is supposed
to do. Whether the actual implementation does that properly on not, I don't
know - I'd have to study it - but per the documentation, it's at least
designed to do the right thing with save.


RefRange.save works correctly. opAssign is the problem.


Re: Must ranges support `r1 = r2;`?

2018-03-24 Thread ag0aep6g via Digitalmars-d

On 03/24/2018 11:36 PM, Simen Kjærås wrote:

void main()
{
     import std.range;
     import std.stdio;

     string s = "foo";
     auto r = refRange(&s);

     auto r2 = r;
     r2 = r2.save;
     /* Surprising: Effectively just does `s = s;` (i.e., nothing). */

     r2.popFront();
     writeln(r); /* Surprising: Prints "oo". */
}

None of this is surprising. When you call r2.popFront(), it's being 
forwarded to s.popFront. That's what refRange does, it's what it's 
supposed to do, and it's the only thing it could sensibly do.


I think it's surprising. It works as intended and as documented, but 
it's surprising. Note that the behavior is different when you change


auto r2 = r;
r2 = r2.save;

to

auto r2 = r.save;

`.save` actually makes a new slice that can be popped independently from 
`s`. But the assignment throws that independent slice away.



This is conceptually what refRange does:

struct RefRange(R) {
     R* innerRange;
     this(R* innerRange) {
     this.innerRange = innerRange;
     }
     void popFront() {
     innerRange.popFront();
     }
     @property auto front() {
     return innerRange.front;
     }
     @property bool empty() {
     return innerRange.empty;
     }
}


That's all fine. You're missing the interesting bit: opAssign. `save` 
might also be interesting, but the actual `save` is perfectly fine.


[...]

So when you do this:

     string s = "foo";
     auto r = refRange(&s).group;
     writeln(r.save);

r.save is going to create a new Group range, which contains a RefRange, 
which ultimately points to s. writeln() then repeatedly calls 
popFront(). This mutates s, as specified above.
That's not how it should be. A saved range should be iterable 
independently from the original. That's the point of `.save`. If that's 
not possible, `.save` should not be there.


You're implying that a saved RefRange points to the same range as the 
original. That's not true. RefRange.save saves the underlying range and 
lets the new RefRange point to that. This is correct. The two ranges can 
be iterated independently.


It's inside `Group` that things get messed up. There you have this 
innocent looking implementation of `save` [1]:


@property typeof(this) save() {
typeof(this) ret = this;
ret._input = this._input.save;
ret._current = this._current;
return ret;
}

The problem is in the line `ret._input = this._input.save;`. That calls 
RefRange.opAssign. If you refactor the code to avoid opAssign, saving 
works properly. For example:


private this(typeof(_input) inp, typeof(_current) cur)
{
this._input = inp; /* Initialization, not assigment. */
this._current = cur; /* Ditto, but doesn't matter. */
}
@property typeof(this) save() {
return typeof(this)(this._input.save, this._current);
}

Note that it calls `_input.save` just the same as before. The code only 
avoids RefRange.opAssign.


[...]
The 'chain', 'choose', and 'cycle' examples are an effect of strings not 
being random access ranges. I'm uncertain if we should call this a bug, 
but I agree the behavior is unexpected, so we probably should.


I don't think random access has anything to do with this.

The splitter example is of course a bug. The crash, that is. The 
expected behavior is that the first writeln prints [foo, ar], which it 
does, and that the second print [].


Again, I don't agree. You're effectively saying that saving a RefRange 
isn't possible. If that were so, it simply shouldn't have a `save` 
method. But the `save` method works perfectly fine. It's Phobos 
(accidentally) calling RefRange.opAssign that breaks things.



[1] 
https://github.com/dlang/phobos/blob/3225b19c9bae4b7e8d7a93d2d8c22c94b2a1a6c5/std/algorithm/iteration.d#L1505-L1510


Re: Must ranges support `r1 = r2;`?

2018-03-24 Thread ag0aep6g via Digitalmars-d

On 03/24/2018 10:57 PM, H. S. Teoh wrote:

On Sat, Mar 24, 2018 at 10:44:35PM +0100, ag0aep6g via Digitalmars-d wrote:

[...]

Short version: With two `std.range.RefRange`s, `r1 = r2;` does not
what other Phobos code expects.

[...]

Short answer: if r1=r2 is meant to save the current position in the
range, that's wrong; it should be r1=r2.save instead.


`r1 = r2.save;` has the exact same problem. See the linked Bugzilla 
issue for details.


Must ranges support `r1 = r2;`?

2018-03-24 Thread ag0aep6g via Digitalmars-d
Long version:  
("std.range and std.algorithm can't handle refRange").


Short version: With two `std.range.RefRange`s, `r1 = r2;` does not what 
other Phobos code expects.


Question is: Who's at fault? Where do I fix this? Do ranges have to 
support assignment as expected - even though std.range doesn't mention 
it? Or should range-handling code never do that - even though it comes 
naturally and is widespread currently?


Re: Shouldn't pureMalloc be @system instead of @trusted?

2018-03-16 Thread ag0aep6g via Digitalmars-d

On 03/16/2018 10:22 PM, Nordlöw wrote:

Shouldn't `pureMalloc` at

https://dlang.org/library/core/memory/pure_malloc.html

be @system instead of @trusted?


You can only access the uninitialized memory with @system features: 
casting the pointer or slicing it. So it's safe, because you can't do 
anything unsafe with it in @safe code.


Re: DIP 1006 - Preliminary Review Round 1

2018-03-07 Thread ag0aep6g via Digitalmars-d

On 03/07/2018 03:01 PM, Paolo Invernizzi wrote:

Are we asking to statically check things like:

Assign Expressions [1]
Undefined Behavior:
   if the lvalue and rvalue have partially overlapping storage
   if the lvalue and rvalue's storage overlaps exactly but the types are 
different
A simple way to get overlapping storage is with a union. Unfortunately, 
DMD accepts this:



struct S
{
union
{
int i;
byte b;
float f;
struct
{
byte b2;
align(1) int i2;
}
}
}

void main() @safe
{
S s;
s.i = s.b; /* Partially overlapping, different types. */
s.f = s.i; /* Exactly overlapping, different types. */
s.i = s.i2; /* Partially overlapping, same type. */
}


I've filed an issue:
https://issues.dlang.org/show_bug.cgi?id=18568

If you have more examples of UB in @safe functions, don't hesitate to 
file them as bugs.


Re: DIP 1006 - Preliminary Review Round 1

2018-03-07 Thread ag0aep6g via Digitalmars-d

On 03/07/2018 03:01 PM, Paolo Invernizzi wrote:

On Wednesday, 7 March 2018 at 13:32:37 UTC, ag0aep6g wrote:

[...]
I don't think anyone is asking for that. The request is for no UB in 
@safe code.


Are we asking to statically check things like:

Assign Expressions [1]
Undefined Behavior:
   if the lvalue and rvalue have partially overlapping storage
   if the lvalue and rvalue's storage overlaps exactly but the types are 
different


If it can't be guaranteed that some code has defined behavior, then it's 
not allowed in an @safe function (or it should not be allowed). We are 
not asking for all valid code to be @safe.


Guaranteeing no UB is exactly @safe's purpose. The spec says: "Safe 
functions are functions that are statically checked to exhibit no 
possibility of undefined behavior." [1]



Is that doable, in practise?


If you think that's not doable, what do you think @safe should aim for?


[1] https://dlang.org/spec/function.html#function-safety


Re: DIP 1006 - Preliminary Review Round 1

2018-03-07 Thread ag0aep6g via Digitalmars-d
On Wednesday, 7 March 2018 at 08:58:50 UTC, Paolo Invernizzi 
wrote:
Just to understand, otherwise, if the assert is removed and it 
does not hold, you are in UB,


You're not. Just let the compiler treat the code as if the 
asserts weren't there. If the resulting code has UB, it won't 
compile, because @safe code is statically checked to not have UB.


so the request is to guarantee memory safety in a UB state, 
right?


I don't think anyone is asking for that. The request is for no UB 
in @safe code.


Re: DIP 1006 - Preliminary Review Round 1

2018-03-06 Thread ag0aep6g via Digitalmars-d

On 03/06/2018 06:01 PM, Paolo Invernizzi wrote:

Only if the assert does not hold, you have _not_ tested it,


In other words: only if you have a bug in your code.

If @safe is only safe as long you don't have bugs, it's no different 
from @system. So -release turns @safe code into @system code, if it 
contains asserts.


and a future 
optimiser will use the assert expression for some hints that generated 
broken code


Re: DIP 1006 - Preliminary Review Round 1

2018-03-05 Thread ag0aep6g via Digitalmars-d

On 03/05/2018 11:57 PM, Timon Gehr wrote:

On 05.03.2018 22:24, ag0aep6g wrote:

On 03/05/2018 10:11 PM, Walter Bright wrote:

[...]

It is not defined behavior with -boundscheck=off.


Dereferencing null is not defined with -boundscheck=off?


This was my bad. It's not dereferencing null. The compiler is free to 
assume 0function is dead code.


How is it free to assume that?

This was the full snippet (before I mutilated it in my quote):


void main()@safe{
 int[] x=[];
 writeln(x[0]); // range violation even with -release
// defined behavior even with -boundscheck=off (!)
}


There is no `assert(0anything, because there are no contracts, no asserts, and main is @safe. 
-boundscheck=off just makes it so that the length isn't checked before 
x.ptr is dereferenced. x.ptr is null, so the code is defined to 
dereference null, no?


If -boundscheck=off somehow does introduce UB here, we have the weird 
situation that using `x.ptr[0]` is more safe than in this scenario than 
`x[0]`. Because surely `x.ptr[0]` is a null dereference that's not 
affected by -boundscheck=off, right?


Re: DIP 1006 - Preliminary Review Round 1

2018-03-05 Thread ag0aep6g via Digitalmars-d

On 03/05/2018 09:55 PM, Walter Bright wrote:

On 3/5/2018 7:48 AM, Timon Gehr wrote:
Again: assert is @safe. Compiler hints are @system. Why should assert 
give compiler hints?


Asserts give expressions that must be true. Why not take advantage of 
them?


Because it's exactly what @safe is not supposed to do. You're trusting 
the programmer to get their asserts right. Trusting the programmer to 
get it right is @system.


[...]> It's the programmer's option to leave those runtime checks in if he

wants to.


As far as I understand, Timon only asks for a third option: to simply 
compile the code as if the asserts weren't there, without assuming that 
they would pass.


That way you get a speedup from the omitted asserts, but you don't get 
UB from a mistaken assert. This is not an unreasonable thing to want, is it?


You say that DMD does not currently use assert information, so -release 
currently does this.


[...]

There was no "-check=off" flag before.


Yes there was, it's the "release" flag.


But the controversial aspect is not implemented. And it will be very 
surprising if you ever do implement it.


I'm actually pretty shocked that -release is described that way. It 
makes a point of keeping bounds checks in @safe code. The reason is that 
it would be unsafe to remove them. What's the point of that when safety 
is compromised anyway by assuming that asserts would pass?


Re: DIP 1006 - Preliminary Review Round 1

2018-03-05 Thread ag0aep6g via Digitalmars-d

On 03/05/2018 10:11 PM, Walter Bright wrote:

On 3/5/2018 11:34 AM, Timon Gehr wrote:

[...]

  int[] x=[];
  writeln(x[0]); // range violation even with -release
 // defined behavior even with -boundscheck=off (!)


It is not defined behavior with -boundscheck=off.


Dereferencing null is not defined with -boundscheck=off?


Re: tupleof vs @safe

2018-03-04 Thread ag0aep6g via Digitalmars-d

On 03/03/2018 12:22 AM, ag0aep6g wrote:
So am I missing something or should `tupleof` not be allowed to ignore 
`private` in `@safe` code?


Filed an issue: https://issues.dlang.org/show_bug.cgi?id=18554


Re: tupleof vs @safe

2018-03-02 Thread ag0aep6g via Digitalmars-d

On 03/03/2018 12:22 AM, ag0aep6g wrote:
But what about `tupleof`? It ignores `private` and it's allowed in 
`@safe` code:




[...]




Now that I've sent this, I find the affected Phobos type I couldn't 
pinpoint. It's `File`:



void main() @safe
{
import std.stdio: File, writeln;
auto hosts = File("/etc/hosts");
{
auto hosts_copy = hosts;
hosts_copy.tupleof[0].refs = 1; /* uh-oh */
}
auto self = File(__FILE__);
writeln(hosts.rawRead(new char[1000]));
/* Reads from __FILE__ instead of /etc/hosts. */
}


https://run.dlang.io/is/1QSsUk


tupleof vs @safe

2018-03-02 Thread ag0aep6g via Digitalmars-d
As far as I understand, this is generally how ref counting is supposed 
to be done, and with a simple payload like `int` it's supposed to be 
properly safe already:



module my_rc_thingy;
struct RCint
{
import core.stdc.stdlib: free, malloc;

private static struct Store
{
int payload;
uint count;
}
private Store* s = null;

int value() @safe { return s.payload; }

this(int value) @trusted
{
s = cast(Store*) malloc(Store.sizeof);
*s = Store(value, 1);
}

this(this) @safe { ++s.count; }

~this() @trusted
{
if (--s.count == 0)
{
free(s);
s = null;
}
}
}


(There could be more checks for null, but dereferencing null crashes the 
program in an `@safe` manner anyway, so why bother in an example.)


I don't have to worry about DIP 1000, because I don't give out 
references to the payload or to the reference count. Right?


But what about `tupleof`? It ignores `private` and it's allowed in 
`@safe` code:



void main() @safe
{
import my_rc_thingy: RCint;
import std.stdio;

int* p;
{
auto rc = RCint(42);
p = &rc.tupleof[0].payload; /* uh-oh */
}
writeln(*p); /* garbage */

auto rc = RCint(42);
{
auto rc2 = rc; /* increasing the refcount */
rc2.tupleof[0].count = 1; /* uh-oh */
}
writeln(rc.value); /* garbage */
}


So am I missing something or should `tupleof` not be allowed to ignore 
`private` in `@safe` code?


Re: Is the following well defined and allowed?

2018-03-02 Thread ag0aep6g via Digitalmars-d

On 03/02/2018 03:39 PM, Steven Schveighoffer wrote:

On 3/1/18 5:27 PM, ag0aep6g wrote:

[...]

No, I'm looking at the source code.

At the very basic level, you have this:

assert(foo == 0);

Or whatever other condition you have. What this does is gives the 
compiler leeway to ASSUME foo is 0 at this point. It can make any number 
of optimizations assuming this. If foo is NOT equal to 0 at this point, 
then it is a program error, and the assumptions may cause bad things to 
happen.


When you compile in normal mode, this assert causes an Error to be 
thrown, before your code can do any damage.


When you compile without asserts, this causes undefined behavior.


Now you're looking beyond the source code. There's no "normal mode" or 
"without asserts mode" in D source code. What you've got in the D code 
is @safe and @system.


Looking at it your way makes sense when the question is how the actual 
generated executable will behave. But I think it's also valuable to look 
at the language in isolation, without compiler settings.


I'd put it this way:

1) @system code may have UB. For example, out-of-bounds accesses have UB 
in @system code.


2) A compiler may give guarantees on what it does with specific 
instances of UB. For example, DMD guarantees that it throws an Error on 
out-of-bounds accesses, unless you compile with -release. This makes it 
effectively implementation defined behavior. You can rely on this. But 
when considering the source code in isolation, it still has UB.


3) @safe code cannot have UB. This is a strong guarantee. This cannot be 
affected by compiler switches without violating the spec.


[...]
I extend this same treatment and logic to all checks: contracts, bounds 
checks, overlapping slice assign checks, etc. To me, they aren't any 
different than asserts. They aren't any different if they are in @safe 
code or @system code.


I don't agree with the @safe/@system part. @safe code must not exhibit 
UB. That's the point of the attribute.


Checks that would fail may cause UB in @system code, but they can't be 
allowed to cause UB in @safe code. Because nothing can be allowed to 
cause UB in @safe code.


[...]
I agree, I think we should remove the option to disable bounds checks on 
@safe code, in any way. It's too dangerous. If you want performance that 
comes without bounds checks, use a trusted escape, or write system code.


I'm not going to argue against that, obviously.


Re: Is the following well defined and allowed?

2018-03-01 Thread ag0aep6g via Digitalmars-d
On Thursday, 1 March 2018 at 21:01:08 UTC, Steven Schveighoffer 
wrote:

Yeah, it seems like -noboundscheck should never be used.


Agreed.

It's undefined behavior if the check is disabled. How you get 
the check disabled may be affected by @safe, but whether it's 
UB or not has nothing to do with @safe. It has to do with "I 
turned off the checks". Basically, in D, if your program *would 
have* thrown an Error, but didn't because you turned it off, 
the compiler is free to assume UB.


You're looking at the behavior of the compiled executable. Then 
it makes sense to say that a program compiled with the checks has 
defined behavior (throwing Errors) and a program without the 
checks does something undefined (because the compiler manual 
doesn't say that anything in particular is supposed to happen).


That's not how I understand/use "undefined behavior". To me, it's 
the D source code that can have "undefined behavior". When it 
does, the program (as given in source code) is invalid and the 
compiler can do whatever it wants with it. It may:


1) reject the program statically, or it may
2) generate code that throws an Error at run time, or it may
3) generate code that does something arbitrary.

With that meaning of UB, out-of-bounds accesses and overlapping 
copies have undefined behavior in @system code, but they have 
defined behavior in @safe code.


For @system code, DMD chooses option #2 or option #3 depending on 
whether you give -release or not. DMD is free to do this, because 
the source code has UB.


For @safe code, DMD goes with option #2 either way, because the 
spec demands it.


If it were capable, DMD could also go with option #1 for both 
@system and @safe code. The spec allows/encourages that.


In this interpetation, -noboundscheck switches DMD to a different 
dialect of D. In that dialect, out-of-bounds accesses (and 
overlapping copies, apparently) always have UB, in both @system 
and @safe code. That defeats the purpose of @safe. Which is why I 
don't really care for that dialect.


Re: Is the following well defined and allowed?

2018-03-01 Thread ag0aep6g via Digitalmars-d
On Thursday, 1 March 2018 at 20:14:07 UTC, Steven Schveighoffer 
wrote:
dmd -version=dosafe -noboundscheck -run testarrayoverlap.d => 
no error, undefined behavior

dmd -run testarrayoverlap.d => error

@safe has nothing to do with it.


@safe has everything to do with. @safe guarantees that there's no 
undefined behavior. If you can trigger UB in @safe code, that's a 
bug. The guarantee must hold whether asserts are enabled or not. 
-noboundscheck does not just disable asserts, it undermines 
@safe, rendering it meaningless.


For just disabling asserts (without affecting @safe), there's 
-release. With your same code, `dmd -release` => UB, but `dmd 
-release -version=dosafe` => Error.


Re: Is the following well defined and allowed?

2018-03-01 Thread ag0aep6g via Digitalmars-d
On Thursday, 1 March 2018 at 19:05:26 UTC, Steven Schveighoffer 
wrote:
Yes it behaves just like array bounds. No it's not well-defined 
if you disable asserts.


Right. So it's defined to throw an Error in @safe code, and it 
has undefined behavior in @system code. The spec should say this.


Re: Is the following well defined and allowed?

2018-03-01 Thread ag0aep6g via Digitalmars-d
On Thursday, 1 March 2018 at 17:06:48 UTC, Steven Schveighoffer 
wrote:

On 3/1/18 11:48 AM, ag0aep6g wrote:

[...]
Does that mean it has undefined behavior and should not be 
allowed in @safe code?


No, it means it's a runtime error.


But then it's well-defined, like going beyond array bounds, no?


Re: Is the following well defined and allowed?

2018-03-01 Thread ag0aep6g via Digitalmars-d

On 03/01/2018 04:34 PM, David Nadlinger wrote:

On Thursday, 1 March 2018 at 14:54:41 UTC, Shachar Shemesh wrote:

I.e. - is it well defined to copy between overlapping slices?


No: https://dlang.org/spec/arrays.html#overlapping-copying


Does that mean it has undefined behavior and should not be allowed in 
@safe code?


Re: can we un-deprecate .ptr on arrays in @safe code? cf issue 18529

2018-02-27 Thread ag0aep6g via Digitalmars-d

On 02/27/2018 06:32 PM, Atila Neves wrote:

On Tuesday, 27 February 2018 at 12:39:04 UTC, Jonathan M Davis wrote:

[...]
In almost all cases, &a[0] is equivalent to a.ptr except that it does 
bounds checking, so it's actually @safe and thus doesn't need to be 
manually verified by the programmer, unlike your pointer function 
suggestion.


There's a common case where it's not equivalent - when the pointer is 
null. Imagine I have a C function I want to call:


extern(C) void fun(int* things);

Imagine also that it's ok to call with null. Well, now I can't use a 
slice to call this and have it be 1) @safe and 2) not throw RangeError. 
I ran into this the other way.


As Jonathan says, you have to manually verify that it's safe, because it 
generally isn't. `arr.ptr` can be invalid but not null, even in @safe code.


Consider:


void fun(int* things) @safe
{
int x = things is null ? 0 : *things;
import std.stdio;
writeln(x);
}

void main()
{
int[] arr;
fun(arr.ptr); /* Ok, prints "0". */

arr = [1, 2, 3];
fun(arr.ptr); /* Ok, prints "1".*/

arr = arr[$ .. $]; /* This is @safe. */
fun(arr.ptr); /* Not ok, prints garbage. */
}


The first two calls are actually safe and can be @trusted. The third 
call is invalid and must not be possible in @safe code.


Maybe it would be possible require `arr.ptr` to be valid or null in 
@safe code. This would outlaw `arr[$ .. $]` and bounds checking would 
have to catch it. I don't know if that would be any practical than 
banning `arr.ptr`.


Re: How do you get comfortable with Dlang.org's Forum?

2018-02-23 Thread ag0aep6g via Digitalmars-d

On 02/23/2018 03:52 PM, JN wrote:

(or there is a hidden threaded mode I am not aware of?).


Click on "Settings" in the upper right corner. There you can change the 
"view mode" to threaded.


Re: Annotation of functions

2018-02-22 Thread ag0aep6g via Digitalmars-d

On 02/22/2018 12:54 PM, psychoticRabbit wrote:

module test;

import std.stdio, std.file, std.json;

void main()
{
     string myFile= "source.json"; // a file produced by: dmd -o- -X 
source.d


     string js = readText(myFile);

     JSONValue j = parseJSON( js[1..$-1] ); // why do I have to do this??

     writefln("%s = %s", j["kind"].str, j["name"].str);
     writefln("file = %s", j["file"].str);

}


You don't have to remove the brackets. You just have to process the 
result correctly. It's not an object but an array with an object as its 
first element.


If you're only interested in the first module (e.g. because you know 
that there is exactly one), you can use `j[0]["kind"]`, `j[0]["name"]`, 
`j[0]["file"]`.


If you want to handle multiple modules, you can loop over the array:

foreach (size_t i, item; j)
/* It's a bit silly that `foreach (item; j)` doesn't work. */
{
/* ... use `item["kind"]` etc. here ... */
}



Re: proposal: heredoc comments to allow `+/` in comments, eg from urls or documented unittests

2018-02-11 Thread ag0aep6g via Digitalmars-d

On 02/11/2018 09:32 AM, Vladimir Panteleev wrote:

This syntax is syntactically ambiguous.

[...]

     assert(StringNumber("4")/"2" == "2"); // Conflict!
     // Division by string, or nested comment?


Strictly, it's not worse than `/*`, is it?


assert(4/*(new int(2)) == 2);
// Division by dereferenced pointer or comment?


I.e., it's a comment and you have to add a space to make it division.
But `/"` would break existing code, of course.


Re: adrdox vs markdown vs ddoc

2018-02-01 Thread ag0aep6g via Digitalmars-d

On 02/01/2018 07:18 AM, Seb wrote:
It tells quite a bit about the complexity of Ddoc that I had to add 
support for -D to run.dlang.io ...

[...]
I'm not a fan of Ddoc by any means, but that has been fixed in Ddoc does 
this too now: https://run.dlang.io/is/75Z55o


Uhh, is it a good idea to generate documentation on run.dlang.io? Isn't 
this an open invitation for XSS?


Simple example, one can replace all links on the page with malicious ones:
https://run.dlang.io/is/wYLpVx


Re: Shouldn't invalid references like this fail at compile time?

2018-01-22 Thread ag0aep6g via Digitalmars-d

On 01/23/2018 03:38 AM, Mike Franklin wrote:

import std.stdio;

void main() @safe
{
     string foo = "foo";
     string* ls0;
     string* p1, p2;

     ls0 = &foo;
     p1 = ls0;
     ls0.destroy();
     p2 = ls0;
     writeln(p2.length);
}

Compile with `-dip1000`

Error: program killed by signal 11

https://run.dlang.io/is/6L6zcH

So that's bad.  But it looks like a bug in `-dip1000`, because if I 
compile without `-dip1000`, I get:


onlineapp.d(9): Error: cannot take address of local foo in @safe 
function main


https://run.dlang.io/is/rHpuf1


No bug.

`&foo` never leaves the scope, so `-dip1000` correctly allows it. If you 
try to `return p1;` or `return p2;`, you get errors from `-dip1000`.


Other than that, `ls0.destroy();` just does `ls0 = null;` and then the 
`writeln` does a null dereference which is considered to be a guaranteed 
segfault. Segfaults are considered safe and `@safe` is not supposed to 
prevent them.


Re: Shouldn't invalid references like this fail at compile time?

2018-01-22 Thread ag0aep6g via Digitalmars-d

On 01/23/2018 01:20 AM, Mike Franklin wrote:
I would be surprised if 
the compiler allowed you to do something like this in `@safe` code.


You might get surprised then, if you expect the compiler to reject code 
like that statically.


If you add `@safe`, the compiler rejects this line:

ls ~= &foo;

But that line would only be problematic if the pointer would leave the 
scope of the function. It doesn't, so this is actually safe. But the 
compiler isn't smart enough to see this.


The real question is about this line:

p2 = ls[0];

That's an out-of-bounds access, and the compiler does not catch this 
statically. Instead, it inserts bounds-checking code that crashes the 
program safely with an `Error`.


Re: The name "Phobos" in user-facing docs

2018-01-12 Thread ag0aep6g via Digitalmars-d

On 01/12/2018 11:26 PM, Michael wrote:
Tango was the original, and Phobos was introduced for D2 as a 
competing library.


Phobos is the original. In D1, Tango was an alternative standard 
library. With D2, you have Phobos as the standard library and you can 
use Tango on top of it. http://code.dlang.org/packages/tango


Re: Compile-time vs. compile-time

2018-01-05 Thread ag0aep6g via Digitalmars-d

On 01/04/2018 11:59 PM, H. S. Teoh wrote:

I wouldn't say that CTFE means that it is forced/guaranteed. But you're
right that it could be confusing the way I described it.  I added a
section to clarify that usually the compiler would not use CTFE to
constant-fold complex expressions, unless the value is required at
compile-time.

[...]

Are you sure that's non-CTFE?  Isn't standard constant folding a part of
CTFE?

Myself, I use "CTFE" only for the forced kind of compile-time evaluation.

This is my train of thought: CTFE is when `__ctfe` is set. Anything else 
would be too confusing. During forced compile-time evaluation, `__ctfe` 
is obviously set. But an optional optimization cannot set `__ctfe`, 
because that might change the value of the optimized expression. And 
that's something an optimization must not do.


Example:

int foo() { return __ctfe ? 10 : 20; }
int main() { return foo(); }


The program must return 20, no matter how aggressively the compiler 
optimizes.


As far as I can tell, the compilers share this view. For the example, 
they optimize `main` to `return 20;` [1]. So they evaluate `foo()` 
during compilation and use `__ctfe = false`.


The spec's wording isn't as clear as it could be, but can be interpreted 
this way, I think. The relevant statements are [2]:


1) "The __ctfe boolean pseudo-variable [...] evaluates to true at 
compile time, but false at run time".
2) "In order to be executed at compile time, the function must appear in 
a context where it must be so executed".


Unfortunately, the first one says "at compile time" which can very well 
be understood to mean that `__ctfe` should be true during constant 
folding as done by the optimizer.  But then the second statement would 
forbid this optional constant folding, because it doesn't allow 
execution "at compile time" unless the context forces it.


So I'm interpreting "at compile time" to be a synonym for the feature 
called "CTFE". And then it makes perfect sense (to me):


1) "The __ctfe boolean pseudo-variable [...] evaluates to true [during 
CTFE], but false [elsewhere]". -- Makes sense.
2) "In order to be executed [via CTFE], the function must appear in a 
context where [its result must be available during compilation]". -- 
Meaning that anything else isn't CTFE.



[1] https://godbolt.org/g/6xrDF7
[2] https://dlang.org/spec/function.html#interpretation


Re: Compile-time vs. compile-time

2018-01-03 Thread ag0aep6g via Digitalmars-d

On 01/03/2018 02:51 AM, H. S. Teoh wrote:


https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time#But_what_of_runtime_performance.3F

object.destroy! :-P


In the CTFE section, you explain that it came from constant folding, but 
you don't point out how the two are different. After reading the 
section, a newbie might think that the term "CTFE" is for when constant 
folding evaluates function calls. But that's not what we mean by "CTFE".


What's missing is that CTFE is forced/guaranteed. It's not an 
optimization. When we say "CTFE", we mean the cases where compilation 
fails if the expression cannot be evaluated.


I doesn't help that the `i` variables in the examples are (seemingly) 
globals, but you also talk about putting them in a "busy inner loop". If 
I just copy the code as it is, `i` is a global and I get actual CTFE. If 
I put `i` in a loop, it's a local and it's up to the compiler if it does 
non-CTFE constant folding.


Also, you mistyped Stefan Koch's name.


Re: What do you want to see for a mature DLang?

2017-12-30 Thread ag0aep6g via Digitalmars-d

On 12/30/2017 04:07 AM, IM wrote:
I like what the D foundation did to the website, the language and 
library docs, the Learn section, the forums, the resources ... etc. That 
definitely gives the impression of maturity.


As far as I'm aware, the foundation isn't too active in those areas; 
unless Vladimir or Seb are on their payroll now. Maybe the foundation 
pays the electricity bills, but the work is done by volunteers.


Re: state of ranges

2017-12-13 Thread ag0aep6g via Digitalmars-d

On 12/13/2017 10:13 AM, Dukc wrote:
front() can assume that 
something can be found, so it may as well fetch the value without 
checking and rely on built-in array bounds checking and null behaviour 
for memory safety. empty() is the one which should check those things 
manually.


No. As Seb has quoted, `front` can't assume that `empty` has been called 
before. For a well-behaved range, `front` must work the same whether 
you've called `empty` or not (given that the range isn't actually empty).


Re: static array with inferred size

2017-09-20 Thread ag0aep6g via Digitalmars-d

On 09/20/2017 06:55 PM, Steven Schveighoffer wrote:

On 9/20/17 11:48 AM, Dgame wrote:

[...]


Unqual!T[n] s(T, size_t n)(T[n] arr)
{
 return arr;
}

auto a = "hallo".s;
writeln(typeof(a).stringof); // char[5]


[...]

Still it can't handle the case of:

ubyte[3] x = [1, 2, 3];


Making the parameter variadic seems to do the trick:


import std.traits: Unqual;

Unqual!T[n] s(T, size_t n)(T[n] arr ...)
{
 return arr[];
/* With indirections, dmd would complain about an
escaping reference. Slicing shuts it up. */
}

void main()
{
auto a = s("hello");
static assert(is(typeof(a) == char[5]));

auto x = s!ubyte(1, 2, 3);
static assert(is(typeof(x) == ubyte[3]));

auto y = s(new int, new int);
static assert(is(typeof(y) == int*[2]));

auto z = s(new immutable int, new immutable int);
static assert(is(typeof(z) == immutable(int)*[2]));
}



Re: Specifying @nogc on structs seems to have no effect

2017-09-19 Thread ag0aep6g via Digitalmars-d

On 09/19/2017 08:06 PM, Craig Black wrote:
This wouldn't 
be allowed for classes or class references, since they are always 
pointing to GC data


That's not true. You can put class objects into other places than the GC 
heap.


Re: Specifying @nogc on structs seems to have no effect

2017-09-19 Thread ag0aep6g via Digitalmars-d

On 09/19/2017 03:46 PM, Craig Black wrote:

struct MyStruct
{
@nogc:
public:
   Foo foo; // This does not produce an error, but it still requires a 
GC scan


@nogc is about GC allocations. `Foo foo;` doesn't cause a GC allocation.

@nogc doesn't control what memory is scanned by the GC.


Re: C `restrict` keyword in D

2017-09-04 Thread ag0aep6g via Digitalmars-d

On 09/04/2017 11:47 AM, Moritz Maxeiner wrote:
Still, though, this is surprising to me, because this means taking the 
address of a parameter passed by reference (which is in your case is 
typed as an existing int) can be null. Is this documented somewhere 
(couldn't find it in the spec and it seems like a bug to me)?


I'm only aware of this part of the spec, which doesn't say much about 
ref parameters:


https://dlang.org/spec/function.html#parameters

g++ accepts the equivalent C++ code and shows the same behavior. But, as 
far as I can tell, it's undefined behavior there, because dereferencing 
null has undefined behavior.


In D, dereferencing a null pointer is expected to crash the program. 
It's allowed in @safe code with that expectation. So it seems to have 
defined behavior that way.


But if a dereferencing null must crash the program, shouldn't my code 
crash at the call site? Or is there an exception for ref parameters? Any 
way, the spec seems to be missing some paragraphs that clear all this up.


Re: C `restrict` keyword in D

2017-09-04 Thread ag0aep6g via Digitalmars-d

On 09/04/2017 06:10 AM, Moritz Maxeiner wrote:
Indeed, but it also means that - other than null dereferencing - pointer 
issues can by made into reference issues my dereferencing a pointer and 
passing that into a function that takes that parameter by reference.


Why "other than null dereferencing"? You can dereference a null pointer 
and pass it in a ref parameter. That doesn't crash at the call site, but 
only when the callee accesses the parameter:



int f(ref int x, bool b) { return b ? x : 0; }
void main()
{
int* p = null;

/* Syntactically a null dereference, but doesn't crash: */
f(*p, false);

/* This crashes: */
f(*p, true);
}



Re: Promoting TutorialsPoint's D tutorial

2017-08-27 Thread ag0aep6g via Digitalmars-d

On 08/27/2017 10:13 PM, Ecstatic Coder wrote:
I still do not understand why they have made so many separated Github 
account for just one website. Just using sub folders on the same Github 
account would have been a much simpler solution, so that it's easy to 
make changes to the website on a more global scale...


The beauty of decentralized, volunteer-driven development.

forum.dlang.org, code.dlang.org, and tour.dlang.org started as 
independent projects by different authors. They were later integrated 
into dlang.org, but so far they remain as separate projects, using 
different technology, having their own maintainers, etc.


I agree that dealing with multiple repositories can be annoying. But 
people have to prioritize what they work on, and merging everything into 
one is probably not high on the list. For the people who maintain it, it 
works reasonably well as it is.


Re: Promoting TutorialsPoint's D tutorial

2017-08-27 Thread ag0aep6g via Digitalmars-d

On 08/27/2017 08:07 PM, Ecstatic Coder wrote:
I've already received enough "No, not interested" answers till now to 
the same proposal to think that this will be ok this time.


Add my voice to that corpus - I honestly don't care what the website 
looks like.


Ok, message received. At least I've got my answer for the PR. Thanks for 
your honesty. Sincerely.


I'm not sure what you're saying here. Are you not going to make a pull 
request because Moritz isn't interested? If so, you should know that he 
is not the one who decides about this stuff (not that he claimed to be). 
Neither am I. We're just engaging in discussion.


Re: Promoting TutorialsPoint's D tutorial

2017-08-26 Thread ag0aep6g via Digitalmars-d

On 08/27/2017 01:53 AM, Ryion wrote:
* D website starts with a big blog of texts Module, ModuleDeclaration 
DeclDefs DeclDefs. What am i reading. Chinese?


You're reading the spec. Teaching is not the spec's first priority. It's 
not a tutorial or a programming textbook.


Have you tried Ali's book? The page on modules is here:

http://ddili.org/ders/d.en/modules.html

Wait a second. Large parts of that are word-for-word the same as on the 
tutorialspoint page [1]. Looks like one of the authors copied from the 
other one. From the bad impression I've got of tutorialspoint, I'd guess 
that they copied from Ali.



[1] https://www.tutorialspoint.com/d_programming/d_programming_modules.htm


Re: Promoting TutorialsPoint's D tutorial

2017-08-26 Thread ag0aep6g via Digitalmars-d

On 08/27/2017 12:26 AM, Ecstatic Coder wrote:
My point is that when you arrive to the further reading, you are invited 
to buy Ali's book :


You can read Ali's book online for free.

[...]
I've no problem with that, but would it be possible to consider adding 
also a link to this tutorial in the same paragraph ?


https://www.tutorialspoint.com/d_programming/


I'd vote against that. It seems poorly written.

* There are multiple grammatical errors in the first paragraph alone.
* The hello work example is repeated multiple times on the first pages, 
always with a pointless `args` parameter on `main`.

* The download links go to 2.064.2, which is several years old.
* The "first D program" has the line `writeln("test!");`. Its output is 
given as "test", missing the exclamation mark.


As far as I see, it's just not good.


Re: C++17 Init statement for if/switch

2017-08-15 Thread ag0aep6g via Digitalmars-d

On 08/15/2017 08:55 PM, Daniel Kozak wrote:

C++17 will have this feature:
https://tech.io/playgrounds/2205/7-features-of-c17-that-will-simplify-your-code/init-statement-for-ifswitch 



What do you think about it, can we have something similar to that.
Maybe something like this:


int func() return 5;

with(auto x = func()) if (condition(x))
 do_something_with(x);
else
 do_something_else_with(x);


Previous discussion:
http://forum.dlang.org/post/vfjlpvpwuyfqoljvp...@forum.dlang.org

Andrei doesn't like the C++ way, but he seems to be ok with the `with` way:
http://forum.dlang.org/post/oktru0$159b$1...@digitalmars.com

Walter didn't comment.

I think this has a good chance of getting in, but someone will have to 
write a DIP and implement it.


Re: all OS functions should be "nothrow @trusted @nogc"

2017-07-27 Thread ag0aep6g via Digitalmars-d

On 07/27/2017 03:24 PM, Moritz Maxeiner wrote:

--- null.d ---
version (linux):

import core.stdc.stdio : FILE;
import core.sys.linux.sys.mman;

extern (C) @safe int fgetc(FILE* stream);

void mmapNull()
{
 void* mmapNull = mmap(null, 4096, PROT_READ | PROT_WRITE, 
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED | MAP_POPULATE, -1, 0);
 assert (mmapNull == null, "Do `echo 0 > /proc/sys/vm/mmap_min_addr` 
as root");

 *(cast (char*) null) = 'D';
}

void nullDeref() @safe
{
 fgetc(null);
}

void main(string[] args)
{
 mmapNull();
 nullDeref();
}
---

For some fun on Linux, try out
# echo 0 > /proc/sys/vm/mmap_min_addr
$ rdmd null.d


The gist of this is that Linux can be configured so that null can be a 
valid pointer. Right?


That seems pretty bad for @safe at large, not only when C functions are 
involved.


Re: all OS functions should be "nothrow @trusted @nogc"

2017-07-25 Thread ag0aep6g via Digitalmars-d

On 07/25/2017 04:32 PM, Shachar Shemesh wrote:
And, indeed, the code calling "read" shouldn't be able to do that as 
@safe. Read itself, however, is trusted (because, let's face it, if you 
cannot trust the kernel, you're screwed anyways).


That's not how `@trusted` works. The point of `@trusted` is to allow 
unsafe features in the implementation. The interface must be just as 
safe as with `@safe`.


`read` doesn't have a safe interface. `read` is safe as long as long as 
you pass good arguments. When you pass bad arguments, `read` will break 
your stuff. A `@trusted` function must always be safe, no matter the 
arguments.


Re: all OS functions should be "nothrow @trusted @nogc"

2017-07-25 Thread ag0aep6g via Digitalmars-d

On 07/25/2017 03:50 PM, Shachar Shemesh wrote:
The title really does says it all. I keep copying OS function 
declarations into my code, just so I can add those attributes to them. 
Otherwise I simply cannot call "signalfd" and "sigemptyset" (to name a 
couple from my most recent history) from @safe code.


Not all OS functions can be `@trusted`.

I don't about `signalfd` and `sigemptyset`, but `read` [1] can't be 
`@trusted`, for example. It takes pointer and length separately, and the 
pointer is a `void*`. That's not safe at all.



[1] http://man7.org/linux/man-pages/man2/read.2.html


  1   2   3   >