Re: Best way to make a template function conditionally @trusted
On Friday, 2 April 2021 at 19:49:30 UTC, ikod wrote: On Thursday, 1 April 2021 at 22:35:01 UTC, tsbockman wrote: Suppose I have a templated struct member function for which I can compute at compile-time when the function is memory safe, and when it is not. But, the compiler cannot correctly determine this automatically. Compiler should be able to derive safety of templated functions. You may just omit `@safe`/`@trusted`. The compiler's approach to verifying memory safety is very simplistic: it declares a function non-`@safe` if any potentially unsafe operation is found in its implementation, without regard for the context. It can only ever infer `@safe` or `@system`, never `@trusted`. The reason `@trusted` is in the language at all is to allow the programmer to manually mark as memory safe those functions which contain operations that would be unsafe in some other context, but which the programmer has manually analyzed and verified to be incapable of violating memory safety, no matter what inputs it receives. Consider the following program: ```D import std.stdio; void writeSafe()(int[2] stuff ...) { foreach(n; 0 .. stuff.length) writeln(stuff[n]); } void writeTrusted()(int[2] stuff ...) { foreach(n; 0 .. stuff.length) writeln(stuff.ptr[n]); } void main() @safe { writeSafe(3, 5); writeTrusted(3, 5); } ``` `writeSafe` and `writeTrusted` generate identical code, and are equally memory safe in reality. The compiler even knows this on some level, because it correctly deduces that the bounds check for `stuff[n]` can never fail, and omits it even in `writeSafe`. Nevertheless, because `.ptr` can be used to violate memory safety in other contexts, `writeSafe` is inferred as `@safe`, while `writeTrusted` is inferred as `@system`. And so, the program above will not compile as it stands. This is, of course, a trivial example where there is no benefit to using the non-`@safe` version, but there are more complex cases where the desired algorithm is memory safe as a whole, but it cannot be expressed in D without using some operations that are forbidden in `@safe` code.
Re: Example for Mir-Random fails
On Saturday, 3 April 2021 at 20:55:40 UTC, Preetpal wrote: On Saturday, 3 April 2021 at 19:02:34 UTC, Brad wrote: Obviously it is a type mismatch - I have tried using to!uint to convert the result from unpredictableSeed to a type that will match - but that just causes more errors. Thank you in advance. I was able to compile the sample without any issue and it was able to run. Can you give more information about your environment and possibly create a minimal example that re-creates the issue like in a Github repository? I figured out that I had not purged all the Phobos random imports from my code and the issue was related to the two libraries not playing well together. It is working now. Interestingly though - the example code will not compile in the D Playground. I am not going to worry about that. It is working for me now. Thanks
Re: Example for Mir-Random fails
On Saturday, 3 April 2021 at 22:04:33 UTC, Bastiaan Veelo wrote: On Saturday, 3 April 2021 at 19:02:34 UTC, Brad wrote: I just do not know enough about the D libraries to figure out what is wrong. I know it is a case of type mismatch. The example appears on the Mir-Random page as listed under DUB: https://code.dlang.org/packages/mir-random [...] I think you are seeing conflicts between Phobos and Mir: they both provide unpredictableSeed and Random. If you want to use the ones from Mir, be sure to not import std or std.random, or use fully qualified names. — Bastiaan. You nailed it. I just now figured that out. It never ceases to amaze me how much time can my lost to a simple mistake like that. Thank you.
Re: Example for Mir-Random fails
On Saturday, 3 April 2021 at 19:02:34 UTC, Brad wrote: I just do not know enough about the D libraries to figure out what is wrong. I know it is a case of type mismatch. The example appears on the Mir-Random page as listed under DUB: https://code.dlang.org/packages/mir-random [...] I think you are seeing conflicts between Phobos and Mir: they both provide unpredictableSeed and Random. If you want to use the ones from Mir, be sure to not import std or std.random, or use fully qualified names. — Bastiaan.
Re: Example for Mir-Random fails
On Saturday, 3 April 2021 at 19:02:34 UTC, Brad wrote: Obviously it is a type mismatch - I have tried using to!uint to convert the result from unpredictableSeed to a type that will match - but that just causes more errors. Thank you in advance. I was able to compile the sample without any issue and it was able to run. Can you give more information about your environment and possibly create a minimal example that re-creates the issue like in a Github repository?
Example for Mir-Random fails
I just do not know enough about the D libraries to figure out what is wrong. I know it is a case of type mismatch. The example appears on the Mir-Random page as listed under DUB: https://code.dlang.org/packages/mir-random The code looks like this: ```d void main() { import mir.random; import mir.random.variable: normalVar; import mir.random.algorithm: randomSlice; // Engines are allocated on stack or global auto rng = Random(unpredictableSeed); auto sample = rng.randomSlice(normalVar, 10); import std.stdio; sample[rng.randIndex($)].writeln; } ``` This is the error I am seeing (I slapped the sample code into another program that flips a coin... It compiles file without the sample code): ```d source\flipcoin.d(39,20): Error: constructor `std.random.MersenneTwisterEngine!(uint, 32LU, 624LU, 397LU, 31LU, 2567483615u, 11LU, 4294967295u, 7LU, 2636928640u, 15LU, 4022730752u, 18LU, 1812433253u).MersenneTwisterEngine.this(uint value)` is not callable using argument types `(ulong)` source\flipcoin.d(39,20):cannot pass argument `unpredictableSeed()` of type `ulong` to parameter `uint value` ``` Obviously it is a type mismatch - I have tried using to!uint to convert the result from unpredictableSeed to a type that will match - but that just causes more errors. Thank you in advance.
Re: Extern/scope issue
On Saturday, 3 April 2021 at 13:50:27 UTC, ag0aep6g wrote: On 03.04.21 15:34, DLearner wrote: The following produces the expected result. However, changing extern(C) to extern(D) causes linker failures. To me, that is bizarre. Testmain: extern(C) int xvar; [...] Testmod: extern extern(C) int xvar; With `extern (C)`, those two `xvar`s refer to the same data. Without `extern (C)` (or with `extern (D)`), they are distinct variables with no relation to another. In D, you don't re-declare another module's symbols. You import the other module. module testmain; import std.stdio: writeln; import testmod: testsub, xvar; void main() { xvar = 1; writeln(xvar); /* prints "1" */ testsub(); writeln(xvar); /* prints "2" */ } module testmod; int xvar; /* same as `extern (D) int xvar;` */ void testsub() { xvar = 2; } Thank you, your suggestions worked. No externs anywhere. For the record, the code is below. import itf; import testmod:testsub; void main() { import std.stdio; writeln("Entering: main"); xvar = 1; writeln("xvar=", xvar); testsub(); writeln("xvar=", xvar); writeln("Leaving: main"); } module itf; int xvar; module testmod; import itf; void testsub() { import std.stdio; writeln("Entering: testsub"); writeln("xvar=", xvar); xvar = 2; writeln("xvar=", xvar); writeln("Leaving: testsub"); }
Re: Extern/scope issue
On 04/04/2021 2:48 AM, DLearner wrote: On Saturday, 3 April 2021 at 13:38:25 UTC, rikki cattermole wrote: On 04/04/2021 2:34 AM, DLearner wrote: However, changing extern(C) to extern(D) causes linker failures. To me, that is bizarre. extern(D) sets the ABI AND mangling. D mangling incorporates things like the module name. I'm sure you are correct, but extern(C) -> extern(D) in both references. So both source streams are aware of the convention used. https://dlang.org/spec/abi.html#name_mangling
Re: Extern/scope issue
On 03.04.21 15:34, DLearner wrote: The following produces the expected result. However, changing extern(C) to extern(D) causes linker failures. To me, that is bizarre. Testmain: extern(C) int xvar; [...] Testmod: extern extern(C) int xvar; With `extern (C)`, those two `xvar`s refer to the same data. Without `extern (C)` (or with `extern (D)`), they are distinct variables with no relation to another. In D, you don't re-declare another module's symbols. You import the other module. module testmain; import std.stdio: writeln; import testmod: testsub, xvar; void main() { xvar = 1; writeln(xvar); /* prints "1" */ testsub(); writeln(xvar); /* prints "2" */ } module testmod; int xvar; /* same as `extern (D) int xvar;` */ void testsub() { xvar = 2; }
Re: Extern/scope issue
On Saturday, 3 April 2021 at 13:38:25 UTC, rikki cattermole wrote: On 04/04/2021 2:34 AM, DLearner wrote: However, changing extern(C) to extern(D) causes linker failures. To me, that is bizarre. extern(D) sets the ABI AND mangling. D mangling incorporates things like the module name. I'm sure you are correct, but extern(C) -> extern(D) in both references. So both source streams are aware of the convention used.
templated overload of opAssign
Why does this code ```d import std.stdio,std.typecons; struct EC { Exception [] ex; auto opAssign (X: void) (lazy X f) { writeln (__PRETTY_FUNCTION__); try return f (); catch (Exception e) ex ~= e; } } class E : Exception { this (string s) { super (s); } } void bar (int i) { if (i == 1) throw new E ("E"); } void main () { EC ec; ec.opAssign (bar (1)); // okay // ec = bar (1); // Error: expression bar(1) is void and has no value ec.writeln; } ``` compile with the abovementioned error?
Re: Extern/scope issue
On 04/04/2021 2:34 AM, DLearner wrote: However, changing extern(C) to extern(D) causes linker failures. To me, that is bizarre. extern(D) sets the ABI AND mangling. D mangling incorporates things like the module name.
Re: Extern/scope issue
The __gshared is irrelevant to it working between modules, but it is relevant if you want C compatibility between threads (NOTE: extern(C) sets mangling, otherwise the module would be encoded in its name). Solved: The following produces the expected result. However, changing extern(C) to extern(D) causes linker failures. To me, that is bizarre. Testmain: extern(C) int xvar; import testmod; void main() { import std.stdio; writeln("Entering: main"); xvar = 1; writeln("xvar=", xvar); testsub(); writeln("xvar=", xvar); writeln("Leaving: main"); } Testmod: extern extern(C) int xvar; void testsub() { import std.stdio; writeln("Entering: testsub"); writeln("xvar=", xvar); xvar = 2; writeln("xvar=", xvar); writeln("Leaving: testsub"); }
Re: Extern/scope issue
--- main.d module main; extern(C) __gshared int foo; import std; void main() { import foo : func; func; writeln(foo); } --- foo.d module foo; extern extern(C) __gshared int foo; void func() { foo++; } The __gshared is irrelevant to it working between modules, but it is relevant if you want C compatibility between threads (NOTE: extern(C) sets mangling, otherwise the module would be encoded in its name).
Re: Extern/scope issue
https://dlang.org/spec/attribute.html#gshared However, you should be using the module system for accessing globals, rather than redeclaring them. If the module system is dumped, and evrything put into one file, works perfectly. With or without __gshared in from of 'int xvar'. int xvar; void main() { import std.stdio; writeln("Entering: main"); xvar = 1; writeln("xvar=", xvar); testsub(); writeln("xvar=", xvar); writeln("Leaving: main"); } void testsub() { import std.stdio; writeln("Entering: testsub"); writeln("xvar=", xvar); xvar = 2; writeln("xvar=", xvar); writeln("Leaving: testsub"); }
Re: Extern/scope issue
extern(L) extern otherQualifiersIfAny variableType variableName; //appears to be a variable declared outside of the module, so at link time a .obj file will have to declare a variable with this symbol name or else the linker will error out. ``` It seems that case 4 is what you desired but i do not know if with this module hierarchy it can/will work with dub.(it should.) With the code as is you should be able to access both variables from main with `testmod.xvar` and simply `xvar`.(when name conflicts like this occur the most local is used by default, otherwise use the full name which should be `testmain.xvar` in this case.) I tried case 4, failed with link errors. I am not trying to establish two variables, just exactly the same one everywhere. That's why the desired test output is 1,1,2,2
Re: Extern/scope issue
Tried the following, same result (1,0,2,1): testmain: __gshared int xvar; import testmod; void main() { import std.stdio; writeln("Entering: main"); xvar = 1; writeln("xvar=", xvar); testsub(); writeln("xvar=", xvar); writeln("Leaving: main"); } testmod: void testsub() { __gshared int xvar; import std.stdio; writeln("Entering: testsub"); writeln("xvar=", xvar); xvar = 2; writeln("xvar=", xvar); writeln("Leaving: testsub"); }
Re: Extern/scope issue
On Saturday, 3 April 2021 at 10:17:14 UTC, DLearner wrote: Does this mean D has no equivalent of C globals? What is the D way of doing this? With __gshared. If the global is defined from within another language, apparently you'd have to do [extern(C) extern __gshared *name*](https://dlang.org/spec/interfaceToC.html#c-globals) It seems that the whole extern keyword can be confusing with variables: ```d //L is the language name extern(L) returnType functionName(parameters); // function implemented in another language or out of this module. extern(L) returnType functionName(parameters) {/*...*/}//extern only changes the name mangling and the calling rules in the resulting assembly code.(with D it does not change anything?) extern(L) variableType variableName; //what you did, declares a normal variable, except that the name mangling rule is that of the language you specified. extern(L) extern otherQualifiersIfAny variableType variableName; //appears to be a variable declared outside of the module, so at link time a .obj file will have to declare a variable with this symbol name or else the linker will error out. ``` It seems that case 4 is what you desired but i do not know if with this module hierarchy it can/will work with dub.(it should.) With the code as is you should be able to access both variables from main with `testmod.xvar` and simply `xvar`.(when name conflicts like this occur the most local is used by default, otherwise use the full name which should be `testmain.xvar` in this case.)
Re: Extern/scope issue
On 03/04/2021 11:17 PM, DLearner wrote: On Saturday, 3 April 2021 at 10:05:45 UTC, rikki cattermole wrote: On 03/04/2021 11:01 PM, DLearner wrote: [...] TLS variable with D mangling, not a c global. [...] That is a regular variable. Setting the calling convention/mangling like that doesn't make any sense and shouldn't be allowed in context. [...] TLS variable with D mangling, not a c global. Does this mean D has no equivalent of C globals? What is the D way of doing this? https://dlang.org/spec/attribute.html#gshared However, you should be using the module system for accessing globals, rather than redeclaring them.
Re: Deprecation message when assigning Nullable values to an associative array.
On Saturday, 3 April 2021 at 10:03:09 UTC, rikki cattermole wrote: On 03/04/2021 10:58 PM, rikki cattermole wrote: Nullable has an alias this which has been deprecated. It is due for removal (the alias this). You can remove it manually from your copy of phobos source. Otherwise you'll just have to wait until it is removed upstream. (deprecation are not errors, so you can ignore them). So yeah, next release. https://github.com/dlang/phobos/commit/36c309fc5fb5bc886e14bd8010e1375fa3a57d53#diff-81bed7f05cbd4e992067b7019125e6a1349ebe5098c6980b64bbbca8d5491e17 Thank you. I am happy with this situation. PJ
Re: Extern/scope issue
On Saturday, 3 April 2021 at 10:05:45 UTC, rikki cattermole wrote: On 03/04/2021 11:01 PM, DLearner wrote: [...] TLS variable with D mangling, not a c global. [...] That is a regular variable. Setting the calling convention/mangling like that doesn't make any sense and shouldn't be allowed in context. [...] TLS variable with D mangling, not a c global. Does this mean D has no equivalent of C globals? What is the D way of doing this?
Re: Extern/scope issue
On 03/04/2021 11:01 PM, DLearner wrote: 'Testmain' imports module 'testmod'. Both are shown below. I expected 1,1,2,2. I got 1,0,2,1 - which speaks to scope/extern misunderstanding Any ideas? Best regards Testmain: int xvar; TLS variable with D mangling, not a c global. import testmod; void main() { import std.stdio; writeln("Entering: main"); xvar = 1; writeln("xvar=", xvar); testsub(); writeln("xvar=", xvar); writeln("Leaving: main"); } Testmod: void testsub() { extern(D) int xvar; That is a regular variable. Setting the calling convention/mangling like that doesn't make any sense and shouldn't be allowed in context. import std.stdio; writeln("Entering: testsub"); writeln("xvar=", xvar); xvar = 2; writeln("xvar=", xvar); writeln("Leaving: testsub"); }
Extern/scope issue
'Testmain' imports module 'testmod'. Both are shown below. I expected 1,1,2,2. I got 1,0,2,1 - which speaks to scope/extern misunderstanding Any ideas? Best regards Testmain: int xvar; import testmod; void main() { import std.stdio; writeln("Entering: main"); xvar = 1; writeln("xvar=", xvar); testsub(); writeln("xvar=", xvar); writeln("Leaving: main"); } Testmod: void testsub() { extern(D) int xvar; import std.stdio; writeln("Entering: testsub"); writeln("xvar=", xvar); xvar = 2; writeln("xvar=", xvar); writeln("Leaving: testsub"); }
Re: Deprecation message when assigning Nullable values to an associative array.
On 03/04/2021 10:58 PM, rikki cattermole wrote: Nullable has an alias this which has been deprecated. It is due for removal (the alias this). You can remove it manually from your copy of phobos source. Otherwise you'll just have to wait until it is removed upstream. (deprecation are not errors, so you can ignore them). So yeah, next release. https://github.com/dlang/phobos/commit/36c309fc5fb5bc886e14bd8010e1375fa3a57d53#diff-81bed7f05cbd4e992067b7019125e6a1349ebe5098c6980b64bbbca8d5491e17
Re: Deprecation message when assigning Nullable values to an associative array.
Nullable has an alias this which has been deprecated. It is due for removal (the alias this). You can remove it manually from your copy of phobos source. Otherwise you'll just have to wait until it is removed upstream. (deprecation are not errors, so you can ignore them).
Deprecation message when assigning Nullable values to an associative array.
I am using the OpenMPI binding and, in recent times, I have been getting a deprecation message when compiling. It seems to be related to assigning Nullable!int entries to an associative array. The following program shows the same message three times but it does run as I expect. import std.stdio, std.typecons; void main(string[] args) { Nullable!(int)[string] my_entries; // First way. my_entries["A"] = Nullable!int.init; // Second way. Nullable!(int) empty; my_entries["B"] = empty; // Third way. my_entries["C"] = 0.nullable; my_entries["C"].nullify(); writeln("my_entries=", my_entries); Nullable!(int) b = Nullable!int.init; writeln("b=", b); Nullable!(int) c = 0.nullable; writeln("c=", c); } peterj@helmholtz ~/work/play/dlang $ dmd null_test.d null_test.d(7): Deprecation: function `std.typecons.Nullable!int.Nullable.get_` is deprecated - Implicit conversion with `alias Nullable.get this` will be removed after 2.096. Please use `.get` explicitly. null_test.d(10): Deprecation: function `std.typecons.Nullable!int.Nullable.get_` is deprecated - Implicit conversion with `alias Nullable.get this` will be removed after 2.096. Please use `.get` explicitly. null_test.d(12): Deprecation: function `std.typecons.Nullable!int.Nullable.get_` is deprecated - Implicit conversion with `alias Nullable.get this` will be removed after 2.096. Please use `.get` explicitly. peterj@helmholtz ~/work/play/dlang $ ./null_test my_entries=["A":Nullable.null, "C":Nullable.null, "B":Nullable.null] b=Nullable.null c=0 Can someone please tell me how I should set these associative array entries such that I keep the compiler happy?