Re: isInputRange is false for non-copyable types
On 04/16/2018 06:15 AM, Shachar Shemesh wrote: Input ranges provide no guarantees about copying the range itself. If you do it and expect *anything* (which it seems you do), you have a bug. If you need to copy the range itself, you absolutely need to require a forward range. A forward range with ref front absolutely promises that both iterations reference the same elements. I find myself sincerely hoping that you are making these examples up in order to win this discussion turned into an argument for some reason, instead of the way phobos is actually written, because if you're right phobos is *broken*. The good news is that if Phobos is broken, this is a great way to flush out the places it's broken. Let's add UTs calling all Phobos functions accepting input ranges (as opposed to forward ranges) with non-copyable ranges (i.e. - the range itself is non-copyable) and fix the compilation errors. This shouldn't take more than a few days to do. I'm currently attempting something similar: fix Phobos to work with RefRange. RefRange is copyable, but assignment is weird. Assignment isn't part of the range interface, so I'm replacing it with `move`: https://issues.dlang.org/show_bug.cgi?id=18657 https://github.com/dlang/phobos/pull/6346 That PR doesn't fix all of Phobos, it's just a start. Going over all of Phobos (and getting it merged) might take a while. Thinking about it, those `move`s probably fix the code for non-copyable ranges as well. There might be considerable overlap here.
[Issue 18472] [Reg 2.078] betterC: cannot use format at compile time.
https://issues.dlang.org/show_bug.cgi?id=18472 --- Comment #7 from Rainer Schuetze--- I think the main issue is that the compiler does not distinguish between information needed at compile time and what's necessary inside the object file. --
Re: isInputRange is false for non-copyable types
On 16/04/18 01:28, Jonathan M Davis wrote: The fact that foreach copies the range that it's given makes using ref with anything other than arrays a bit of an iffy proposition. It will compile regardless of whether front returns by ref or not (which arguably is a bug), but it will only affect the original elements if copying the range doesn't copy the elements You keep referring to ranges that contain the data, but I am racking my mind and failing to find examples. You can have ranges over arrays,linked lists, trees (though you'd probably use opApply there), and any other container, as well as external data sources (files, sockets, pipes). In none of those cases would your range contain actual data. I need to see the use case for ranges *with* embedded data. Plus, as I've said before, if ranges are expected to contain data, copying them seems like an incredibly bad idea. The whole idea behind casually copying the range about is that it's cheap to do. which in the case of a basic input range rather than a forward range I don't see how that statement is true. is generally true, otherwise, it would be a forward range. A forward range is an input range. But as it stands, using ref with foreach in generic code is not going to go well. If anything, it's actually a code smell. You are conflating ref with owning data, which I find unsubstantiated. If non-copyable types were allowed, then functions that accept a range would fail to compile on non-copyable types if they do a copy. But the flip side is that if non-copyable would be allowed, a lot of functions that current copy would not. There are far too many unnecessary copies in the code that serve no purpose, but they are invisible, so they are not fixed. And if a templated function fails to compile if it's given a particular argument, and that failure is not due to the template constraint, that usually means that the template constraint is incomplete. I do not accept this argument outright. In fact, our experience at Weka has drove us to the exact opposite direction. We deliberately set up functions to include invalid cases and then either let them fail because of lacking constraints, or even set up a static assert to fail the function generation rather than fail matching. We found that the error messages produced by the alternative are simply too difficult to parse out and figure what went wrong. With that said, there is some merit to setting up the function constraints so that it matches what the function actually need. It allows overloading the missing combinations by another module. I don't think it is a good argument in this particular case, however. I think we should set up to document which phobos functions require copying. It will flesh out bugs and unnecessary copying in phobos, as well as force phobos developers to think about this scenario when they write code. It shouldn't even take that much time to do this run: just go over all UTs and add instantiation over a non-copyable type. The UTs that fail need work. it would mean that _every_ range-based function then has to worry about non-copyable elements No, just those in libraries. The same way they have to worry about big O complexity, type safety, @nogc and a bunch of other things. When you write a library, you have to think about your users. This doesn't change anything about that. So, allowing non-copyable types complicates range-based code across the board. Like I said above, it is more likely to find bugs than to introduce needless complications. If you code cannot be easily implemented over non-copyable types, exclude them. Don't shut me out of the entire game. Not all algorithms can call front just once without copying it Huh? Where did that come from? Phobos already assumes that calling front needs to be an O(1) operation. You can call front as many times as you like. Why would you assume otherwise? and many ranges (e.g. map) calculate front on each call, meaning that repeated calls to front can be more expensive than just calling it once and copying the result. Not by a lot, and definitely not in any way the generic code has any right to assume. I reject this argument outright. The result of all of this is that in generic code, you have no clue whatsoever what the semantics are of copying a range around, because it depends entirely on the copying semantics of whatever range that code is currently being instantiated with. As such, generic code basically has to assume that once you copy a range, you can't mutate the original (since it may or may not be affected by mutating the copy and may or may not be cleanly affected by mutating the copy), Jonathan, I'm sorry, but what you are describing is called "a bug". Input ranges provide no guarantees about copying the range itself. If you do it and expect *anything* (which it seems you do), you have a bug. If you need to copy the range itself, you absolutely
Aurora DirectX Bindings 12.1
I am happy to announce that after a prolonged hiatus the Aurora DirectX bindings have been updated to support DirectX 12.1 and DirectX 11.4. The project has been refactored to more closely align with the DirectX SDK headers and the scope is significantly increased to include the D3D Video, D2D Effects, SVG, and Debugging libraries. And finally, the package has now been added to DUB. The following components of DirectX are supported: DirectX 12.1 - Shaders - Shader Tracing - Video - SDK Layers (Debugging) DirectX 11.4 - Shaders - Shader Tracing - Video - SDK Layers (Debugging) Direct2D 1.3 - Effects 1.2 - SVG DirectWrite 1.3 DXGI 1.6 WIC The work is a combination of mechanical and hand conversion and there may be some inconsistent or incorrect types in the interface. If you encounter any inconsistencies I would love you pull requests. Please note that most Macros are NOT ported yet. PR's welcome! These bindings are based on the Windows SDK version 10.0.16299.0 (Windows Build 1709 - Redstone 3) GitHub: https://github.com/auroragraphics/directx DUB: http://code.dlang.org/packages/aurora-directx -- Adam Wilson IRC: LightBender import quiet.dlang.dev;
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:55:41 UTC, Giles Bathgate wrote: On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: I am proposing a new function called getOrAdd in I posted details of the PR here because at least 2 people do not like the name getOrAdd (and one of those people being myself) Time for a bikeshed discussion... I think Adding a Yes.add flag to the existing get makes sense, but property functions only have max 2 args. S...getOrAdd or getOrSet would be my pick. Jordan
[Issue 18753] chunkBy compile error causes ICE
https://issues.dlang.org/show_bug.cgi?id=18753 --- Comment #2 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/d119ed9912891f133092ef0d61bbba74ca175aca Fix Issue 18753 - chunkBy compile error causes ICE https://github.com/dlang/dmd/commit/4106f382f14eb1a0fca7c563bebd3b7089873a59 Merge pull request #8161 from RazvanN7/Issue_18753 Fix Issue 18753 - chunkBy compile error causes ICE merged-on-behalf-of: Mike Franklin--
[Issue 18753] chunkBy compile error causes ICE
https://issues.dlang.org/show_bug.cgi?id=18753 github-bugzi...@puremagic.com changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --
[Issue 18034] SIMD optimization issues
https://issues.dlang.org/show_bug.cgi?id=18034 --- Comment #2 from github-bugzi...@puremagic.com --- Commits pushed to master at https://github.com/dlang/dmd https://github.com/dlang/dmd/commit/ba478b04139b8d4f7a42a35279f8089615156099 Fix issue 18034 - Bad codegen for OPvecfill Do not replace vector values if that implies a change of Ety, doing so may end up initializing the vector with the wrong content. https://github.com/dlang/dmd/commit/2493fb8bbea05d31a1fdae2a02d8eeae3ad0ff46 Merge pull request #7994 from LemonBoy/b18034 Fix issue 18034 - Bad codegen for OPvecfill merged-on-behalf-of: Mike Franklin--
Re: Small Buffer Optimization for string and friends
On Sunday, 8 April 2012 at 05:56:36 UTC, Andrei Alexandrescu wrote: Andrei Have anybody put together code that implements this idea in a library? That is, a small strings up to length 15 bytes unioned with a `string`.
[Issue 18472] [Reg 2.078] betterC: cannot use format at compile time.
https://issues.dlang.org/show_bug.cgi?id=18472 --- Comment #6 from Mike Franklin--- (In reply to Rainer Schuetze from comment #5) > Here's a simpler test case: > > module betterc; > enum b = typeid(size_t) is typeid(uint); At https://dlang.org/spec/betterc.html under the "Not Available" section: > 2. TypeInfo and ModuleInfo So, it is by design that any call to `typeid` is going to fail when compiled with `-betterC`. This specific issue is about not being able to use `format` in `-betterC`. Perhaps the reason for that is because `format` relies on runtime type information (i.e. TypeInfo). So the solution, specific to this issue, would not be allow uses of `typeid` in `-betterC`, but rather to remove the dependency of `format` on runtime type information (if that's even possible). D has excellent facilities for doing introspection at compile-time, so it may be possible to look to those facilities in concert with templates to find a solution that does not rely on runtime type information. It would likely also help to begin replacing compiler-generated calls to runtime hooks that depend on `TypeInfo` with templates. See also https://forum.dlang.org/post/mr7a65$2hc$1...@digitalmars.com --
Re: isInputRange is false for non-copyable types
On Sunday, April 15, 2018 12:29:17 Dmitry Olshansky via Digitalmars-d wrote: > On Sunday, 15 April 2018 at 10:39:32 UTC, Jonathan M Davis wrote: > > So, while I'd love to have the opportunity to sit down and > > redesign the range API, I don't see how we really can - not and > > actually have it implemented as part of the language or Phobos > > anyway. > > Yeah, I think as surely as we can redesign postblit. Let’s not > focus on learned helplessnes and “it’s just the way things are”. > Recent opMove shows there is great flexibility in what can be > done. > > Seriously, it’s just fixing a library design issue even if its > use proved viral. Replacing postblit is trivial in comparison to redesigning ranges. The worst that's going to happen with postblit is that all postblit constructors are going to be deprecated in favor of some other kind of constructor, which would result in a deprecation warning for types with postblit constructors until they've replaced one constructor with the other. As far as breaking changes go, it shouldn't be much more complicated than renaming a function and requiring everyone to update their code. It shouldn't even affect anyone using types with postblit constructors except maybe if they're using __traits(getMembers, ...) to get at __postblit or __xpostblit. It's just the types themselves that need to be updated. In that sense, it's actually less disruptive to replace the postblit constructor than it would be to rename a function, because all that has to be changed is the function itself, not every place that it gets called. And if we get some kind of opMove solution, that wouldn't break any existing code. It would be invisible to anything but new code that was written to use it. That's the easiest kind of improvement. Ranges, on the other hand, are integral to how a large percentage of Phobos works, and a lot of existing code depends on them heavily. And unless you're talking about simply renaming popFront to something else, changing them gets pretty hairy. Changing ranges in any serious way risks having to essentially fork Phobos (or at least large portions of it). Any major redesign would almost certainly require renaming most or all of the range traits. All functions accepting ranges would have to be rewritten. Any function returning a range would have to either be renamed or somehow work with both the old and new range API (and since containers use an operator rather than a function name to provide ranges, that could make updating containers rather interesting unless we're willing to give up on slicing being how we get a range from a container). We may be able to make small changes here and there, but I don't see how anything major is possible unless we're willing to break a ton of existing code. Now, maybe someone can come up with something clever to make some decent improvements to what we have without doing a major redesign, but I think that a major redesign requires effectively forking the range API, which means either ending up with two different range APIs that everyone has to deal with, or requiring all range-based code to eventually be updated from one range API to another, which is an enormous change and far more than simply swapping one function out for another. So, if we decide that we're willing to make changes that effectively require that almost every D program make changes that are potentially quite invasive, then sure, we can redesign the range API. And it would be great to be able to do that. But I have a hard time buying that such a large change would be acceptable at this point. - Jonathan M Davis
Re: Feature to get or add value to an associative array.
On Sunday, 15 April 2018 at 22:52:47 UTC, Giles Bathgate wrote: I am proposing a new function called getOrAdd in I posted details of the PR here because at least 2 people do not like the name getOrAdd (and one of those people being myself) Time for a bikeshed discussion...
Feature to get or add value to an associative array.
Hi, I wanted a way to lazily insert a value into an associative array, and I am proposing a new function called getOrAdd in https://github.com/dlang/druntime/pull/2162 The function provides a means to get a value corresponding to the key, but if the value doesn't exist it will evaluate the lazy argument to create a new value, add this to the associative array and then return it. ``` auto p = lookup.getOrAdd("giles", new Person); p.eyeColor = Color.Brown; //... assert("giles" in lookup); ``` Corresponding documentation added in https://github.com/dlang/dlang.org/pull/2343 Implementation details: Traditionally the above example could be done like so: ``` auto p = "giles" in lookup; if (p is null) { p = new Person; lookup["giles"] = p; } p.eyeColor = Color.Brown; //... assert("giles" in lookup); ``` I find this later code clunky and it requires two hashes/lookups. The proposed implementation adds support directly to rt/aaA.d to avoid this. I should also point out that the allocation of a new Person in the example is trivial, but it might often be the case that the person instance is created by fetching a record from a db, or an Image loaded from disk, or a movie downloaded from the internet.
[Issue 18765] New: [Arrays] Docs need info on initialization of static array with element literal
https://issues.dlang.org/show_bug.cgi?id=18765 Issue ID: 18765 Summary: [Arrays] Docs need info on initialization of static array with element literal Product: D Version: D2 Hardware: All URL: http://dlang.org/ OS: All Status: NEW Severity: enhancement Priority: P3 Component: dlang.org Assignee: nob...@puremagic.com Reporter: mrsmit...@yandex.ru All elements of static array can be initialized to specific value with: ubyte[4] array = 42; assert(array == [42, 42, 42, 42]); Should be added to https://dlang.org/spec/arrays.html#static-init-static --
Zig talk on youtube (mentions D briefly)
There was a talk recently by the creator of the Zig language [1]. Zig which was mentioned on the forums a few times. The creator comes down really hard on languages with hidden memory allocations. He emphasizes correct handling of memory errors, particularly allocation fails. D is mentioned in the context of languages that handle such errors using exceptions (C++, C#, Java), which the creator doesn't like (one of the principles of Zig is "no hidden control flow"). Strangely, Rust isn't mentioned at all. The compile-time features seem really nice. There are a lot of similarities with D templates, but also some differences - In Zig types are first class entities, so you can have functions taking and returning types. For instance, A generic list would be implemented as a (compile-time) function taking a type T and returning a user-defined type List[T]. In practice it doesn't seem that different from D templates but I thought it's a nice way to think about generics. [1] https://www.youtube.com/watch?v=Z4oYSByyRak
[Issue 18762] DMD should use a unique path/filename for __stdin.o
https://issues.dlang.org/show_bug.cgi?id=18762 Vladimir Panteleevchanged: What|Removed |Added CC||dlang-bugzilla@thecybershad ||ow.net, ||hst...@quickfur.ath.cx Component|dlang.org |dmd Summary|The spec tester fails to|DMD should use a unique |link examples with |path/filename for __stdin.o |__stdin.o | --- Comment #1 from Vladimir Panteleev --- The problem seems to be that the same object file name is used when reading from stdin: $ echo 'void main() {}' | dmd -v -run - | grep ^cc cc __stdin.o -o /tmp/dmd_runIAGsLe -m64 -Xlinker --export-dynamic -L/home/vladimir/opt/dmd/bin/../lib64 -Xlinker -Bstatic -lphobos2 -Xlinker -Bdynamic -lpthread -lm -lrt -ldl This cannot work reliably in multiple threads, as several concurrent DMD instances will write __stdin.o, and several concurrent linkers will attempt to read it. --
Re: Assoc. Array and struct with immutable member
On Sunday, 15 April 2018 at 17:59:01 UTC, Dgame wrote: How am I supposed to insert a struct with immutable members into an assoc. array? Reduced example: struct A { immutable string name; } A[string] as; as["a"] = A("a"); // Does not work Via a static this() it would work. But I guess, this is not what you are looking for, is it? ´´´ static this() { as["a"] = A("a"); } void main() { assert(as["a"].name == "a"); } struct A { immutable string name; } A[string] as; ´´´ It also works, if you hide the AA in a class and all the insertions into the constructor. ´´´ /* static this() { as["a"] = A("a"); } */ void main() { auto c = new Container(A("a")); assert(c.as["a"].name == "a"); } struct A { immutable string name; } class Container { A[string] as; this(A a) { as[a.name] = a; } } ´´´
Assoc. Array and struct with immutable member
How am I supposed to insert a struct with immutable members into an assoc. array? Reduced example: struct A { immutable string name; } A[string] as; as["a"] = A("a"); // Does not work
Diamond MVC (Full-stack web-framework) - v2.9.1
Pleased to announce a new version of Diamond - v2.9.1 This release comes with the following: * SEO Functionality, full support for schema.org (With the most common data structures already implemented.) * placeHolder's deprecation period is over and all places using "placeHolder" must now use "placeholder". * Fixes a critical bug that caused applications to crash with double slashes in the url. * Better error messages for views. Github: https://github.com/DiamondMVC/Diamond/ Website: http://diamondmvc.org/ DUB: https://code.dlang.org/packages/diamond Thanks to everyone who has helped Diamond get where it is!
Re: NoCopy for overriding @disable this(this)
On Thursday, 12 April 2018 at 17:09:22 UTC, Shachar Shemesh wrote: On 12/04/18 18:42, Uknown wrote: On Thursday, 12 April 2018 at 12:16:53 UTC, Shachar Shemesh wrote: [...] The problem seems to be that cast is happening at compile time, as opposed to run time, as you might have already figured out. Do you need to really do this cast at compile time? I tried running the snippet you gave here: https://run.dlang.io/is/im19nL Is this how you intend for it to be used? Then there's no need for compile time casts. If not, could you give an example of how `NoCopy` would be used? struct Disabled { int i = 17; @disable this(this); } struct Container { NoCopy!Disabled disabled; } Any instance you create of "Container" will have i initialized to 0 by default. Since `T` has the postblit disabled, I'm guessing the ctor should take a `ref T`. Since `T` has the postblit disabled, I'm guessing the ctor should take a `ref T`.
Re: Why is the error message coming by the end of the compilation?
On Sunday, 15 April 2018 at 16:55:36 UTC, bauss wrote: On Sunday, 15 April 2018 at 15:55:15 UTC, ag0aep6g wrote: On 04/15/2018 05:33 PM, bauss wrote: On Sunday, 15 April 2018 at 10:27:26 UTC, ag0aep6g wrote: On 04/14/2018 08:56 PM, bauss wrote: I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... [...] mixin("#line 1 \"mymixin\"\n" ~ "somecode;"); /* mymixin(1): Error: undefined identifier somecode */ [...] I don't see how the #line will help because you don't know which mixin the line would be associated with as they can come in any order. I don't follow. It's not about setting the line number. The point is setting the source file name to "mymixin". You asked for a way associate a name with a string mixin, and have that name included in errors. As far as I see, `#line` lets you do that. Note how the error message in my example shows "mymixin". Oh, I'm sorry I didn't notice that, my bad. I guess adding that would be the equivalent to what my proposal is. I'll give it a try and come back It's almost as good as I want it to be, so this solution will do for now!
Re: Why is the error message coming by the end of the compilation?
On Sunday, 15 April 2018 at 15:55:15 UTC, ag0aep6g wrote: On 04/15/2018 05:33 PM, bauss wrote: On Sunday, 15 April 2018 at 10:27:26 UTC, ag0aep6g wrote: On 04/14/2018 08:56 PM, bauss wrote: I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... [...] mixin("#line 1 \"mymixin\"\n" ~ "somecode;"); /* mymixin(1): Error: undefined identifier somecode */ [...] I don't see how the #line will help because you don't know which mixin the line would be associated with as they can come in any order. I don't follow. It's not about setting the line number. The point is setting the source file name to "mymixin". You asked for a way associate a name with a string mixin, and have that name included in errors. As far as I see, `#line` lets you do that. Note how the error message in my example shows "mymixin". Oh, I'm sorry I didn't notice that, my bad. I guess adding that would be the equivalent to what my proposal is. I'll give it a try and come back
Re: Why is the error message coming by the end of the compilation?
On 04/15/2018 05:33 PM, bauss wrote: On Sunday, 15 April 2018 at 10:27:26 UTC, ag0aep6g wrote: On 04/14/2018 08:56 PM, bauss wrote: I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... [...] mixin("#line 1 \"mymixin\"\n" ~ "somecode;"); /* mymixin(1): Error: undefined identifier somecode */ [...] I don't see how the #line will help because you don't know which mixin the line would be associated with as they can come in any order. I don't follow. It's not about setting the line number. The point is setting the source file name to "mymixin". You asked for a way associate a name with a string mixin, and have that name included in errors. As far as I see, `#line` lets you do that. Note how the error message in my example shows "mymixin".
Re: File names in string mixins
On Sunday, 15 April 2018 at 10:09:36 UTC, Simen Kjærås wrote: In a thread[0] over on D.learn, bauss suggested adding a second argument to MixinExpressions, such that mixin("foo()", "my mixin") compiles. The use case for the extra argument is as an identifier that will be used in error messages, where the current behavior is to create a virtual file name on the form __FILE__-mixin-__LINE__. Instead of this behavior: unittest { // .\foo.d-mixin-17(17): Error: undefined identifier bar mixin("bar();"); } You would have this behavior: unittest { // My mixin(1): Error: undefined identifier bar mixin("bar();", "My mixin"); } A toy example like this doesn't really show how useful this would be, but in a more complex use case where multiple mixins are generated from different template arguments, in a static foreach, etc, the relevant context may be added by the programmer as he writes the code: static foreach (i, item; getCodeSources()) { mixin(item.generateCode(), "Code source "~i.to!string); } When the above code fails on item 15, the error message would immediately show "Code source 15(__LINE__): ", making it much easier to figure out where to start fixing. Destroy! -- Simen [0]: https://forum.dlang.org/post/tbyqqefafgzfiltgl...@forum.dlang.org Yes, this would be so much easier, especially for frameworks that relies on user code to mixin, in which case you or the user don't really know the exact line of the resulting mixin. If this requries a DIP I wouldn't mind writing one, but it seems to be such a small trivial thing though.
Re: Why is the error message coming by the end of the compilation?
On Sunday, 15 April 2018 at 10:14:56 UTC, Simen Kjærås wrote: On Saturday, 14 April 2018 at 08:20:51 UTC, bauss wrote: The problem is I can't pragma(msg) the code I want to mixin manually since all mixins are dynamically generated. That's why my only way is to do it within that static foreach. Wat. So the compiler is able to generate the string you want to mixin, but not print it? If you try this: static foreach (viewResult; generateViewsResult) { pragma(msg, "Compiling: " ~ viewResult.name); pragma(msg, viewResult.source); pragma(msg, "Compiled: " ~ viewResult.name); } Does it blow up? Does it print gibberish? Does it complain in any way? I initially tried to just use __traits(compiles) but it fails even on the valid generated D code. This also sounds weird. Are you missing brackets around the generated code? If the generated code consists of more than one expression, you generally have to check __traits(compiles, { mixin(foo()); }). From reading your messages here it seems the mixin simply contains a class. This test shows the difference: enum s = "class A {}"; // Global scope: static assert(!__traits(compiles, mixin(s))); static assert(__traits(compiles, { mixin(s); })); unittest { // Function scope: static assert(!__traits(compiles, mixin(s))); static assert(__traits(compiles, { mixin(s); })); } As we can see, the version with extra brackets compiles, the other does not. I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... That seems like a very good idea. Posted it in D.general: https://forum.dlang.org/post/epqmzhjoyqcdqrqks...@forum.dlang.org -- Simen Tried in brackets already, also tried to wraper __traits(compiles) into a function and given __traits(compiles) a function that has the code mixin. It does not print gibberish and the code is valid, but __traits(compiles) still returns false for it. On Sunday, 15 April 2018 at 10:27:26 UTC, ag0aep6g wrote: On 04/14/2018 08:56 PM, bauss wrote: I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... That would completely solve this issue and I wouldn't have to have pragma(msg) all over the place. The `#line` thing might help: void main() { mixin("#line 1 \"mymixin\"\n" ~ "somecode;"); /* mymixin(1): Error: undefined identifier somecode */ somecode; /* test.d(5): Error: undefined identifier somecode */ } https://dlang.org/spec/lex.html#special-token-sequence I don't see how the #line will help because you don't know which mixin the line would be associated with as they can come in any order.
[Issue 18764] New: -g makes OPTLINK fail to find symbols
https://issues.dlang.org/show_bug.cgi?id=18764 Issue ID: 18764 Summary: -g makes OPTLINK fail to find symbols Product: D Version: D2 Hardware: x86 OS: Windows Status: NEW Severity: normal Priority: P1 Component: dmd Assignee: nob...@puremagic.com Reporter: johnnymar...@gmail.com Created attachment 1686 --> https://issues.dlang.org/attachment.cgi?id=1686=edit DirectX Library OMF Format Optlink failed to find symbols when passing `-g` to dmd. Note that the only difference in the link command when passing `-g` is it adds the `/co` option to OPTLINK (NOTE: not sure what this option means for OPTLINK). To reproduce. clone the direct-x binding repository: git clone https://github.com/evilrat666/directx-d Create the following file: --- issue.d import directx.d2d1; int main() { //auto result = D2D1CreateDevice(null, null, null); ID2D1Factory direct2dFactory; auto options = D2D1_FACTORY_OPTIONS(D2D1_DEBUG_LEVEL_WARNING); auto result = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, _ID2D1Factory, , cast(void**)); return 0; } --- Download the attached directx omf library (converted from the COFF library). Compilation/Link should work with the following: dmd -I= d2d1.omf.lib issue.d Example: did -I=..\directx-d\src d2d1.omf.lib issue.d Now perform the same compilation but add `-g`, and you should get the following linker error: OPTLINK (R) for Win32 Release 8.00.17 Copyright (C) Digital Mars 1989-2013 All rights reserved. http://www.digitalmars.com/ctg/optlink.html issue.obj(issue) Error 42: Symbol Undefined _D2D1CreateDevice@12 issue.obj(issue) Error 42: Symbol Undefined _D2D1CreateDeviceContext@12 Error: linker exited with status 2 --
[Issue 18763] Segfault in garbage collector
https://issues.dlang.org/show_bug.cgi?id=18763 |changed: What|Removed |Added CC||dhase...@gmail.com --- Comment #2 from | --- Created attachment 1685 --> https://issues.dlang.org/attachment.cgi?id=1685=edit Test case for segfault Added test case (as seen on IRC). Stacktrace (also as seen on IRC): Program received signal SIGSEGV, Segmentation fault. 0x555d5b35 in _D2gc4impl12conservativeQw3Gcx11fullcollectMFNbbZm () (gdb) bt #0 0x555d5b35 in _D2gc4impl12conservativeQw3Gcx11fullcollectMFNbbZm () #1 0x555d8856 in _D2gc4impl12conservativeQw14ConservativeGC__T9runLockedS_DQCeQCeQCcQCnQBs18fullCollectNoStackMFNbZ2goFNbPSQEaQEaQDyQEj3GcxZmTQvZQDfMFNbKQBgZm () #2 0x555d2961 in _D2gc4impl12conservativeQw14ConservativeGC18fullCollectNoStackMFNbZv () #3 0x555d2932 in _D2gc4impl12conservativeQw14ConservativeGC14collectNoStackMFNbZv () #4 0x555e5cf1 in gc_term () #5 0x555da3cb in rt_term () #6 0x555c63b5 in rt.dmain2._d_run_main(int, char**, extern(C) int(char[][]) function).runAll() () #7 0x555c6290 in rt.dmain2._d_run_main(int, char**, extern(C) int(char[][]) function).tryExec(scope void() delegate) () #8 0x555c61fb in _d_run_main () #9 0x555bbede in main () #10 0x76bf2a87 in __libc_start_main (main=0x555bbebc , argc=2, argv=0x7fffea68, init=, fini=, rtld_fini=, stack_end=0x7fffea58) at ../csu/libc-start.c:310 #11 0x555b114a in _start () --
[Issue 18763] Segfault in garbage collector
https://issues.dlang.org/show_bug.cgi?id=18763 Basile B.changed: What|Removed |Added CC||b2.t...@gmx.com --- Comment #1 from Basile B. --- You forgot to upload an attachment apparently. SEGFAULT by GC can be caused by a destructor that allocates. destructor are not allowed to. --
[Issue 17833] compiling dmd on x86 linux fails
https://issues.dlang.org/show_bug.cgi?id=17833 Tyler Dencechanged: What|Removed |Added CC||tyz...@archlinux32.org --- Comment #3 from Tyler Dence --- Bumping this issue, since this is triggering the removal of this package from the archlinux32 repos. --
[Issue 18472] [Reg 2.078] betterC: cannot use format at compile time.
https://issues.dlang.org/show_bug.cgi?id=18472 Rainer Schuetzechanged: What|Removed |Added CC||r.sagita...@gmx.de --- Comment #5 from Rainer Schuetze --- Here's a simpler test case: module betterc; enum b = typeid(size_t) is typeid(uint); >dmd -betterC -c betterc.d betterc.d(2): Error: TypeInfo cannot be used with -betterC --
[Issue 15574] wrong order of linker arguments
https://issues.dlang.org/show_bug.cgi?id=15574 Remi Thebaultchanged: What|Removed |Added CC||remi.theba...@gmail.com --- Comment #4 from Remi Thebault --- Here is a simple test case to reproduce what is decribed by John: $ git clone https://github.com/rtbo/dmd_link_args_order $ cd dmd_link_args_order $ make app It builds a static lib with C code, a static lib with D code that calls a C function (bindings to the C code) and an D app that uses the D code. $ dmd -ofapp app.d libdsquare.a -L-L. -L-lcsquare issues the following linker command: $ cc app.o -o app -m64 -L. -lcsquare -L/usr/lib -Xlinker --export-dynamic libdsquare.a -Xlinker -Bstatic -lphobos2 -Xlinker -Bdynamic -lpthread -lm -lrt -ldl Note that libdsquare.a is after -lcsquare and causes a link error. An intermediate fix would be to place the *.a files before the linker switches given on the command line. I argue that *.a have much more chances to depend on -l libraries than the opposite. This is what LDC is doing. --
Re: isInputRange is false for non-copyable types
On 15/04/18 09:39, Jonathan M Davis wrote: It's extremely common for range-based functions to copy front. Even foreach does it. e.g. Not necessarily: foreach(ref e; [S(0), S(1), S(2)]){} While that would work with foreach, it will not work with anything that expects an inputRange (and since D defines a forward range as an extension, this is also not a forward range). If non-copyable types were allowed, then no function which accepted a range would be allowed to copy front without first checking that front was copyable (something that most code simply isn't going to do) No, that's not correct. If non-copyable types were allowed, then functions that accept a range would fail to compile on non-copyable types if they do a copy. But the flip side is that if non-copyable would be allowed, a lot of functions that current copy would not. There are far too many unnecessary copies in the code that serve no purpose, but they are invisible, so they are not fixed. Remember also that a large percentage of ranges that don't wrap dynamic arrays put their elements on the stack, which means that whenever the range is copied, the elements are copied. If I am guaranteed to be able to copy an input range, what's the difference between it and a forward range? Strike that, I have a better one: If I am allowed to copy an input range, what does the "save" function in forward range even mean? I'm not sure why it ends up printing each of them 3 times rather than 2, Because some code somewhere does an unnecessary copy? the fact that foreach copies any range that it's given means that in order to have ranges allow non-copyable types, we'd have to change how foreach worked, which would break a lot of code. Right now, Like I said above, foreach(ref) works with "input ranges" that define ref return from front to uncopyable objects. Foreach without ref doesn't, but that's mandatory from the interface: You cannot iterate copies of a range returning uncopyable objects. As for ranges that store the values inside them: you REALLY don't want to copy those around. They may get quite big (not to mention that I don't see how you can define one over a non-copyable type). foreach(e; range) { } is lowered to something like for(auto __range = range; !__range.empty; __range.popFront()) { auto e = __range.front; } And that indeed generates a lot of confusion regarding what running two foreaches in a row does. This is a bug that already affects more than just uncopyable objects. That requires both copying the range and copying front. We could theoretically change it so that everywhere that e was used, it would be replaced with __range.front Like I said, already solved for foreach(ref) Now, generic range-based code really shouldn't ever use a range after it's been copied, since whether mutating the copy affects the original depends on the implementation of the range (and thus generic code should assume that foreach may have consumed the range and call save if it doesn't want that to happen), but lots of code does it anyway, And allowing ranges with uncopyable members would turn this potential deadly run-time bugs into easy to find compile time errors. Sound like a great reason to allow it, to me. and if the code isn't generic, it can work just fine, since then the code can depend on the semantics of that specific range type Such as it being copyable? Non-generic code is of no relevance to this discussion, as far as I can tell. Also, in order for a range to work with a non-copyable type, either front would have to return by ref or it would have to construct a new object to return so that it could be moved rather than copied. Correct I expect that quite a few ranges would have problems with such a restriction, Then those ranges will not work with non-copyable objects. That's no reason to make it impossible for *any* range to work with non-copyable. In addition, it's quite possible that forcing functions to not copy front would hurt performance. I'm going to stop responding now, because, frankly, I think you and I are having very different discussions. You seem to be advocating against making *all* ranges support non-copyable types, while I'm merely asking that *any* range be allowed to support such types. Current situation is that a range with uncopyable types is not considered an input range, and cannot use any phobos range functions, including some that it should be able to use without a problem. There is no reason to block such ranges from using "map" or "any", except the fact they require that the type answer "isInputRange" with true. IIRC, when this has come up previously, Andrei ruled that supporting non-copyable types simply wasn't worth the extra complication, though a quick search doesn't turn up anything where he talked about it. So, I can't verify that at the moment. I will trust Andrei to weigh in on this point if he thinks he
Re: isInputRange is false for non-copyable types
On Sunday, 15 April 2018 at 10:39:32 UTC, Jonathan M Davis wrote: On Sunday, April 15, 2018 10:14:20 Dmitry Olshansky via Digitalmars-d wrote: On Sunday, 15 April 2018 at 06:39:43 UTC, Jonathan M Davis wrote: > On Sunday, April 15, 2018 07:26:54 Shachar Shemesh via > > Digitalmars-d wrote: >> [...] > > It's extremely common for range-based functions to copy > front. Even foreach does it. e.g. > > [...] Arguably it should “move” them. This would have worked if input ranges didn’t have to cache front to support multiple ‘front’ calls before popFront. Which is a painful misfeature really as all algorithms would optimize for touching front once anyway. Input range should “produce” elements not keep cache of them, forward ranges may cache current item alright. If that were the route that we were going to go, then front and popFront wouldn't make any sense at all. Rather, you'd treat it more like in iterator in Java and have next() return the next element and pop it off at the same time. Surprisingly, they might have got that right. But even if we did that, it wouldn't have been appropriate in the general case to move the element unless we put serious restrictions on what could be an input range (e.g. that would make no sense whatsoever with dynamic arrays or any kind of container). There it would copy. You get rvalue either way. Another option is ref scope T. I do not see incompatibility you seem to imply. So, while I'd love to have the opportunity to sit down and redesign the range API, I don't see how we really can - not and actually have it implemented as part of the language or Phobos anyway. Yeah, I think as surely as we can redesign postblit. Let’s not focus on learned helplessnes and “it’s just the way things are”. Recent opMove shows there is great flexibility in what can be done. Seriously, it’s just fixing a library design issue even if its use proved viral. - Jonathan M Davis
Re: "%s"-format template function arguments
On 04/15/2018 02:04 PM, vladdeSV wrote: foo(1,2,3); void foo(T...)(T args) { writefln("expected: %s", [1,2,3]); writefln("actual: %s", args); } The code above will output expected: [1, 2, 3] actual: 1 How would I go on about to print all the arguments as I expected it, using "%s"? writefln("%s", [args]); Or avoiding the allocation: import std.range: only; writefln("%s", only(args)); You could also change the `args` parameter to give you a stack-based array: void foo(T)(T[] args ...) { writefln("%s", args); } [...] P.S. I do not understand why only a `1` is printed in the actual result. This: writefln("actual: %s", args); becomes this: writefln("actual: %s", args[0], args[1], args[2]); So there are three arguments after the format string. The %s placeholder only refers to the first one. The others are ignored.
Re: "%s"-format template function arguments
On Sunday, 15 April 2018 at 12:04:19 UTC, vladdeSV wrote: How would I go on about to print all the arguments as I expected it, using "%s"? You can expand the template arguments into an array by putting it into square brackets: [args]. You can format an array with the default notation using %s, for a custom format you can use %( and %). See https://dlang.org/phobos/std_format.html ``` void main() { foo(1, 2, 3); } void foo(T...)(T args) { writefln("%s", [args]); // prints [1, 2, 3] writefln("%(%s; %)", [args]); //custom ; separator, prints 1; 2; 3 } ```
Re: "%s"-format template function arguments
On Sunday, 15 April 2018 at 12:04:19 UTC, vladdeSV wrote: Hello people of D-land. In a template function, I want to format all arguments as if it was an array. Se this snippet of code: foo(1,2,3); void foo(T...)(T args) { writefln("expected: %s", [1,2,3]); writefln("actual: %s", args); } The code above will output expected: [1, 2, 3] actual: 1 How would I go on about to print all the arguments as I expected it, using "%s"? Best regards, Vladimirs Nordholm --- P.S. I do not understand why only a `1` is printed in the actual result. If you define foo like that, then, you advice D to handle the input as separate objects. That's ok. But then, you have to define that you still assume, they belong together, like an array. In this example the solution is simple: ´´´ void main() { foo(1,2,3); } void foo(T...)(T args) { import std.stdio : writefln; import std.range : only; writefln("expected: %s", [1,2,3]); writefln("actual: %s", args.only); } ´´´ However, there will be problems, if the types of elements differs: While the template foo will be able to handle this, the std.range : only function won't. It assumes at least something common across them. https://dlang.org/library/std/range/only.html
"%s"-format template function arguments
Hello people of D-land. In a template function, I want to format all arguments as if it was an array. Se this snippet of code: foo(1,2,3); void foo(T...)(T args) { writefln("expected: %s", [1,2,3]); writefln("actual: %s", args); } The code above will output expected: [1, 2, 3] actual: 1 How would I go on about to print all the arguments as I expected it, using "%s"? Best regards, Vladimirs Nordholm --- P.S. I do not understand why only a `1` is printed in the actual result.
[Issue 18763] New: Segfault in garbage collector
https://issues.dlang.org/show_bug.cgi?id=18763 Issue ID: 18763 Summary: Segfault in garbage collector Product: D Version: D2 Hardware: x86_64 OS: Linux Status: NEW Severity: normal Priority: P1 Component: druntime Assignee: nob...@puremagic.com Reporter: lieuw...@gmail.com This program gives a segfault somewhere in the garbage collector when ran with oscillofun.flac as input. --
Re: isInputRange is false for non-copyable types
On Sunday, April 15, 2018 10:14:20 Dmitry Olshansky via Digitalmars-d wrote: > On Sunday, 15 April 2018 at 06:39:43 UTC, Jonathan M Davis wrote: > > On Sunday, April 15, 2018 07:26:54 Shachar Shemesh via > > > > Digitalmars-d wrote: > >> [...] > > > > It's extremely common for range-based functions to copy front. > > Even foreach does it. e.g. > > > > [...] > > Arguably it should “move” them. > > This would have worked if input ranges didn’t have to cache front > to support multiple ‘front’ calls before popFront. Which is a > painful misfeature really as all algorithms would optimize for > touching front once anyway. > > Input range should “produce” elements not keep cache of them, > forward ranges may cache current item alright. If that were the route that we were going to go, then front and popFront wouldn't make any sense at all. Rather, you'd treat it more like in iterator in Java and have next() return the next element and pop it off at the same time. But even if we did that, it wouldn't have been appropriate in the general case to move the element unless we put serious restrictions on what could be an input range (e.g. that would make no sense whatsoever with dynamic arrays or any kind of container). In some respects it would be nice if input ranges were completely separate beasts from forward ranges, since ideally, forward ranges would all be value types, and input ranges would all be reference types (in which case, save wouldn't be a thing), but that would cause it's own set of problems, because then it wouldn't really work to have input ranges and forward ranges use the same code, which could get really annoying. Input ranges are kind of an abomination IMHO , because they're so painfully limited, but unfortunately, it simply doesn't work to have all ranges be forward ranges if you don't want to have to do stuff like buffer data. So, figuring out what we would ideally do with input ranges and forward ranges gets to be a bit of an interesting question. Regardless, even if we could all agree on how ranges would ideally be redesigned if we were doing this stuff from scratch, we're not doing it from scratch, and for better or worse, a lot of existing code depends on the current design. So, while I'd love to have the opportunity to sit down and redesign the range API, I don't see how we really can - not and actually have it implemented as part of the language or Phobos anyway. - Jonathan M Davis
Re: Why is the error message coming by the end of the compilation?
On 04/14/2018 08:56 PM, bauss wrote: I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... That would completely solve this issue and I wouldn't have to have pragma(msg) all over the place. The `#line` thing might help: void main() { mixin("#line 1 \"mymixin\"\n" ~ "somecode;"); /* mymixin(1): Error: undefined identifier somecode */ somecode; /* test.d(5): Error: undefined identifier somecode */ } https://dlang.org/spec/lex.html#special-token-sequence
Re: isInputRange is false for non-copyable types
On Sunday, 15 April 2018 at 10:14:20 UTC, Dmitry Olshansky wrote: On Sunday, 15 April 2018 at 06:39:43 UTC, Jonathan M Davis wrote: On Sunday, April 15, 2018 07:26:54 Shachar Shemesh via Digitalmars-d wrote: [...] It's extremely common for range-based functions to copy front. Even foreach does it. e.g. [...] Arguably it should “move” them. This would have worked if input ranges didn’t have to cache front to support multiple ‘front’ calls before popFront. Which is a painful misfeature really as all algorithms would optimize for touching front once anyway. Input range should “produce” elements not keep cache of them, forward ranges may cache current item alright. On a related note this also destroys idea of “lock-free” or “concurrent” input ranges since front/empty/popFront sequence of calls can’t be cheaply synchronized in as a whole in presence of multiple consumers. [...]
Re: isInputRange is false for non-copyable types
On Sunday, 15 April 2018 at 06:39:43 UTC, Jonathan M Davis wrote: On Sunday, April 15, 2018 07:26:54 Shachar Shemesh via Digitalmars-d wrote: [...] It's extremely common for range-based functions to copy front. Even foreach does it. e.g. [...] Arguably it should “move” them. This would have worked if input ranges didn’t have to cache front to support multiple ‘front’ calls before popFront. Which is a painful misfeature really as all algorithms would optimize for touching front once anyway. Input range should “produce” elements not keep cache of them, forward ranges may cache current item alright. [...]
Re: Why is the error message coming by the end of the compilation?
On Saturday, 14 April 2018 at 08:20:51 UTC, bauss wrote: The problem is I can't pragma(msg) the code I want to mixin manually since all mixins are dynamically generated. That's why my only way is to do it within that static foreach. Wat. So the compiler is able to generate the string you want to mixin, but not print it? If you try this: static foreach (viewResult; generateViewsResult) { pragma(msg, "Compiling: " ~ viewResult.name); pragma(msg, viewResult.source); pragma(msg, "Compiled: " ~ viewResult.name); } Does it blow up? Does it print gibberish? Does it complain in any way? I initially tried to just use __traits(compiles) but it fails even on the valid generated D code. This also sounds weird. Are you missing brackets around the generated code? If the generated code consists of more than one expression, you generally have to check __traits(compiles, { mixin(foo()); }). From reading your messages here it seems the mixin simply contains a class. This test shows the difference: enum s = "class A {}"; // Global scope: static assert(!__traits(compiles, mixin(s))); static assert(__traits(compiles, { mixin(s); })); unittest { // Function scope: static assert(!__traits(compiles, mixin(s))); static assert(__traits(compiles, { mixin(s); })); } As we can see, the version with extra brackets compiles, the other does not. I wish there was a way to give a mixin some kind of identity like: mixin("mymixin", "somecode"); Where an error message would print something like: Error in mixin("mymixin"): ... That seems like a very good idea. Posted it in D.general: https://forum.dlang.org/post/epqmzhjoyqcdqrqks...@forum.dlang.org -- Simen
File names in string mixins
In a thread[0] over on D.learn, bauss suggested adding a second argument to MixinExpressions, such that mixin("foo()", "my mixin") compiles. The use case for the extra argument is as an identifier that will be used in error messages, where the current behavior is to create a virtual file name on the form __FILE__-mixin-__LINE__. Instead of this behavior: unittest { // .\foo.d-mixin-17(17): Error: undefined identifier bar mixin("bar();"); } You would have this behavior: unittest { // My mixin(1): Error: undefined identifier bar mixin("bar();", "My mixin"); } A toy example like this doesn't really show how useful this would be, but in a more complex use case where multiple mixins are generated from different template arguments, in a static foreach, etc, the relevant context may be added by the programmer as he writes the code: static foreach (i, item; getCodeSources()) { mixin(item.generateCode(), "Code source "~i.to!string); } When the above code fails on item 15, the error message would immediately show "Code source 15(__LINE__): ", making it much easier to figure out where to start fixing. Destroy! -- Simen [0]: https://forum.dlang.org/post/tbyqqefafgzfiltgl...@forum.dlang.org
Re: d2sqlite3 db.run, where lies the bug?
On Wednesday, 11 April 2018 at 11:00:30 UTC, ag0aep6g wrote: On 04/11/2018 04:08 AM, Ralph Amissah wrote: Generous, I merely stumbled on it and shouted out, you fixed it. I would be grateful if you please file the bug and your fix. There you go: https://github.com/biozic/d2sqlite3/pull/43 Thanks for fixing this ! -- Nicolas
Re: dub 2.079.1-beta.1 test failures on Mac OSX 10.13.5 Beta
On Sunday, 15 April 2018 at 00:52:21 UTC, Martin Nowak wrote: Does the dub beta work for you though? Have you tried the official binary? Dub's CI tests were so far targeted at linux and might have some issues with OS dependent differences. On other platform's we've only been running unit-tests, but not the integration test-suite. -Martin Haven't tried the official binary. It's also not useful with Nix. I package dub versions regularly on Nix and see those errors for the first time on Mac OSX. I looked at the travis script and it seems you are testing by invoking the run-unittest.sh script too. How do I just run the unittests without the integration test-suite? I packaged the final release version of 1.8.1 and everything worked fine. Strange. With 1.8.1-beta.1 I tried it two times and got the same errors. So not a big problem anymore since I only really package release versions. Still, it would be interesting to know what's going on.
Re: How/where to hack DMD to generate docs for string mixed members.
On Sunday, April 15, 2018 07:59:17 Stefan Koch via Digitalmars-d-learn wrote: > On Sunday, 15 April 2018 at 05:20:31 UTC, 9il wrote: > > Hey, > > > > How/where to hack DMD to generate docs for string mixed members? > > > > struct S > > { > > > > mixin(" > > > > /// > > auto bar() {} > > > > "); > > > > } > > > > Best regards, > > Ilya Yaroshenko > > hmm you should be able to see docs for string mixins, if not. > try using -vcg-ast and try to run ddoc on the cg file AFAIK, it's never worked to see any ddoc from string mixins. Certainly, I'm quite sure that it didn't used to work, so if it does now, something changed within the last couple of years. The closest that I'm aware of is that putting /// on a template mixin works so that you can do something like class MyException : Exception { /// mixin basicExceptionCtors; } and have the ddoc within the template mixin show up. - Jonathan M Davis
Re: How/where to hack DMD to generate docs for string mixed members.
On Sunday, 15 April 2018 at 05:20:31 UTC, 9il wrote: Hey, How/where to hack DMD to generate docs for string mixed members? struct S { mixin(" /// auto bar() {} "); } Best regards, Ilya Yaroshenko hmm you should be able to see docs for string mixins, if not. try using -vcg-ast and try to run ddoc on the cg file
Re: isInputRange is false for non-copyable types
On Sunday, April 15, 2018 07:26:54 Shachar Shemesh via Digitalmars-d wrote: > import std.range; > import std.stdio; > > struct S { > int a; > > @disable this(this); > } > > void main() { > writeln(isInputRange!(S[])); // Prints false > } > > The reason, as far as I can tell, is that an input range requires that > we can do: > > auto a = ir.front; // Assuming ir isn't empty > > That doesn't work for non-copyable types, for obvious reasons. > > With that said, that seems more like a deficiency in the input range > definition than anything. There is no reason we shouldn't be able to > iterator type operations over non-copyable types. It's extremely common for range-based functions to copy front. Even foreach does it. e.g. import std.stdio; struct S { this(int i) { _i = i; } this(this) { writefln("copied: %s", _i); } int _i; } void main() { foreach(e; [S(0), S(1), S(2)]) { } } prints copied: 0 copied: 1 copied: 2 If non-copyable types were allowed, then no function which accepted a range would be allowed to copy front without first checking that front was copyable (something that most code simply isn't going to do), and some functions outright require being able to copy front. They could test for copyability, but that would complicate a lot of range-based functions for a relatively rare corner case (much as it obviously matters to any code that has that corner case). Remember also that a large percentage of ranges that don't wrap dynamic arrays put their elements on the stack, which means that whenever the range is copied, the elements are copied. e.g. if the above example uses std.range.only instead of an array literal, it actually prints copied: 0 copied: 1 copied: 2 copied: 0 copied: 1 copied: 2 copied: 0 copied: 1 copied: 2 I'm not sure why it ends up printing each of them 3 times rather than 2, but the fact that foreach copies any range that it's given means that in order to have ranges allow non-copyable types, we'd have to change how foreach worked, which would break a lot of code. Right now, foreach(e; range) { } is lowered to something like for(auto __range = range; !__range.empty; __range.popFront()) { auto e = __range.front; } That requires both copying the range and copying front. We could theoretically change it so that everywhere that e was used, it would be replaced with __range.front so that front wasn't copied and probably wouldn't break code in the process (though it could affect performance), but if we made it so that the range itself wasn't copied, then instead of iterating over a copy, foreach would consume the original range, which would definitely break a lot of code. Now, generic range-based code really shouldn't ever use a range after it's been copied, since whether mutating the copy affects the original depends on the implementation of the range (and thus generic code should assume that foreach may have consumed the range and call save if it doesn't want that to happen), but lots of code does it anyway, and if the code isn't generic, it can work just fine, since then the code can depend on the semantics of that specific range type instead of having to work with the semantics of arbitrary ranges. e.g. if code is written specifically for dynamic arrays rather than ranges in general, then calling save to iterate over a separate slice would be silly, but if the code doesn't currently call save, and foreach were changed to not copy the range, then all of a sudden code like string str = "hello world"; foreach(c; str) { } would consume the dynamic array instead of iterating over a separate slice. Also, in order for a range to work with a non-copyable type, either front would have to return by ref or it would have to construct a new object to return so that it could be moved rather than copied. I expect that quite a few ranges would have problems with such a restriction, and certainly, even if a range could have its front changed to return by ref, the range would no longer be able to guarantee that the caller couldn't mutate the value of front, which would cause problems in at least some cases. In addition, it's quite possible that forcing functions to not copy front would hurt performance. In some cases, by using front directly, you can avoid a copy (e.g. it returns by ref), but in others, the value of front is calculated every time it's called. So, depending on the implementation of the range, calling front repeatedly can be more expensive than simply copying the value and reusing it. As such, it's not necessarily a good idea to force range-based code to not copy front. Also, it's not uncommon for ranges to store the value of front (e.g. it's calculated every time that popFront is called), and that wouldn't work with non-copyable types. Also, if such ranges were changed to calculate the value in front to then work with non-copyable types, whatever calculation they were doing would then have to