Re: Manu's `shared` vs the @trusted promise
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. For reading, its a size_t so can be done with atomics, writing OTOH is a @property that calls a function to reallocate if ned be. Reallocation obviously needs to be locked.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:55:00 UTC, Timon Gehr wrote: On 22.10.18 02:46, Nicholas Wilson wrote: On Monday, 22 October 2018 at 00:38:33 UTC, Timon Gehr wrote: I just did, Link please? https://forum.dlang.org/post/pqii8k$11u3$1...@digitalmars.com That contains no code. Not all of the parties that participate in the data race are in @trusted code. There are two cases of @trusted code, bad and good. Bad trusted code can indeed be misused by @safe code to corrupt memory. Good trusted code cannot. What part of the proposal breaks the type system? The implicit conversion to shared implies that the passed to function is @safe iff all the functions it calls are @safe only call function with that parameter to other shared @safe functions _OR_ they are @trusted. The point of @trusted is modularity: you manually check @trusted code according to some set of restrictions and then you are sure that there is no memory corruption. Yes. And?
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:46:04 UTC, Walter Bright wrote: That's what I was referring to, and Manu's example. It doesn't work, as I pointed out. I'm pretty sure it does, but please repeat it. We will eventually. This started as a "please point out any problems with this" and has probably outlived that phase. You'll need to address the issues raised here in the DIP. That is a given. You would do well to heed it for your own DIPs.
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:38:33 UTC, Timon Gehr wrote: I just did, Link please?
Re: shared - i need it to be useful
On Monday, 22 October 2018 at 00:32:35 UTC, Timon Gehr wrote: This only works if untrusted programmers (i.e. programmers who are only allowed to write/modify @safe code) are not allowed to change your class. I.e. it does not work. This is the basis of the current @safe/@trusted/@system model. Are you saying it is useless?
Re: shared - i need it to be useful
On Sunday, 21 October 2018 at 22:12:18 UTC, Neia Neutuladh wrote: On Sun, 21 Oct 2018 12:04:16 -0700, Manu wrote: On Sun, Oct 21, 2018 at 12:00 PM Timon Gehr via Digitalmars-d wrote: Note that there may well be a good way to get the good properties of MP without breaking the type system, but MP itself is not good because it breaks @safe. Show me. Nobody has been able to show that yet. I'd really like to know this. If we only used your proposal and only used @safe code, we wouldn't have any data races, Only of the @trusted implementation is thread safe, which it _should_ be. This is the same caveat as non threaded -@safe/@tusted code. but that's only because we wouldn't have any shared data. We'd have shared *variables*, but they would not contain any data we could read Reads must be atomic. or alter, and that's pretty much useless. To use your proposal, we need to cast data back from shared to unshared. Yes but this is in the @trusted implementation that forms the basis of your threadsafety. When it's unshared, we need to make sure that exactly one thread has a reference to that data as unshared. Nod. And @safe *should* help us with that. Nod. Currently, it helps because casting unshared to shared is not @safe, This remains the case, and should be done (enforced by the compiler) only in @trusted/@system code as a basis for thread safe, @safe code. because it makes it trivial to get multiple threads with unshared references to the same data. That is @trusted or @system code and therefore is the programmers responsibility. And that's when you're using shared as expected rather than doing something weird. That forms the basis of your thread safe stack. From there on, the basis that shared arguments to functions are treated safely in the presence of threading means that code that calls the @trusted implementations is @safe.
Re: shared - i need it to be useful
On Sunday, 21 October 2018 at 21:32:14 UTC, Walter Bright wrote: On 10/21/2018 2:08 PM, Walter Bright wrote: On 10/21/2018 12:20 PM, Nicholas Wilson wrote: Yes, but the problem you describe is arises from implicit conversion in the other direction, which is not part of the proposal. It's Manu's example. Then I don't know what the proposal is. Pieces of it appear to be scattered over numerous posts, mixed in with other text, opinions, and handwavy stuff. There's nothing to point to that is "the proposal". The proposal is: Implicit conversion _to_ shared, e.g. passing it to a thread entry point, and not implicit conversion _from_ shared (just like implicit const conversions). Shared disables reads and writes Your confusion results from the use of atomic add which, in Manu's examples had a different signature than before. I suggest you and Manu write up a proper proposal. Something that is complete, has nothing else in it, has a rationale, illuminating examples, and explains why alternatives are inferior. We will eventually. This started as a "please point out any problems with this" and has probably outlived that phase. Trying to rewrite the semantics of shared is not a simple task, Not as much as trying to explain it! Having talked to Manu in person it is much easier to understand. doing multithreading correctly is a minefield of "OOPS! I didn't think of that!" The above case in point, this is about assuming your implementation of thread safe primitives are thread safe (@trusted) that you use it correctly (@safe).
Re: shared - i need it to be useful
On Sunday, 21 October 2018 at 19:07:37 UTC, Nicholas Wilson wrote: On Sunday, 21 October 2018 at 09:50:09 UTC, Walter Bright wrote: Your proposal makes that impossible because the compiler would allow unshared data to be implicitly typed as shared. Yes, but not the other way around. Whoops that should read Your proposal makes that impossible No because the compiler would allow unshared data to be implicitly typed as shared. Yes, but the problem you describe is arises from implicit conversion in the other direction, which is not part of the proposal.
Re: shared - i need it to be useful
On Sunday, 21 October 2018 at 09:50:09 UTC, Walter Bright wrote: Manu's Proposal --- @safe: int i; int* a = &i; StartNewThread(a); // Compiles! Coder has no idea! ... in the new thread ... void StartOfNewThread(shared(int)* b) { ... we have two threads accessing 'i', one thinks it is shared, the other unshared, and StartOfNewThread() has no idea and anyone writing code for StartOfNewThread() has no way to know anything is wrong ... lockedIncrement(b); // Data Race! No, does not compile, lockedIncrement takes an int* Error cannot convert shared(int)* to int* Your proposal means that the person writing the lockedIncrement(), which is a perfectly reasonable thing to do, Indeed. simply cannot write it in a way that has a @safe interface, because the person writing the lockedIncrement() library function has no way to know that the data it receives is actually unshared data. It does, it takes an int* which is not implicitly convertible to given an shared(int)* I.e. @trusted code is obliged to proved a safe interface. Yes. Your proposal makes that impossible because the compiler would allow unshared data to be implicitly typed as shared. Yes, but not the other way around.
Re: shared - i need it to be useful
On Sunday, 21 October 2018 at 09:58:18 UTC, Walter Bright wrote: On 10/20/2018 11:08 AM, Nicholas Wilson wrote: You can if no-one else writes to it, which is the whole point of Manu's proposal. Perhaps it should be const shared instead of shared but still. There is no purpose whatsoever to data that can be neither read nor written. Indeed but there is a subtle difference between that and Manu's proposal: access through the shared variable may not have non-atomic reads, not no reads. Shared data is only useful if, at some point, it is read/written, Yes presumably by casting it to unshared in @trusted code. That is one way to do it, others include atomics and other @trusted primitives As soon as that is done, you've got a data race with the other existing unshared aliases. You're in @trusted code, that is the whole point. The onus is on the programmer to make that correct, same with regular @safe/@trusted@system code.
Re: shared - i need it to be useful
On Saturday, 20 October 2018 at 17:06:22 UTC, Stanislav Blinov wrote: On Saturday, 20 October 2018 at 16:48:05 UTC, Nicholas Wilson wrote: On Saturday, 20 October 2018 at 09:04:17 UTC, Walter Bright wrote: by code that believes it is unshared you cannot `@safe`ly modify the memory through `b`, `a`'s view of the memory is unchanged in @safe code. And that's already a bug, because the language can't enforce threadsafe access through `a`, regardless of presence of `b`. Only the programmer can. access through `a` is through the owned reference threadsafety through a does't mean anything, all _other_ access must ensure that the are ordered correctly. and, code that believes it is shared. you cannot have non-atomic access though `b`, `b` has no @safe view of the memory, unless it is atomic (which by definition is synchronised). Synchronized with what? You still have `a`, which isn't `shared` and doesn't require any atomic access or synchronization. Synchronized w.r.t any writes to that memory, e.g. from `a`. At this point it doesn't matter if it's an int or a struct. Yes. As soon as you share `a`, you can't just pretend that reading or writing `a` is safe. You can if no-one else writes to it, which is the whole point of Manu's proposal. Perhaps it should be const shared instead of shared but still.
Re: shared - i need it to be useful
On Saturday, 20 October 2018 at 16:41:41 UTC, Stanislav Blinov wrote: On Saturday, 20 October 2018 at 16:18:53 UTC, aliak wrote: class C { void f(); void g() shared; } void t1(shared C c) { c.g; // ok c.f; // error } void t2(shared C c) { c.g; // ok c.f; // error } auto c = new C(); spawn(&t1, c); // line 20 spawn(&t2, c); // line 21 c.f; // ok c.g; // ok // line 23 Those are not "ok". They're only "ok" under Manu's proposal so long as the author of C promises (via documentation) that that's indeed "ok". There can be no statically-enforced guarantees that those calls are "ok", or that issuing them in that order is "ok". Yet Manu keeps insisting that somehow there is. Backing up a bit and making a few observations (after adding imports and wrapping the bottom code in a function): 1. the code above currently does not compile, error messages are: i. line 20 & 21: spawn fails to instantiate because c is not shared ii. line 23: shared method C.g is not callable using a non-shared object iii. the lines already marked // error 2. in order to fix 1.i, one must cast c to shared at the call site, this is not @safe 3 fixing 1.ii requires doing `(cast(shared)c).g`, this is also not @safe 4 fixing 1.iii fixing requires casting away shared, this is not only not @safe, but also wrong. c is a class so one could try locking it although I'm not sure what the implications are for doing that when another thread owns the data, probably bad. 5 the current means of dealing with shared with lock and cast away shared is also not @safe 6 under Manu's proposal reading and writing shared objects results in compilation error 7 The static guarantees we have in the language are type safety and @safe 8 under Manu's proposal to do anything one must call shared functions on said object, this implies a "@trusted" implementation at the bottom of the stack for ensuring thread safety (atomics and lock + cast (assuming it is not wrong), other sync primitives) that are not @safe, but not outright wrong either. The question then becomes: assuming the implementation _is_ @safe type correct and thread safe etc., can the author of C provide guarantees of @safe and type correctness? and can this guarantee be free of false positives? Currently the answer is no: the requirement to cast to and from shared is un-@safe and that burden is on the user which means that they must understand the inner workings of C to know it that is the case. Manu's proposal is slightly more interesting. shared becomes a guarantee that accesses to that object will not race, assuming that the @trusted implementation at the bottom of the stack are correct. In the above if t1 and t2 took `const shared C` and `g` was also const shared, then I think that it could.
Re: shared - i need it to be useful
On Saturday, 20 October 2018 at 09:04:17 UTC, Walter Bright wrote: On 10/19/2018 11:18 PM, Manu wrote: The reason I ask is because, by my definition, if you have: int* a; shared(int)* b = a; While you have 2 numbers that address the same data, it is not actually aliased because only `a` can access it. They are aliased, Quoting Wikipedia: two pointers A and B which have the same value, then the name A[0] aliases the name B[0]. In this case we say the pointers A and B alias each other. Note that the concept of pointer aliasing is not very well-defined – two pointers A and B may or may not alias each other, depending on what operations are performed in the function using A and B. In this case given the above: `a[0]` does not alias `b[0]` because `b[0]` is ill defined under Manu's proposal, because the memory referenced by `a` is not reachable through `b` because you can't read or write through `b`. by code that believes it is unshared you cannot `@safe`ly modify the memory through `b`, `a`'s view of the memory is unchanged in @safe code. and, code that believes it is shared. you cannot have non-atomic access though `b`, `b` has no @safe view of the memory, unless it is atomic (which by definition is synchronised). This is not going to work. Aú contraire.
Re: Shared - Another Thread
On Saturday, 20 October 2018 at 00:00:49 UTC, Dominikus Dittes Scherkl wrote: Hmm. mutable, immutable and const form a triple, the second is a declaration attribute, the last an parameter attribute, indicating that you don't want to modify the parameter, may it be because you can't (as it is immutable) or you only don't need to despite it would be possible (if it was mutable). The later is your responsibility to guarantee (with the help from the compiler). Therefore it is possible to implicitly cast from mutable or immutable to const but not in any other direction. I think for unshared, shared and threadsave it should be the same: The second is a declaration attribute, the third a parameter attribute. The first two can implicitly be cast to threadsave, may be because it is thread-local and therefore no race condition is possible, or may be because you take special care in your type to guarantee the thread safety by using atomic operations or locking or whatever. That make it possible, that the implicit cast from shared to unshared can be avoided while still providing functions that can take both kinds of arguments. Yes, that would add a little to the attribute bloat (new keyword) but not to the number of attributes per type or parameter. Mutable = value may change const = I will not change the value immutable = the value will not change unshared = I (well the current thread) owns the reference shared = reference not owned, no unordered access, no (unordered) writes threadsafe = ???
Re: Truly @nogc Exceptions?
On Friday, 19 October 2018 at 23:34:01 UTC, Atila Neves wrote: On Thursday, 20 September 2018 at 12:48:13 UTC, Steven Schveighoffer wrote: How is the exception destroyed when dip1008 is enabled? Apparently, it isn't. Which renders dip1008 pretty much useless since we could already use static immutable exceptions before. Wow, that is useless! Is that an implementation bug or was that specified by the DIP?
Re: shared - i need it to be useful
On Wednesday, 17 October 2018 at 15:51:04 UTC, Steven Schveighoffer wrote: On 10/17/18 9:58 AM, Nicholas Wilson wrote: On Wednesday, 17 October 2018 at 13:25:28 UTC, Steven Schveighoffer wrote: It's identical to the top one. You now have a new unshared reference to shared data. This is done WITHOUT any agreed-upon synchronization. It isn't, you typo'd it (I originally missed it too). int *p3 = cast(int*)p2; vs int *p3 = p; It wasn't a typo. The first example assigns p2, the second assigns p (which is thread local) _not_ p2 (which is shared), I'm confused.
Re: shared - i need it to be useful
On Wednesday, 17 October 2018 at 14:26:43 UTC, Timon Gehr wrote: On 17.10.2018 16:14, Nicholas Wilson wrote: I was thinking that mutable -> shared const as apposed to mutable -> shared would get around the issues that Timon posted. Unfortunately not. For example, the thread with the mutable reference is not obliged to actually make the changes that are performed on that reference visible to other threads. Yes, but that is covered by not being able to read non-atomically from a shared reference.
Re: shared - i need it to be useful
On Wednesday, 17 October 2018 at 07:24:13 UTC, Stanislav Blinov wrote: On Wednesday, 17 October 2018 at 05:40:41 UTC, Walter Bright wrote: When Andrei and I came up with the rules for: mutable const shared const shared immutable and which can be implicitly converted to what, so far nobody has found a fault in those rules... Here's one: shared -> const shared shouldn't be allowed. Mutable aliasing in single-threaded code is bad enough as it is. Could you explain that a bit more? I don't understand it, mutable -> const is half the reason const exists. I was thinking that mutable -> shared const as apposed to mutable -> shared would get around the issues that Timon posted.
Re: shared - i need it to be useful
On Wednesday, 17 October 2018 at 13:25:28 UTC, Steven Schveighoffer wrote: On 10/16/18 8:26 PM, Manu wrote: On Tue, Oct 16, 2018 at 2:20 PM Steven Schveighoffer via Digitalmars-d wrote: There is in fact, no difference between: int *p; shared int *p2 = p; int *p3 = cast(int*)p2; Totally illegal!! You casted away shared. That's as bad as casting away const. But if you can't do anything with shared data, how do you use it? and this: int *p; shared int *p2 = p; int *p3 = p; There's nothing wrong with this... I don't understand the point? It's identical to the top one. You now have a new unshared reference to shared data. This is done WITHOUT any agreed-upon synchronization. It isn't, you typo'd it (I originally missed it too). int *p3 = cast(int*)p2; vs int *p3 = p;
Re: shared - i need it to be useful
On Wednesday, 17 October 2018 at 00:29:04 UTC, Manu wrote: On Tue, Oct 16, 2018 at 3:25 PM Nicholas Wilson via Digitalmars-d wrote: On Tuesday, 16 October 2018 at 21:19:26 UTC, Steven Schveighoffer wrote: > There is in fact, no difference between: > > int *p; > shared int *p2 = p; > int *p3 = cast(int*)p2; > > and this: > > int *p; > shared int *p2 = p; > int *p3 = p; If I understand Manu correctly the first should compile, and the second should error, just like if you replaces shared with const in the above. Why is the second an error? Right, for the sake of the thought experiment, replace shared with const. The first is an abomination (casting away const)... the second is just a no-op. I missed that the third example was *p3 = p; not *p3 = p2;
Re: shared - i need it to be useful
On Tuesday, 16 October 2018 at 21:19:26 UTC, Steven Schveighoffer wrote: There is in fact, no difference between: int *p; shared int *p2 = p; int *p3 = cast(int*)p2; and this: int *p; shared int *p2 = p; int *p3 = p; If I understand Manu correctly the first should compile, and the second should error, just like if you replaces shared with const in the above.
Re: shared - i need it to be useful
On Tuesday, 16 October 2018 at 21:19:26 UTC, Steven Schveighoffer wrote: OK, so here is where I think I misunderstood your point. When you said a lock-free queue would be unusable if it wasn't shared, I thought you meant it would be unusable if we didn't allow the implicit cast. But I realize now, you meant you should be able to use a lock-free queue without it being actually shared anywhere. What I say to this is that it doesn't need to be usable. I don't care to use a lock-free queue in a thread-local capacity. I'll just use a normal queue, which is easy to implement, and doesn't have to worry about race conditions or using atomics. A lock free queue is a special thing, very difficult to get right, and only really necessary if you are going to share it. And used for performance reasons! I think this comes up where the queue was originally shared, you acquired a lock on the thing it is a member of, and you want to continue using it through your exclusive reference.
Re: shared - i need it to be useful
On Monday, 15 October 2018 at 23:30:43 UTC, Stanislav Blinov wrote: On Monday, 15 October 2018 at 21:51:43 UTC, Manu wrote: If a shared method is incompatible with an unshared method, your class is broken. What?!? So... my unshared methods should also perform all that's necessary for `shared` methods? No, its the other way around: a shared method that does extra synchronisation should work irrespective of wether or not the object needs that synchronisation. e.g. atomic loading a TLS variable is fine. Explicit casting doesn't magically implement thread-safety, it basically just guarantees failure. It doesn't indeed. It does, however, at least help prevent silent bugs. Via that same guaranteed failure. That failure is about all the help we can get from the compiler anyway. What I suggest are rules that lead to proper behaviour with respect to writing a thread-safe API. You can write bad code with any feature in any number of ways. Yup. For example, passing an int* to a function expecting shared int*. That is a reasonable thing to do if shared is const + no unsynched reads. I see it this way: If your object has shared methods, then it is distinctly and *deliberately* involved in thread-safety. You have deliberately opted-in to writing a thread-safe object, and you must deliver on your promise. The un-shared API of an object that supports `shared` are not exempt from the thread-safety commitment, they are simply the subset of the API that may not be called from a shared context. And therefore they lack any synchronization. So I don't see how they *can* be "compatible" with `shared` methods. I think Manu means you have a shared object with some shared methods and some unshared methods. The shared methods deal with synchronisation and can therefore be call from anywhere by anyone, whereas the unshared methods must be called on a locked object. snip Nobody writes methods of an object such that they don't work with each other... methods are part of a deliberately crafted and packaged entity. If you write a shared object, you do so deliberately, and you buy responsibility of making sure your objects API is thread-safe. If your object is not thread-safe, don't write shared methods. Ahem... Okay... import std.concurrency; import core.atomic; void thread(shared int* x) { (*x).atomicOp!"+="(1); } shared int c; void main() { int x; auto tid = spawn(&thread, &x); // "just" a typo } You're saying that's ok, it should "just" compile. It shouldn't. It should produce an error and a mild electric discharge into the developer's chair. Indeed that is just a typo, just as that is a contrived example. You'd notice that pretty quick in a debugger.
Re: shared - i need it to be useful
On Monday, 15 October 2018 at 21:08:38 UTC, Manu wrote: On Mon, Oct 15, 2018 at 2:05 PM Nicholas Wilson via Digitalmars-d wrote: I'm saying that while what you propose sounds very reasonable, we should make sure that reading immutable variables is still good ;) I don't think what I describe affects immutable in any way; `is(immutable(int) == shared) == false`, as it should be. Immutable wouldn't have its rules affected by any change to shared. OK, just making sure you've got this covered.
Re: shared - i need it to be useful
On Monday, 15 October 2018 at 20:54:12 UTC, jmh530 wrote: On Monday, 15 October 2018 at 20:44:35 UTC, Manu wrote: snip Are you saying `is(immutable(int) == shared) == true)` ?? From the spec: "Applying any qualifier to immutable T results in immutable T. This makes immutable a fixed point of qualifier combinations and makes types such as const(immutable(shared T)) impossible to create." Example: import std.stdio : writeln; void main() { writeln(is(immutable(int) == shared immutable(int)) == true); //prints true } The philosophy of this is that: the value never changes, therefore only one copy of the variable needs to exist (i.e. immutable variables declared at module scope are _not_ thread local) and can be shared between threads with no race conditions. I'm saying that while what you propose sounds very reasonable, we should make sure that reading immutable variables is still good ;)
Re: shared - i need it to be useful
On Monday, 15 October 2018 at 18:46:45 UTC, Manu wrote: Destroy... Keep in mind immutable is implicitly shared (i.e. not in tls) because nobody can change it. It should stay readable for this reason.
Re: shared - i need it to be useful
On Monday, 15 October 2018 at 19:14:58 UTC, Peter Alexander wrote: On Monday, 15 October 2018 at 18:46:45 UTC, Manu wrote: 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. Just checking my understanding: are you saying here that shared methods can effectively do anything and the burden of correctness is on the author? Or do you still have to cast the shared away first? Well `this` is still shared so you would be prevented from doing anything non-atomically or lock cast away shared, but that will be enforced by the type system. So the burden of correctness is on the author, but the complier enforces correct behaviour.
Re: You don't like GC? Do you?
On Friday, 12 October 2018 at 20:12:26 UTC, Stanislav Blinov wrote: On Friday, 12 October 2018 at 19:55:02 UTC, Nicholas Wilson wrote: Freeing your mind and the codebase of having to deal with memory leaves it in an easier place to deal with the less common higher impact leaks: file descriptors, sockets, database handles ect. (this is like chopping down the forest so you can see the trees you care about ;) ). That's done first and foremost by stripping out unnecessary allocations, not by writing "new" every other line and closing your eyes. If you need perf in your _scripts_, a use LDC and b) pass -O3 which among many other improvements over baseline will promote unnecessary garbage collection to the stack. I mean come on, it's 2018. We're writing code for multi-core and multi-processor systems with complex memory interaction. We might be sometimes. I suspect that is less likely for a script to fall in that category. Precisely where in memory your data is, how it got there and how it's laid out should be bread and butter of any D programmer. It's true that it isn't critical for one-off scripts, but so is deallocation. Saying stuff like "do more with GC" is just outright harmful. That is certainly not an unqualified truth. Yes one shouldn't `new` stuff just for fun, but speed of executable is often not what one is trying to optimise when writing code, e.g. when writing a script one is probably trying to minimise development/debugging time. Kids are reading, for crying out loud. Oi, you think thats bad? Try reading what some of the other Aussies post, *cough* e.g. a frustrated Manu *cough*
Re: You don't like GC? Do you?
On Friday, 12 October 2018 at 19:43:02 UTC, Stanislav Blinov wrote: On Friday, 12 October 2018 at 18:50:26 UTC, Neia Neutuladh wrote: Over the lifetime of the script, it processed more memory than my computer had. That means I needed a memory management strategy other than "allocate everything". The GC made that quite easy. Now *that* is a good point. Then again, until you run out of address space you're still fine with just plain old allocate-and-forget. Not that it's a good thing for production code, but for one-off scripts? Sure. People demonstrably have trouble doing that. We can do it most of the time, but everyone occasionally forgets. The GC isn't a cure for forgetfulness. One can also forget to close a file or a socket, or I dunno, cancel a financial transaction. By lines of code, programs allocate memory much more often than they deal with files or sockets or financial transactions. So anything that requires less discipline when dealing with memory will reduce bugs a lot, compared with a similar system dealing with sockets or files. My point is it's irrelevant whether it's memory allocation or something else. If you allow yourself to slack on important problems, that habit *will* bite you in the butt in the future. Freeing your mind and the codebase of having to deal with memory leaves it in an easier place to deal with the less common higher impact leaks: file descriptors, sockets, database handles ect. (this is like chopping down the forest so you can see the trees you care about ;) ).
Re: std.data.json formal review
On Tuesday, 9 October 2018 at 18:07:44 UTC, Márcio Martins wrote: On Tuesday, 28 July 2015 at 14:07:19 UTC, Atila Neves wrote: Start of the two week process, folks. Code: https://github.com/s-ludwig/std_data_json Docs: http://s-ludwig.github.io/std_data_json/ Atila Sorry for the late ping, but it's been 3 years - what has happened to this? Has it been forgotten? Working with JSON in D is still quite painful. I presume it became vibe.data.json, there is also asdf if you're looking for some other library.
Re: Thread-safe attribution
On Sunday, 7 October 2018 at 01:59:21 UTC, Manu wrote: So I'm working on a SMT infrastructure, and expression of thread-safety is a core design mechanic... but I'm really struggling to express it in terms of the type system. I figure I'll throw some design challenges out here and see if anyone can offer some good ideas. The thing I'm trying to model is an attribute along the lines of `shared`, but actually useful ;) I'll use the attribute `threadsafe` in place of `shared`, and see where that goes. Consider: struct Bob { int x; threadsafe Atomic!int y; void m1(); void m2() threadsafe;; void overloaded(); void overloaded() threadsafe; } void func( ref Bob x, ref threadsafe Bob y) { x.x = 10; // fine x.y = 10; // fine x.m1(); // fine x.m2(); // fine x.overloaded(); // fine, use the un-threadsafe overload y.x = 10; // ERROR, a threadsafe reference can NOT modify an un-threadsafe member y.y = 10; // fine x.m1(); // ERROR, method not threadsafe x.m2(); // fine x.overloaded(); // fine, use the threadsafe overload threadsafe Bob* p = &x; // can take threadsafe reference to thread-local object } This is loosely what `shared` models, but there's a few differences: 1. thread-local can NOT promote to shared 2. shared `this` applies to members For `shared` to be useful, it should be that a shared reference to something inhibits access to it's thread-local stuff. And in that world, then I believe that thread-local promotion to shared would work like const does. I guess I'm wondering; should `shared` be transitive? Perhaps that's what's wrong with it...? A delta comparison with shared void func( ref Bob x, ref threadshared /* either shared or threadsafe*/ Bob y) { // threadsafe / shared x.x = 10; // fine / fine x.y = 10; // fine / fine uses atomics x.m1(); // fine / fine x.m2(); // fine / error cannot call shared method on unshared object x.overloaded(); // fine, use the un-threadsafe overload / fine y.x = 10; // ERROR, a threadsafe reference can NOT modify an un-threadsafe member / error y.y = 10; // fine / fine (using atomics) // Assuming these are supposed to be y not x y.m1(); // ERROR, method not threadsafe / error y.m2(); // fine / fine y.overloaded(); // fine, use the threadsafe overload / fine threadsafe Bob* p = &x; // can take threadsafe reference to thread-local object / error } Differences: Can call threadsafe method on thread local / unshared Can take threadsafe reference to thread-local object. One thing that occurred to me is that _objects_ are shared, whereas _functions/methods_ (and their parameters) are thread safe . Theadsafe is kind of like a const (as to mutable/immutable) to threading, a promise to behave correctly in the presence of threading. thread safe references therefore must not escape.
Re: Farewell (of sorts)
On Thursday, 4 October 2018 at 13:15:23 UTC, Shachar Shemesh wrote: Hello everyone, First of all, I know I've had a shorter than usual fuse of late. I'd like to apologize to everyone about this. It is the culmination of quite a few things increasing the load I'm under. One of those things is this: October 14th will be my last day working for Weka.IO. Accordingly, my involvement in D will be considerably reduced after that date, as working with D will no longer be my day job. A few of you knew that I was looking for a new job, but I postponed officially announcing this, as I wanted to see who will be taking over maintenance of Mecca. On that front, I have some good news and some bad news. The bad news is that the person taking over will not have Mecca as his sole responsibility. I am hoping he'll be able to do enough. The good news is that they put on this task my top pick for it. His name is Eyal Lotem, and is a great developer. Some of you have met him as he attended DConf three years ago. I will probably keep half an eye on the forum, and I might also be around on the Slack channels. My email address will change as a result. Feel free to find me at firstn...@lastname.biz, after applying the relevant substitutions. I think it's a better captcha than running D code :-) Shachar Please do keep around if you can. I hope to have some good news regarding D processes (the wetware kind) soon. I do hope you get to keep your job title wherever you go next, its the best I've ever seen :) So long and thanks for all the laughs, Chief Court Jester Nic
Re: DConf and outreach, e.g. ACCU [was Please don't do a DConf 2018, consider alternatives]
On Wednesday, 3 October 2018 at 07:33:44 UTC, Russel Winder wrote: I have been muttering about this a while. :-) I know, but this conference was sorta last minute realisation that it would be very beneficial to attend and I've been rather busy with it. Being at another conference clearly makes things a bit more difficult, but having registered, logged in to the Web application, a submission just requires a title, blurb and presenter bio. This might hopefully be feasible for you, albeit less than ideal. Good, although I can't guarantee that the blurb will match the final presentation because I'm sure a lot will happen in the mean time, but oh well.
Re: DConf and outreach, e.g. ACCU [was Please don't do a DConf 2018, consider alternatives]
On Wednesday, 3 October 2018 at 06:40:28 UTC, Russel Winder wrote: How about DConf continues, as it should, and people submit sessions to ACCU as part of the outreach programme. The call for sessions opens at the end of this week and lasts three weeks. Ow, that does not give me a lot of time, as I'm going to the US for a conference in the mean time.
Re: Please don't do a DConf 2018, consider alternatives
On Tuesday, 2 October 2018 at 06:26:30 UTC, Joakim wrote: [snip] Also you're out by a year :)
Re: Please don't do a DConf 2018, consider alternatives
On Tuesday, 2 October 2018 at 06:26:30 UTC, Joakim wrote: I'm sure some thought and planning is now going into the next DConf, so I'd like to make sure people are aware that the conference format that DConf uses is dying off, as explained here: https://marco.org/2018/01/17/end-of-conference-era There was a discussion about this in a previous forum thread: https://forum.dlang.org/post/bnbldtdfeppzjuthx...@forum.dlang.org Jonathan and Mike argue in that thread that DConf is great for the core team to get together in person and hash things out for D with very high-bandwidth interaction, but I pointed out that doesn't justify 95%+ of the attendees being there. If there's a real need for this, maybe get those 8-15 people together in an online video conference or offline retreat, without a bunch of hangers-on and talks. People are now experimenting with what replaces conferences, we should be doing that too. I came up with some ideas in that thread: "Have most talks prerecorded by the speaker on their webcam or smartphone, which produce excellent video these days with not much fiddling, and have a couple organizers work with them to get those home-brewed videos up to a certain quality level, both in content and presentation, before posting them online." I volunteer to help presenters do this. "Once the videos are all up, set up weekend meetups in several cities [all over the world], where a few livestreamed talks may talk place if some speakers don't want to spend more time producing a pre-recorded talk, but most time is spent like the hackathon, discussing various existing issues from bugzilla in smaller groups or brainstorming ideas, designs, and libraries for the future." I can setup an event like this in my city, where AFAIK nobody uses D, so most of it would be geared towards introducing them to the language. I estimate that you could do ten times better at raising awareness and uptake with this approach than the current DConf format, by casting a much wider net, and it would cost about 10X less, ie you get two orders of magnitude better bang for the buck. At the very least, DConf should just be a big hackathon of self-organizing groups, rather than wasting any time passively imbibing talks next to a hundred other people. I still don't think the cost of getting a hundred people in the same room for 3-4 days would be justified, but at least it would be a step in the right direction. As I'm sure has been said before, if it were just the talks it probably wouldn't be worth it. But conferences are sooo much more than just the talks. Its the conversations over breakfast/lunch/dinner/ between talks and long into the night (sometimes too long). Its the networking, the hacking, the face to face. The talks are usually pretty good too. The conference is definitely not dead, I'm going to one in San José in 2 weeks, sure the talks look really interesting but the main reason is to talk to other people to get stuff done.
Re: `shared`...
On Monday, 1 October 2018 at 09:55:41 UTC, ag0aep6g wrote: 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. Hmm, you are right. Its annoying because the use case for this is where the data is already shared and a lock has been taken. `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)? Error: pure function onlineapp.f cannot call impure function core.thread.Thread.start
Re: `shared`...
On Monday, 1 October 2018 at 08:04:38 UTC, Kagamin wrote: Shared data may need different algorithms. Yes, but those same algorithms will work on unshared (they might be slower but they will work). The reverse is not true, it can lead to race conditions. If unshared data is implicitly convertible to shared, you start to conflate shared data with unshared, so you're back to C-style sharing. No, when participating in overloading, an unshared method will be preferred over a shared method for an unshared object. Same with parameters that are not `this`. This is how you can do it: shared struct SharedBob { this(int){} void setThing(){} } alias shared SharedBob Bob; void f(ref shared Bob a, ref Bob b) { a.setThing(); // I have a shared object, can call shared method b.setThing(); // ok } int main() { auto b=Bob(0); Bob c; f(b,c); return 0; } I'm not sure what that was supposed to demonstrate.
Re: `shared`...
On Monday, 1 October 2018 at 06:06:31 UTC, ag0aep6g wrote: `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 */ } We've realised that. 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.
Re: `shared`...
On Monday, 1 October 2018 at 04:22:24 UTC, Manu wrote: Ah, good point. So, it could only be allowed if scope... struct Bob { void setThing() shared scope; } That's going to require far-reaching proliferation of `scope`. Do we infer `scope` like the other attributes? For templates (either the function or the struct it is in) and auto returning functions, I think so: definitely under -dip1000, probably also when not using -dip1000. The default for `scope` is totally backwards. :/ Alas, such is the nature of retrofitting.
Re: `shared`...
On Monday, 1 October 2018 at 03:33:16 UTC, Manu wrote: On Sun, Sep 30, 2018 at 8:20 PM Nicholas Wilson via Digitalmars-d wrote: On Monday, 1 October 2018 at 02:29:40 UTC, Manu wrote: > struct Bob > { > void setThing() shared; > } > > As I understand, `shared` attribution intends to guarantee > that > I dun > synchronisation internally. > This method is declared shared, so if I have shared > instances, > I can > call it... because it must handle thread-safety internally. seems reasonable https://github.com/dlang/dmd/pull/8782 Haha, sneaky bugger :P I reckon the patch is gonna be a lot bigger than that though! Of course, there will be updating the test suite. And Walter will probably tell you to bugzilla this. implicit conversion of mutable (i.e. no mods) to const share should be absolutely no problem, as that it rusts borrowing model (one owning mutable thread local reference and zero or more non thread local non-owning const references) and is fine. mutable to mutable shared I'm not so sure as references to otherwise owned references could escape. shared Bob* sneaky; struct Bob { void setSneaky() shared // legit as this is shared { sneaky = &this; } } void oblivious(ref shared Bob a, ref Bob b) { a.setSneaky(); // Fine b. setSneaky(); // would become not an error, but totally not fine. } unfortunately scope is not a modifier so the PR will have to be larger, oh well.
Re: `shared`...
On Monday, 1 October 2018 at 02:29:40 UTC, Manu wrote: struct Bob { void setThing() shared; } As I understand, `shared` attribution intends to guarantee that I dun synchronisation internally. This method is declared shared, so if I have shared instances, I can call it... because it must handle thread-safety internally. seems reasonable https://github.com/dlang/dmd/pull/8782
Re: BetterC and CTFE mismatch
On Wednesday, 26 September 2018 at 12:51:57 UTC, Steven Schveighoffer wrote: So anything I do at CTFE has to be betterC as well? That is a bummer. This is an artificial, and not really intended, limitation. Essentially, CTFE has to be a real function. If it's defined, it's expected to be callable from runtime as well as CTFE. But I can't see why, if you don't call from runtime, it should matter. I think this has to do with the places betterC is enforced in the compiler. I'll try to workaround this, but I would like to see this fixed. Is there anything I can do to move this forward? I'd suggest a bug report if one hasn't been made. -Steve https://issues.dlang.org/show_bug.cgi?id=18472 is an open regression on 2.078. Doesn't cover all use cases of what Sebastiaan might want though.
Re: Jai compiles 80,000 lines of code in under a second
On Friday, 21 September 2018 at 09:21:34 UTC, Petar Kirov [ZombineDev] wrote: I have been watching Jonathan Blow's Jai for a while myself. There are many interesting ideas there, and many of them are what made me like D so much in the first place. It's very important to note that the speed claims he has been making are all a matter of developer discipline. You can have an infinite loop executed at compile-time in both D and Jai. You're going to OOM pretty fast in D if you try :)
Re: DIP 1015--removal of integer & character literal conversion to bool--Final Review
On Sunday, 16 September 2018 at 23:59:18 UTC, aliak wrote: What about: enum E: bool { no, yes } void main() { E e = cast(E)(0); } Would be illegal I assume? You have an explicit cast, so no, it would be fine.
Re: int/longRe: DIP 1015--removal of integer & character literal conversion to bool--Final Review
On Sunday, 16 September 2018 at 01:47:33 UTC, Mike Franklin wrote: On Friday, 14 September 2018 at 23:08:34 UTC, Nicholas Wilson The only thing I think is missing is a flag to accelerate the process s.t. the examples f(E.a); f(E.b); g(a - b); can be made to call their int/long overloads straight away. But otherwise, er, no. A resounding yes with a small request to make the transition faster! I'm not too keen on adding a compiler flag, because then I have to worry about deprecating the compiler flag. I don't know if the bugs that this DIP fixes are serious enough to justify it. I'd be happy to add it if others are willing to voice their support for it, demonstrating sufficient demand. Or, I suppose I could add it as an option for Walter and Andrei to approve or reject on judgement day. Mike Its more about dealing with the deprecation warning. With the current specification I can tell the compiler I want the old behaviour with a cast. I should be able to tell the compiler that "Yes, I wan't this new behaviour. Please don't warn me about it.", once I have verified that my code is correct under the new behaviour. Without it, I get a (possibly quite a lot of) deprecation warnings and I have to insert a cast to the corresponding type, e.g. f(cast(int)E.a)/g(cast(long)(a - b)), to verify the behaviour under the new system and silence the deprecation warning (absolutely necessary if using `-de`). Then I have to delete them after stage 2, but what if I want to support older compilers? Well then I have to wait until they are sufficiently old enough.
int/longRe: DIP 1015--removal of integer & character literal conversion to bool--Final Review
On Friday, 14 September 2018 at 13:41:40 UTC, Mike Parker wrote: DIP 1015, "Deprecation and removal of implicit conversion from integer and character literals to bool", is now ready for Final Review. This is a last chance for community feedback before the DIP is handed off to Walter and Andrei for the Formal Assessment. Please read the procedures document for details on what is expected in this review stage: https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#final-review The current revision of the DIP for this review is located here: https://github.com/dlang/DIPs/blob/299f81c2352fae4c7fa097de71308d773dcd9d01/DIPs/DIP1015.md In it you'll find a link to and summary of the previous review round. This round of review will continue until 11:59 pm ET on September 28 unless I call it off before then. Thanks in advance for your participation. Small typo under Breaking Changes and Deprecations "4. After the time period specified in step 4 has elapsed, stage 2 can be merged." should be "4. After the time period specified in step _3_ has elapsed, stage 2 can be merged." The only thing I think is missing is a flag to accelerate the process s.t. the examples f(E.a); f(E.b); g(a - b); can be made to call their int/long overloads straight away. But otherwise, er, no. A resounding yes with a small request to make the transition faster! Thanks Mike & Mike! Looking forward to it. Nic
Re: More fun with autodecoding
On Tuesday, 11 September 2018 at 14:58:21 UTC, jmh530 wrote: Is there any reason why this is not sufficient? [1] https://run.dlang.io/is/lu6nQ0 Overloads: https://run.dlang.io/is/m5HGOh The static asserts being in the constraint affects the template candidacy viability. Being in the function body/runtime contract does not so you'll end up with onlineapp.d(17): Error: onlineapp.foo called with argument types (float) matches both: onlineapp.d(1): onlineapp.foo!float.foo(float x) and: onlineapp.d(7): onlineapp.foo!float.foo(float x) despite the fact only one of them is viable, whereas bar is fine.
Re: Mobile is the new PC and AArch64 is the new x64
On Tuesday, 11 September 2018 at 07:52:45 UTC, Joakim wrote: On Tuesday, 11 September 2018 at 07:42:38 UTC, passenger wrote: On Monday, 10 September 2018 at 13:43:46 UTC, Joakim wrote: [...] Is it possible to develop versus a NVidia Jetson, CUDA included? I think so, but I doubt anyone has ever actually tried it: https://www.nvidia.com/en-us/autonomous-machines/embedded-systems-dev-kits-modules/ As for CUDA, Nicholas Wilson said recently that he could do something with it for his DCompute project with ldc, but no idea what the current status is: https://forum.dlang.org/post/slijjptlxdrfgvoya...@forum.dlang.org I'm about to release v0.2, ETA 1 week, with math functions and a API that asserts that you use it correctly (i.e. less reliant on driver error codes which is therefore easier to develop for).
Re: extern(C++, ns) is wrong
On Wednesday, 12 September 2018 at 03:59:30 UTC, Danni Coy wrote: So my understanding is that the main issue with extern(C++,"ns") is functions that have different C++ name-spaces overriding each other in unexpected ways. How feasible is to simply disallow functions/variables/objects/... with the same name but a different "ns" being in the same module? Very. The compiler would do it automatically because they would cause name collisions.
Re: More fun with autodecoding
On Tuesday, 11 September 2018 at 13:08:46 UTC, Steven Schveighoffer wrote: On 9/10/18 7:00 PM, Nicholas Wilson wrote: On Monday, 10 September 2018 at 20:44:46 UTC, Andrei Alexandrescu wrote: On 9/10/18 12:46 PM, Steven Schveighoffer wrote: On 9/10/18 8:58 AM, Steven Schveighoffer wrote: I'll have to figure out why my specialized range doesn't allow splitting based on " ". And the answer is: I'm an idiot. Forgot to define empty :) Also my slicing operator accepted ints and not size_t. I guess a better error message would be in order. https://github.com/dlang/DIPs/pull/131 will help narrow down the cause. While this would help eventually, I'd prefer something that just transforms all the existing code into useful error messages. See my response to Andrei. -Steve Please tell me where to get one of those! But yeah, that DIP will tell you that has slicing is you problem straight away. Extracting useful information to present to the user on why hasSlicing!R is false is much trickier for the same reason that providing useful information in the current template constraint format is hard: it is a bunch of potentially unstructured logic that has already been const-folded in order to evaluate it in the first place, so you can't re-evaluate it without flushing the template cache. That's not to say that the situation can't be improved beyond what the DIP specifies, but I haven't had any brilliant ideas (and the Idea for that DIP was stolen from someone else anyway).
Re: More fun with autodecoding
On Monday, 10 September 2018 at 20:44:46 UTC, Andrei Alexandrescu wrote: On 9/10/18 12:46 PM, Steven Schveighoffer wrote: On 9/10/18 8:58 AM, Steven Schveighoffer wrote: I'll have to figure out why my specialized range doesn't allow splitting based on " ". And the answer is: I'm an idiot. Forgot to define empty :) Also my slicing operator accepted ints and not size_t. I guess a better error message would be in order. https://github.com/dlang/DIPs/pull/131 will help narrow down the cause.
Re: Debugging mixins - we need to do something
On Saturday, 8 September 2018 at 22:01:23 UTC, Manu wrote: [snip] Is anyone interested in this issue? https://github.com/dlang/dmd/pull/8677
Re: Debugging mixins - we need to do something
On Saturday, 8 September 2018 at 22:01:23 UTC, Manu wrote: TL;DR, debugging is critical and neglected. Mixin is worst offender. So, string mixin breaks the debugger. All of a sudden there is code that's executing that doesn't exist anywhere. We need a solution to this problem... As I and others have suggested before; mixin expansion should emit a `[sourcefile].d.mixin` file to the object directory, this file should accumulate mixin instantiations, and perhaps it would be ideal to also emit surrounding code for context. The debuginfo should point into that file when compiling mixin code, so that it's possible to step and inspect within the mixin. How is this done in C/C++ w.r.t macros? Point to within the macro? I initially imagined an 'expanded' copy of the file would be cool, but that doesn't work when mixins are driven by template args, since the expansion may be different for every instantiation of the surrounding code. There has been lots of chatter in the past, can we prioritise it? It would help me a lot. I think this is a high-importance ticket. I have absolutely no idea where to start with this, and I don't have anywhere near enough time to put towards my current initiatives (extern(C++) stuff). Is anyone interested in this issue? Obligatory "Bugzilla issue?". I don't think is should be too difficult to come up with a really dumb solution, just dump CompileStatement's string to a file, set the Lexer's loc to that file and let regular debug info generation do its thing. I'm busy for the next few days, but I'll take a crack at it if no-one beats me to it.
Re: This is why I don't use D.
On Friday, 7 September 2018 at 19:15:21 UTC, Jonathan M Davis wrote: Honestly, I wouldn't rely on anything beyond dub build working in a consistent manner across projects. As far as I can tell, you can't actually do anything properly custom with dub test, and I'm inclined to think that how it approaches things is outright wrong. For Dcompute I define a unittest configuration that has a main that runs tests, and the (default) library configuration excludes source files in the test directory. It seems to work fine. Admittedly it is a little different to you usual package, and there are no test specific symbols and no unit tests, and I haven't tested anything that has dcompute as a dependancy. Are you suggesting this will break users of Dcompute that run dub test in their code? If so that truly does suck, because regular unittests will not cut the mustard.
Re: This is why I don't use D.
On Thursday, 6 September 2018 at 16:50:32 UTC, H. S. Teoh wrote: Again, this strongly suggests the idea I've mentioned a few times now: *all* packages on code.dlang.org needs to be run through a CI tester, and success/failure to compile should be reported back to dlang.org somehow. Then in the search results and in the package's home page, there should be a prominently-displayed notice of which compiler versions work / don't work with the package. This gives users the information they need to make the right decision (e.g., the last known compiler that compiles this package is 2.060, so don't bother, move on.). And this *must* be automated, because nobody has the time or energy to manually test every package against every known compiler release and manually update code.dlang.org. And doing it manually tends to quickly get out of date, not to mention the chance of human error. T How would this work for packages that cannot be built by DMD? Or that have no CI infrastructure but are maintained? *cough* DCompute *cough*
Re: extern(C++, ns) is wrong
On Wednesday, 5 September 2018 at 13:53:15 UTC, Jonathan M Davis wrote: Very well said, thanks. Based on everything Walter said in the previous thread, it honestly seems to me to be primarily like he just can't give up on the idea that D has to worry about modeling C++ namespaces. That is the conclusion I came to as well. What Walter did makes perfect sense if you assume that D needs to care about namespaces when using the C++ symbol in D, but the conclusion of the rest of us when looking at the problem has been that D really doesn't need to care about the namespaces beyond mangling, because D modules already solve the problem. I think this is the key insight, everything else follows from this. But regardless, I'm with you and Manu at this point in that I don't understand why extern(C++, "Namespace") isn't a clearly better (and simpler) solution overall. But maybe we'll get lucky and after Walter has thought about it long enough, he'll come around. Either way, per the current process, we would clearly need a DIP even if Walter already agreed. So, the next step is to write a DIP, and hopefully it can be written well enough that it's appropriately convincing unlike everything that has been argued thus far. Indeed, It is a pity the DIP pipeline is so full. Manu, what timeline do you ideally need this by? and do you have an implementation? Putting it into LDC is probably going to be the fastest given there are 3 high impact DIPs in the queue already + however long takes to get this trough and then implemented.
Re: extern(C++, ns) is wrong
On Wednesday, 5 September 2018 at 08:30:25 UTC, Walter Bright wrote: On 9/4/2018 10:16 PM, Manu wrote: I'm serious, you can have your cake, and potentially, I could have my cake too, and everybody would be happy... nobody would be sad. If it is the same, It is I provided solutions in those threads. The incomplete example code did not make use of them. Those "solutions" do not satisfactorily solve the problem, hence: I have to contort my code to undo a thing that should never have been there. It's truly >embarrassing. I can't show this to people. ***I can not present my work to stakeholders with a straight face*** I don't think I could either. I don't know why you have "no option" left. There is one: add it to LDC, which will accept it, see https://github.com/ldc-developers/ldc/issues/2800#issuecomment-410817126 but this is a language feature we (LDC) would rather not have an upstream diff for. This is a prime example of an industry blocker if ever there was. Yes there has been a lot of talking past each other, but surely you understand _what_ Manu is wanting even if you seem to think that your workarounds (which you called solutions) are sufficient. It is backwards compatible and solves a clear need, I don't see why this is such a contentious issue.
Re: DIP25/DIP1000: My thoughts round 2
On Sunday, 2 September 2018 at 05:14:58 UTC, Chris M. wrote: Hopefully that was coherent. Again this is me for me to get my thoughts out there, but also I'm interested in what other people think about this. Thanks! Please add anything you think is missing to https://github.com/dlang/dlang.org/pull/2453 since Walter doesn't seem to be interested.
Re: -op can be quite strange
On Saturday, 1 September 2018 at 14:48:55 UTC, Jonathan Marler wrote: Note that we would want this to be a new option so as not to break anyone depending on "-op" semantics. Maybe "-om" for "output path based on 'Module' name"? LDC has this already as -oq, FWIW.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Thursday, 30 August 2018 at 23:03:57 UTC, Walter Bright wrote: On 8/25/2018 4:49 PM, Nicholas Wilson wrote: Run semantic3 on the constructor independent of the requirement to destruct already constructed objects. If the constructors is nothrow then there is no need to have the destructors run or the eh code at all, because no Exceptions can be thrown (an Error may be thrown but that will kill the program). This is how I intend to fix it after I refactor semantic3. A function can be made nothrow by: try { } catch (Exception e) { ... handle it locally ... } Then I should have said: no exceptions can propagate, which is the real problem. Also, your proposal is ignoring the destructors, which is literally what the compiler does now. It was implicit in that the throwing case would call the destructors in the event of an exception (otherwise the bug ain't fixed). This formulation is to reduce the amount of breakage, which was the problem last time. Yes this will break (as in code breakage) @safe ctors calling @system dtors but, such is life. The ctor probably shouldn't be throwing in the first place. I'll probably add -vthrowingctor and -vthrowingdtor as well since this will be a perf hit in the case of a throwing ctor. Sorry for any confusion.
Re: splitting general into Technical and less technical
On Wednesday, 29 August 2018 at 16:38:48 UTC, Ali Çehreli wrote: On 08/22/2018 10:20 PM, Nicholas Wilson wrote: That reminds me, what happened to our conversation with Ali Çehreli about splitting general [newsgroup/forum] into Technical and less technical? Even I remember that conversation. :) I don't remember who were involved but as soon as I opened the discussion at the next dinner table, I was discouraged; I think people were against the idea. Ali It was You, me, Matthias Lang, Shachar, Liran, Don(?) and maybe some more. That is a pity, it would be nice to have a list that has a better SNR than general. Greater industry participation on the technical matters would be a nice thing to have.
Re: Is @safe still a work-in-progress?
On Wednesday, 29 August 2018 at 08:35:30 UTC, Walter Bright wrote: On 8/28/2018 10:18 PM, Nicholas Wilson wrote: Bugzilla is not documentation. These are language changes they need to be in release notes and the spec. You asked for a clue: "we have no clue WTF its supposed to do or why the changes are being made" and there it is. There are no barriers to reviewing the idea nor the implementation. I don't know how much more blunt I can be while still being professional about it: _this must be documented properly_. This is not just about us reviewing it, this is also about people using it. Think about it this way: I'm a new user and I hear that D is supposed to be memory safe. Am I going to trawl through bugzilla to find about the features of this memory safety? Suppose I do a search for "dlang memory safety" on how I can use this feature. What does a search bring up? First hit: https://dlang.org/spec/memory-safe-d.html Gives me a link to https://dlang.org/articles/safed.html, not very helpful, and to @system/@safe/@trusted, that tells me a bunch of things I'm not allowed to do in safe code. Second hit: https://dlang.org/blog/2016/09/28/how-to-write-trusted-code-in-d/ More (admittedly better) info on @system/@safe/@trusted Third Hit: https://forum.dlang.org/thread/ofkjuq$or6$1...@digitalmars.com welp the forum is down, next! Fourth hit: https://wiki.dlang.org/Memory_Management Fifth hit: https://dconf.org/2017/talks/bright.pdf Some stuff about scope, possibly not up to date(!). Sixth hit is Adam Ruppe's fork of the spec page on memory safety Seventh is https://news.ycombinator.com/item?id=12391370 Number 8: https://www.meetup.com/en-AU/SeaLang/events/246692611/ 9: https://www.reddit.com/r/cpp/comments/6b4xrc/walter_bright_believes_memory_safety_will_kill_c/ 10: is the Wikipdia page on D. Searching for "dlang scope" brings up scope(exit) & friends and some old forum posts including https://forum.dlang.org/thread/obfftm$2m3j$1...@digitalmars.com which feels like déjà vu, followed by a bunch of irrelevant links to various parts of the spec. That was on a not anonymous search, I know precisely what I'm looking for, and the closest thing I found was 4/5ths the way down a 42 slide PDF with no annotations from a year ago. Even someone relatively familiar is going to look at the spec and the changelog, and they're not going to find anything BECAUSE ITS NOT THERE! You know where it is? Bugzilla, because that's where Walter thinks documentation should go.
Re: Is @safe still a work-in-progress?
On Wednesday, 29 August 2018 at 05:04:22 UTC, Walter Bright wrote: On 8/25/2018 4:09 AM, Nicholas Wilson wrote: On Saturday, 25 August 2018 at 02:25:41 UTC, Walter Bright wrote: I'm not hostile to debate. I just don't care for "this is uncharted territory, so let's do nothing" which has been going on for probably 4 years now, coincident with "scope is incomplete, D sux". I.e. lead, follow, or get out of the way :-) Document it Already done: https://issues.dlang.org/show_bug.cgi?id=19097 Bugzilla is not documentation. These are language changes they need to be in release notes and the spec.
Re: D now has a dangerous competitor
On Tuesday, 28 August 2018 at 08:39:20 UTC, bauss wrote: The following language is a dangerous competitor to D. https://github.com/joaomilho/Enterprise Thats very funny, but I found Rockstar even funnier.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Monday, 27 August 2018 at 01:10:17 UTC, Manu wrote: On Sun, 26 Aug 2018 at 18:08, Manu wrote: Actually, I'm really mostly interested in DX12 shader output right now... I think there are tools that can convert LLVM to DX shaders? I haven't looked into it yet, but it's on my backlog. Next would be SPIRV for Vulkan. This looks promising: https://blogs.msdn.microsoft.com/directx/2017/01/23/new-directx-shader-compiler-based-on-clangllvm-now-available-as-open-source/ I would love to do it but that repo is _horribly_ organised and resembles nothing like a backend and appears to lack relevant LLVM IR tests. SPIRV for Vulkan would be doable if there is support from the Vulcan folks when the SPIRV backend is upstreamed to LLVM.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Monday, 27 August 2018 at 00:26:35 UTC, Manu wrote: Yeah, i've been following both those efforts. I don't have any free time to motivate this stuff on my own right now. I'm just listing all the things (because Walter asked me to). Fair enough. I suppose you'd need namespaces working first anyway to get much out of those tools. Incidentally, what's the state of DCompute stuff lately? Did the front-end ever get a polish pass? That's actually another really high-value ticket that I could use to gain a lot of leverage, if it's at a place where you'd want to show it to developers... Mostly, just a good set of step-by-step docs would make all the difference. Mostly I've been stupidly busy with uni but I'm now FREEE! I'm going to wait for the LLVM 7 release (very soon) and then get things going again: testing, atomics, docs, API contracts etc. I'll post to Announce when I've done all that. I'm still waiting for the Khronos folks to get back to me to get the SPIRV backend into upstream LLVM. You're mostly interested in CUDA, right? That should be much easier to get shipshape.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Sunday, 26 August 2018 at 23:39:32 UTC, Manu wrote: We could really use robust tools to produce a matching C++ .h file from the extern symbols in a D module, and likewise a .di file from a C/C++ header. This category of tooling has many existing instances, it's overwhelming. As far as I can tell, they're all experimental, or broken, or designed only to target a specific application (DMD), etc. I think it would be an advantage if there were *one* tool, that works, in both directions, which is advertised, recommended, and maintained by the core group. I've evaluated them all before at various points in time, but the landscape keeps shifting. Someone, please give me a prominent hyperlink to the solution that *works*, and instructions. I don't have energy to re-do comprehensive evaluations on this front, I'm spent. Agree on one, make it the official one, and then track bugs against it in bugzilla? I know this isn't quite what you asked for but you should get in contact with Iain to generalise https://github.com/dlang/dmd/pull/8591/files As for the other direction, I'd suggest talking to Atila to get app working for your use cases. This is about as official as its going to get.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Sunday, 26 August 2018 at 20:55:04 UTC, Walter Bright wrote: On 8/26/2018 12:34 PM, Manu wrote: I work at a company with a thousand engineers, all VS users, D could find home there if some rough edges were polished, but they *absolutely must be polished* before it would be taken seriously. It is consistently expressed that poor VS integration is an absolute non-starter. I will tiresomely ask again, do you have a list of each and every aspect of the poor integration? Not to put words in his mouth, but: * rvalue references: see recent DIP * https://github.com/ldc-developers/ldc/issues/2800 Really a DMD issue * https://issues.dlang.org/show_bug.cgi?id=19179 probably more.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Sunday, 26 August 2018 at 10:17:51 UTC, Walter Bright wrote: I'm not sure what you're referring to. I'm referring to the specified message, and the example: struct Array { int[] _payload; ~this() // (2) { import core.stdc.stdlib : free; free(_payload.ptr); // (3) } } class Scanner { Array arr; this() @safe {} // (1) } In order for (1) to be @safe, then the destructor it calls for arr (2) must also be @safe. But the destructor calls free() (3), which is not @safe. Therefore, the compilation fails. Inference does not solve this problem, because (2) is inferred as @system. Yes but if Scanners constructor is nothrow then all is fine, since it won't unwind unless an error is thrown in which case it game over anyway.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Saturday, 25 August 2018 at 20:52:06 UTC, Walter Bright wrote: On 8/25/2018 3:52 AM, Chris wrote: On Friday, 24 August 2018 at 19:26:40 UTC, Walter Bright wrote: Every programmer who says this also demands new (and breaking) features. "Every programmer who..." Really? You want to remove autodecoding (so do I) and that will break just about every D program in existence. For everyone else, it's something else that's just as important to them. For example, Shachar wants partially constructed objects to be partially destructed, a quite reasonable request. Ok, but consider the breakage: struct S { ~this() {} } class C { S s; this() nothrow {} } I.e. a nothrow constructor now must call a throwing destructor. This is not some made up example, it breaks existing code: https://github.com/dlang/dmd/pull/6816 If I fix the bug, I break existing code, and apparently a substantial amount of existing code. What's your advice on how to proceed with this? Run semantic3 on the constructor independent of the requirement to destruct already constructed objects. If the constructors is nothrow then there is no need to have the destructors run or the eh code at all, because no Exceptions can be thrown (an Error may be thrown but that will kill the program). This is how I intend to fix it after I refactor semantic3.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Saturday, 25 August 2018 at 20:19:44 UTC, Walter Bright wrote: On 8/25/2018 6:32 AM, Timon Gehr wrote: (Or at least, not wrong. Using e.g. `void*` instead of an incompatible type would already be an improvement.) Making it void* is a reasonable idea. If/when (I really hope the latter) DIP 1011 gets in it should be extern(delegate) with `ref typeof(this)` as the first parameter.
Re: Is @safe still a work-in-progress?
On Saturday, 25 August 2018 at 02:25:41 UTC, Walter Bright wrote: I'm not hostile to debate. I just don't care for "this is uncharted territory, so let's do nothing" which has been going on for probably 4 years now, coincident with "scope is incomplete, D sux". I.e. lead, follow, or get out of the way :-) Document it and we will help you get it reviewed and merged. Until you do that we will stay in your way. Heck, once we understand it we may even lead, but we can't do that if we have no clue WTF its supposed to do or why the changes are being made. At the very least PRs need detailed changelog entries and preferably spec updates and revisions to the DIP1000 proposal document. Heck even a wiki page would be useful. I'm trying to make the spec page on memory safe programming the authoritative source see https://github.com/dlang/dlang.org/pull/2453
Re: D is dead
On Saturday, 25 August 2018 at 07:56:55 UTC, Walter Bright wrote: On 8/24/2018 6:34 AM, Shachar Shemesh wrote: No, unlike what I suggest, that doesn't work without carefully reviewing every single place you put it to see whether the constructor actually supports destructing a partially constructed object. All D objects are default-initialized before the constructor sees it (unlike C++). A destructor should be able to handle a default-initialized object. Then we should add a switch to inject a unittest to run a destructor on a default initialisable object. i.e. if it has a static opCall or an @disable this(); then don't otherwise do. Otherwise this is a well disguised instance of faith based programming.
Re: Dicebot on leaving D: It is anarchy driven development in all its glory.
On Saturday, 25 August 2018 at 01:43:19 UTC, Walter Bright wrote: On 8/24/2018 4:22 PM, tide wrote: struct SomeStruct { void foo() { // use SomeStruct } } void broken() { void function() foo = &SomeStruct.foo; foo(); // runtime error, isn't actually safe uses wrong calling convention as well } Not really lack of feature so much as there exists broken code. This has been valid code for god knows how long. At some point it was usable in @safe, but it looks you can't take an address of a member function without "this" as well in safe anymore. That's because it isn't safe. But being able to take the address is important for system work. The stupid thing is you _have_ to cast (which is unsafe) the return type to be correct. This could be solvable with DIP1011 to make &SomeStruct.foo return `extern(delegate) void function(ref Foo)` although it makes no explicit mention other than "member functions be implicitly convertible to extern(delegate) functions".
Re: D is dead
On Friday, 24 August 2018 at 09:58:13 UTC, Walter Bright wrote: On 8/23/2018 5:02 PM, Nicholas Wilson wrote: am currently up against a ~thousand headed hydra~ thousand line function . Good times :-) Tell me about it. I'm now wading through its carcass in review. I will split it up but it takes a lot of effort.
Re: D is dead
On Thursday, 23 August 2018 at 17:02:12 UTC, Shachar Shemesh wrote: How much time or money exactly has Weka spent on getting this issue and other "critical" bugs fixed? Weka is paying prominent D developers as contractors. We've had David Nadlinger and currently employ Johan Engelen. Both said they are cannot fix this particular bug. If you can, feel free to contact me off-list, and I'm fairly sure we can get the budget for you to work on it. The same goes for anyone else on this list. I'll be taking a good stab at it. I am currently wading through the swamps of Semantic Analysis and am currently up against a ~thousand headed hydra~ thousand line function .
Re: D is dead
On Thursday, 23 August 2018 at 07:00:01 UTC, Iain Buclaw wrote: On Thursday, 23 August 2018 at 06:34:04 UTC, Shachar Shemesh wrote: On 23/08/18 09:17, Jacob Carlborg wrote: I don't see why we just can't add support for scoped lazy parameters. It's already in the language just with a different syntax (delegates). That would probably be an easy fix (last famous words :)). I guess it would be better if it could be inferred. Here's the interesting question, though: is this *going* to happen? We've known about this problem for ages now. No movement. It's on my todo list, however I've instead been doomed to work on higher priority things. More generally though, some time should be spent on trying out things in the spirit of "will it blend" just to see what happens. Putting effort towards having a more homogeneous environment in the language should in the long run pay its dividends. Is there even any way to escape a lazy? If no, then lazy is identical to scope lazy. E.g. https://run.dlang.io/is fails to compile
Re: D is dead (was: Dicebot on leaving D: It is anarchy driven development in all its glory.)
On Thursday, 23 August 2018 at 03:50:44 UTC, Shachar Shemesh wrote: No, no and no. I was holding out on replying to this thread to see how the community would react. The vibe I'm getting, however, is that the people who are seeing D's problems have given up on affecting change. It is no secret that when I joined Weka, I was a sole D detractor among a company quite enamored with the language. I used to have quite heated water cooler debates about that point of view. Every single one of the people rushing to defend D at the time has since come around. There is still some debate on whether, points vs. counter points, choosing D was a good idea, but the overwhelming consensus inside Weka today is that D has *fatal* flaws and no path to fixing them. A list, please? Now that I actually have time to fix things, I intend to do so. And by "fatal", I mean literally flaws that are likely to literally kill the language. And the thing that brought them around is not my power of persuasion. The thing that brought them around was spending a couple of years working with the language on an every-day basis. And you will notice this in the way Weka employees talk on this forum: except me, they all disappeared. You used to see Idan, Tomer and Eyal post here. Where are they? This forum is hostile to criticism, and generally tries to keep everyone using D the same way. If you're cutting edge D, the forum is almost no help at all. Consensus among former posters here is that it is generally a waste of time, so almost everyone left, and those who didn't, stopped posting. And it's not just Weka. I've had a chance to talk in private to some other developers. Quite a lot have serious, fundamental issues with the language. You will notice none of them speaks up on this thread. They don't see the point. That reminds me, what happened to our conversation with Ali Çehreli about splitting general into Technical and less technical? Not to imply that the problems listed are purely technical. There is a distinct lack of well documented direction beyond incremental improvements. No technical project is born great. If you want a technical project to be great, the people working on it have to focus on its *flaws*. The D's community just doesn't do that. To sum it up: fatal flaws + no path to fixing + no push from the community = inevitable eventual death. With great regrets, Shachar Indeed. It is time to push, then. Nic
Re: Is @safe still a work-in-progress?
On Tuesday, 21 August 2018 at 14:31:02 UTC, Atila Neves wrote: The problem is that the code we write doesn't deal directly with pointers - see the recent confusion in this forum over where `scope` on the left applies to the `this` pointer or the one returned by the member function. Kagamin just told me I needed to use `return` instead of `scope` to get things to work and I'm still not sure why. The way I think about it is if you have a function that takes a pointer, any pointer, and either returns it or a pointer derived from it (dereferencing or indexing) that argument must be marked `return`. In your case it was a pointer derived from `this` so `return` must be applied to `this`.
Re: Friends don't let friends use inout with scope and -dip1000
On Tuesday, 21 August 2018 at 10:57:15 UTC, Atila Neves wrote: On Tuesday, 21 August 2018 at 09:50:46 UTC, Atila Neves wrote: On Monday, 20 August 2018 at 15:55:54 UTC, Kagamin wrote: On Monday, 20 August 2018 at 13:02:23 UTC, Atila Neves wrote: On Monday, 20 August 2018 at 12:56:42 UTC, Kagamin wrote: Error: address of variable s assigned to gInt with longer lifetime Looks safe to me. With dmd 2.081.2 on Arch Linux, the code above compiles with no error message. Never mind, I forgot to use -dip1000. Ok, cool, so _why_ does it work as intended now? Also, if I have to remember to annotate correctly, surely this is a massive hole in @safe dip1000? MyStruct is not a template, I presume `return` would get inferred if it was. But yeah that is annoying.
Re: Friends don't let friends use inout with scope and -dip1000
On Monday, 20 August 2018 at 09:31:09 UTC, Atila Neves wrote: On Friday, 17 August 2018 at 13:39:29 UTC, Steven Schveighoffer wrote: // used to be scope int* ptr() { return ints; } scope inout(int)* ptr() inout { return ints; } Does scope apply to the return value or the `this` reference? I assumed the return value. I think I've read DIP1000 about a dozen times now and I still get confused. As opposed to `const` or `immutable`, `scope(T)` isn't a thing so... I don't know? What usually happens is that qualifiers to the left of the name apply to the return type and those to the right apply `this`. Not that that _should_ make any difference since lifetime ints == lifetime this What happens if you remove the return type? (i.e. scope auto) And write what instead? scope ptr() inout { return ints; } ?
Re: static foreach, expression-Based Contract Syntax and better error messages
On Tuesday, 7 August 2018 at 08:20:55 UTC, Basile B. wrote: On Tuesday, 7 August 2018 at 07:33:49 UTC, Nicholas Wilson wrote: so the following void foo(As...)(As as) in { static foreach (a ;as) assert(a>0); } do { } void main() { foo(1,2,3,4,5); } passes and compiles, whereas void foo(As...)(As as) static foreach (a ;as) in(a>0) { } void main() { foo(1,2,3,4,5); } does not compile. I suppose thats fair enough, there is after all a not very verbose workaround. I only note this because in researching examples for my multiple template constraints DIP[1], I noticed while I can make individual clauses easier to understand, I realised that recursive templates clauses are still going to be horrible so it would be useful to be able to do void foo(As...)(As as) static foreach (alias A ;As) if(isFoo!A) { //... } [...] Should this work? And is this something people would like to see added to the DIP? No. At this point syntax of contracts or constraints is getting *really* mad. I think it's better to put the static loop in the function body, especially since with assert you can format a nice message, while not with constraints. I have decided to make the DIP be consistent with `in` contracts: that is allow both an expression form and block statement form. The block state meant can use static foreach to static assert on variadic lists, while the expression from is more concise.
Re: DIP 1017--Add Bottom Type--Community Review Round 1
On Friday, 10 August 2018 at 13:15:46 UTC, Dukc wrote: The benefit would be that null can be a regular pointer constant (enum null = typeof(&assert(false)).init) instead of a symbol with special meaning. I'd think it makes compiler rules less complex. I disagree. Another advantage is that you could pass null as an argument for a function template which wants to know it's element type (but of course not instantiate it) like any other pointer. Of what _practical use_ is that?
Re: DIP 1017--Add Bottom Type--Community Review Round 1
On Friday, 10 August 2018 at 11:31:02 UTC, Dukc wrote: On Friday, 10 August 2018 at 11:28:38 UTC, Dukc wrote: One example comes to mind: is(typeof(null) == typeof(assert(0))). meant is(typeof(*null) == typeof(assert(0))) How is that a good thing??? Also that is not specified in the dip. I would expect that to fail because both will produce error nodes in the AST, only assert(0) is considered special under this DIP.
Re: DIP 1017--Add Bottom Type--Community Review Round 1
On Thursday, 9 August 2018 at 10:47:37 UTC, Stefan Koch wrote: Regarding the rationale: It should be pointed out that this is a further complication of the type-system (which is already more complex than what c++ has). That does impact generic code. My own experience with generic code has show that it is very hard (practically impossible) to write correct code, (correct meaning here working as intended, when instantiation succeeds) even when using template constraints. Indeed. There is no explanation of when the additional optimizations would be actually relevant, Usually functions that don't return abort the program anyway. I presume Walter is talking about considering all branches that don't return to be cold and "outlining" them as much as possible so as to not pollute icache, which he already implemented. So I assume he's talking about propagating that information? There not even an example piece of code where the newly enabled optimizations would make an impact. The point about other system languages having this feature is actually the most substantiated one :) It was about that is was required to be competitive which I find to be a bizarre claim. But we already have this in LDC, GDC probably has something similar (whatever corresponds to __attribute__(noreturn)),and if you care about perf you are not using DMD.
Re: DIP 1017--Add Bottom Type--Community Review Round 1
On Thursday, 9 August 2018 at 03:02:55 UTC, Mike Parker wrote: This is the feedback thread for the first round of Community Review for DIP 1017, "Add Bottom Type": https://github.com/dlang/DIPs/blob/8274b0f600075e4553b41c31f4b77be2d917bb40/DIPs/DIP1017.md All review-related feedback on and discussion of the DIP should occur in this thread. The review period will end at 11:59 PM ET on August 24, or when I make a post declaring it complete. At the end of Round 1, if further review is deemed necessary, the DIP will be scheduled for another round. Otherwise, it will be queued for the Final Review and Formal Assessment by the language maintainers. Please familiarize yourself with the documentation for the Community Review before participating. https://github.com/dlang/DIPs/blob/master/PROCEDURE.md#community-review Thanks in advance to all who participate. All of my points made in the draft review still stand, i.e. that this should be an attribute or pragma. Note that this feature is already supported by LDC as an attribute. The benefit that this DIP provides are: "documentation" (rationale point 2) and optimisation (rationale points 1 & 4). The claim made by Point 3 is dubious and unsubstantiated at best. Rationale point 2 comes in the form of rendered documentation and the source code. Rendered documentation, regardless of the form used should be able to convey that a function does not return. Reading the source it should be easily determinable that a function does not return, use of an suitably named attribute or pragma (i.e. pragma (noreturn) or @noreturn) makes it immediately obvious. Returning a type named "Tbottom" absolutely does not, "never_t" as suggested in the draft review is better but is not strictly better than an attribute or pragma but, IMO is still worse. The optimisation benefits provided by dead code elimination may be significant, but again this information is equally well conveyed to the compiler by an attribute or pragma. The hardcoded list of symbols, will provide the vast majority of those gains so extending this to user code will provide very marginal benefit, especially with a aggressively optimising compiler (e.g. LDC, GDC) that will propagate that information anyway. The downsides of this DIP are the breaking changes and unneeded complexity. Generic code that checks `is(T==void)` or `is(ReturnType!F == void)` will break, as will code that uses the return value of a function that happens to be inferred to return no type, use of the ternary ?: will now no longer always be the common type of the second and third operands. The complexity will manifest itself as making error messages more confusing, making the learning curve steeper than it needs to be and the implementation. The DIP makes the claim that: * "[@noreturn] has the awkward result of a function specifying it has a return type T, but never returns that type". When it is deliberate (such as annotating a fatal error function) the is almost exclusively `void` (I know of no examples to the contrary). * "[With @noreturn] other potential uses of a bottom type will not be expressible". What other? Documentation and optimisation definitely can be, the are in LDC since a long time, there are no other substantiated benefits listed in the DIP. If this DIP were to make the claim that type inference and propagation would catch bugs, then perhaps it would make more sense than an attribute or pragma, but it would have to be convincing that resulting code breakage would be worth it.
static foreach, expression-Based Contract Syntax and better error messages
so the following void foo(As...)(As as) in { static foreach (a ;as) assert(a>0); } do { } void main() { foo(1,2,3,4,5); } passes and compiles, whereas void foo(As...)(As as) static foreach (a ;as) in(a>0) { } void main() { foo(1,2,3,4,5); } does not compile. I suppose thats fair enough, there is after all a not very verbose workaround. I only note this because in researching examples for my multiple template constraints DIP[1], I noticed while I can make individual clauses easier to understand, I realised that recursive templates clauses are still going to be horrible so it would be useful to be able to do void foo(As...)(As as) static foreach (alias A ;As) if(isFoo!A) { //... } and this was the closest thing syntactically. (yes I know I could have use allSatisfy here but for thing like un-recursing ptrdiff_t countUntil(alias pred = "a == b", R, Rs...)(R haystack, Rs needles) if (isForwardRange!R && Rs.length > 0 && isForwardRange!(Rs[0]) == isInputRange!(Rs[0]) && is(typeof(startsWith!pred(haystack, needles[0]))) && (Rs.length == 1 || is(typeof(countUntil!pred(haystack, needles[1 .. $]) its not so simple) Should this work? And is this something people would like to see added to the DIP? [1]:https://github.com/thewilsonator/DIPs/blob/template-constraints/DIPs/DIP1xxx.md
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 7 August 2018 at 05:58:17 UTC, Walter Bright wrote: On 8/6/2018 8:14 PM, Nicholas Wilson wrote: Yes, but only for a single instance of the namespace. In the general case no, see the first reply in https://forum.dlang.org/post/xdaedmlbbqtztiqcw...@forum.dlang.org The idea is to not have a namespace That is what we have been arguing for all thread... I don't see what making an alias to a namespace has to do with it. That was your suggested workaround, was it not? If not you have _really_ lost me.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 7 August 2018 at 02:25:32 UTC, Walter Bright wrote: Let's see if we can find some common ground. The boilerplate I suggested seems to enable DPP to generate working code that behaves "as if" the namespace scope is not there, even for nested namespaces. Is this correct? Yes, but only for a single instance of the namespace. In the general case no, see the first reply in https://forum.dlang.org/post/xdaedmlbbqtztiqcw...@forum.dlang.org
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Tuesday, 31 July 2018 at 23:02:16 UTC, Rubn wrote: One thing I don't like is that the C++ namespaces takes the name. So if you try to import a module that has C++ namespace of the same with the existing module, then you'll get an error. For effectively no reason, because as you say that namespace is useless and just occupies a name that could otherwise be used for the module name. Indeed, case in point: std
string literal string and immutable(char)* overload ambiguity
is there any particular reason why void foo(string a) {} void foo(immutable(char)* b) {} void bar() { foo("baz"); } result in Error: foo called with argument types (string) matches both: foo(string a) and: foo(immutable(char)* b) especially given the pointer overload is almost always void foo(immutable(char)* b) { foo(b[0 .. strlen(b)]); } and if I really want to call the pointer variant I can with foo("baz".ptr); but I can't call the string overload with a literal without creating a temp. I think we should make string literals prefer string arguments.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 30 July 2018 at 02:53:43 UTC, Nicholas Wilson wrote: On Monday, 30 July 2018 at 02:15:57 UTC, Walter Bright wrote: On 7/29/2018 1:45 PM, Manu wrote: There's no way you'll get a bug report from someone complaining they can't multiply define symbols in the same scope. That's common sense. But then you cannot interface with this C++ code: namespace ab { void foo(); } namespace cd { void foo(); } Why would you find this acceptable? But you can if ab and cd are in different modules. The point is to decouple the mangling from the scope, leave the scope to D's module system, leave the mangling to extern(C++, "foo") Not that this alleviates Alita's issues at all.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 30 July 2018 at 02:15:57 UTC, Walter Bright wrote: On 7/29/2018 1:45 PM, Manu wrote: There's no way you'll get a bug report from someone complaining they can't multiply define symbols in the same scope. That's common sense. But then you cannot interface with this C++ code: namespace ab { void foo(); } namespace cd { void foo(); } Why would you find this acceptable? But you can if ab and cd are in different modules. The point is to decouple the mangling from the scope, leave the scope to D's module system, leave the mangling to extern(C++, "foo")
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Monday, 30 July 2018 at 02:09:37 UTC, Walter Bright wrote: On 7/29/2018 1:52 PM, Manu wrote: On Sun, 29 Jul 2018 at 05:10, kinke via Digitalmars-d wrote: [...] so that a straight C++ namespace => D module hierarchy mapping would probably be required in the general case: ``` // cppns/package.d module cppns; extern(C++, "cppns") { void foo(); } // cppns/nested/package.d module cppns.nested; extern(C++, "cppns") extern(C++, "nested") { void foo(); } ``` It's beautiful! (but I added the quotes in there for you; without quotes is existing defined behaviour which introduces scopes) But that works now, I suggested it, and you didn't find it acceptable !!?!! No it doesn't. You missed (but I added the quotes in there for you; without quotes is existing defined behaviour which introduces scopes) With the above extern(C++, "cppns") (note the quotes) defines the mangling, the D module defines the scope. This is consistent with e.g. how the druntime bindings to C's standard library (with extern(C)) are used with extern(C) only affects the mangling, not introducing a scope, only that with extern(C++) you can have multiple things in different namespaces all called the same thing, so you actually need the scope as well as the mangling.
Re: Is there any good reason why C++ namespaces are "closed" in D?
On Sunday, 29 July 2018 at 03:20:29 UTC, Walter Bright wrote: On 7/28/2018 11:18 AM, Manu wrote: Make a PR that implements namespace as a string... I will use that fork of D forever. 1. Look how it is mangled on the C++ side. (Use "grep" on the object file.) 2. Use: pragma(mangle, "the mangled name") That a) doesn't scale in a real dynamic codebase (think templates), and b) is platform dependent and so isn't a proper solution. Honestly the only problem with Manu's suggestion is you can't expose `a::foo` and `b::foo` with the same signature within the same module due to (D) name collisions, although I don't see any reason why we can't do both. Then again I don't see any (non philosophical/compiler front end internal) issue why you can't reopen a namespace. D is supposed to be pragmatic, after all.
Re: Looking for the article comparing D to Ada and others
On Thursday, 26 July 2018 at 02:21:58 UTC, Ali Çehreli wrote: On 07/25/2018 04:27 PM, Nicholas Wilson wrote: On Wednesday, 25 July 2018 at 21:59:52 UTC, Ali Çehreli wrote: Somebody had posted an article here on how well different languages matched certain requirements of a certain coding safety standards. I remember D was doing pretty well and I think Ada (or SPARK?) was included as well. What article? Where? Thank you, Ali https://dlang.org/blog/2018/06/20/how-an-engineering-company-chose-to-migrate-to-d/ Thanks but no. :) The article I'm looking for was specifically for comparing languages against each paragraph (point?) of a safety spec. Ali Oh, I vaguely remember that too. I think it was the MISRA spec? Or was it JSF or something else? Can't quite remember, sorry.
Re: Looking for the article comparing D to Ada and others
On Wednesday, 25 July 2018 at 21:59:52 UTC, Ali Çehreli wrote: Somebody had posted an article here on how well different languages matched certain requirements of a certain coding safety standards. I remember D was doing pretty well and I think Ada (or SPARK?) was included as well. What article? Where? Thank you, Ali https://dlang.org/blog/2018/06/20/how-an-engineering-company-chose-to-migrate-to-d/
Re: DIP 1016--ref T accepts r-values--Community Review Round 1
On Saturday, 21 July 2018 at 04:09:25 UTC, Jonathan M Davis wrote: Honestly, I think we're just coming from points of view that are too different. IMHO, the core use case for ref is for a function to mutate an argument and have that result progagate to the argument, I think the critical point here is that the the caller is free to ignore the refness of the arg by creating a temporary and not using it further. and having ref accept rvalues is not only counter to that, but it risks bugs that are currently impossible. A class of bugs I believe to be self-evident and incredibly sparse. I think that having a way to accept rvalues by ref for functions where you want to avoid copying is potentially useful but not particularly critical. On the other hand, you seem to see little or no value in having parameters that are intended to only accept lvalues As the API author you can @disable the rvalue overload, but nothing you do can stop the caller supplying an unused temporary to the ref argument. Yes you can discourage them with docs/@disabled overload sets/ whatever, but you can't stop them. That is no different to today. This DIP may lessen your ability to discourage them from misusing it, but you can't stop a stubborn idiot, and that is not the audience D is targeting. and see great value in having functions that accept rvalues by ref in order to avoid copying. It is not just the avoiding copying, if it were I'm not sure I'd support it. For me the greatest benefit is the increase in readability due to not having useless temporaries everywhere in ref heavy code (that may not be under API user's control).
Re: DIP 1016--ref T accepts r-values--Community Review Round 1
On Friday, 20 July 2018 at 23:35:46 UTC, Jonathan M Davis wrote: On Friday, July 20, 2018 14:35:57 Manu via Digitalmars-d wrote: Comparatively rare? It's exactly what most functions using output ranges need to do. For many output ranges, if the function copies the range instead of copying, then you have a serious bug, because then the data that gets put to the output range inside the function does not affect the function argument - or worse, if it's a pseudo-reference type, it can partially mutate the argument, putting it in an invalid state. So, unless a function that accepts an output range is supposed to be taking ownership of it, the function needs to mark the output range parameter with ref, and it would be a bug for it to accept an rvalue. If anyone screws up and does something like return an output range from a function without that function returning ref and then passes it to a function that is intended to operate on an output range, they would currently get an error, whereas with this DIP, they would instead get subtle bugs with their severity depending on what type of ouput range it was and what the code was doing with it. This is an interesting case not completely covered by Manu's prior reasoning (that you can't muck it up because you need to use it after e.g. appender). But for the case that you would not need it later either you already have it as a lvalue (e.g. from a function parameter) or its some kind of singleton (e.g. nullSink or put's to a global variable). And yes, in most cases, programmers would not pass something other than a variable to a function that is clearly designed to take its argument by ref and mutate it, but with the heavy use of properties in a lot of D code, it can be trivial to operate on something that looks like an lvalue but isn't. Right now, such code gets caught, because it's an error to pass an rvalue to a ref parameter, but with this DIP, that would no longer be true. The situation gets even worse when you consider code maintenance issues like when someone initially has something be a variable and then later changes it to a property function and doesn't make it return by ref (and property functions usually don't return by ref). With this DIP, there could easily be silent code breakage as a result, whereas such breakage would not be silent with the current semantics for ref. Honestly, I don't see how accepting rvalues by ref is anything but error-prone for any case where the ref is there because the argument is supposed to be mutated and then be used after the function call. And while you may very well want to use ref simply to avoid copying - and may do that frequently right now in spite of that being a pain with rvalues - I have exactly the opposite experience that you seem to with regards to how ref is used. In my experience, using ref to avoid copies is rare, and using it to have the argument be mutated is what's common. So this problem is restricted output range @properties that somehow don't return by ref, aren't intended to be used after having data written to them _and_ aren't singleton like?