Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 15:50:18 UTC, Dennis wrote: [...] care about the type / mutability of the pointer. Returning `i`'s address in a long does not trigger the escape detector: ``` long foo (long s, return ref int i) { s = cast (long) return s; } auto bar () { int i; long s; return foo (s, i); } ``` dmd compiles this without complaints.
Re: class variable initialization
On 4/15/23 09:06, NonNull wrote: >> struct Wrapper >> { >>Object x = new Object(); >>alias x this; >> } > Amazing, was this always so? At least for a long time. However, every Wrapper object will have a pointer to that single shared object. If you think that cost is unnecessary, you can have a static variable: struct Wrapper { static Object x; alias x this; } static this() { Wrapper.x = new Object(); } However, because such data are thread-local by-default, not the entire class, but each thread will have a copy that variable. When you want a single class variable for all threads, then it must be defined as shared: struct Wrapper { shared static Object x; alias x this; } shared static this() { Wrapper.x = new Object(); } void foo(shared Object o) { assert(o !is null); } Note how foo's interface had to be changed as well. And of course you may have to provide thread synchronization when that variable needs to be mutated at run time. Ali
Re: How to use @safe when a C library integration needed
On Friday, 14 April 2023 at 16:19:22 UTC, Paul Backus wrote: On Friday, 14 April 2023 at 14:10:41 UTC, Leonardo wrote: [...] No, there isn't. C is an unsafe language, so if you want to call C from `@safe` code, you have to do the work to make sure that each individual call is `@safe`. [...] Thanks for your response.
Re: class variable initialization
On Saturday, 15 April 2023 at 15:47:40 UTC, Steven Schveighoffer wrote: You can construct objects at compile time. If I understand your question properly: ```d struct Wrapper { Object x = new Object(); alias x this; } void foo(Object o) { assert(o !is null); } void main() { Wrapper w; foo(w); } ``` -Steve Amazing, was this always so?
Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 14:33:52 UTC, kdevel wrote: Does that make sense? Whether it makes sense is subjective, but it is by design. Escape analysis considers every pointer the same, it doesn't care about the type / mutability of the pointer. In `@system` / `@trusted` code, you could coerce `i` to become a string and return it: ```D string foo(string s, return ref int i) { return (cast(immutable char*) )[0..4]; } ```
Re: class variable initialization
On 4/15/23 7:05 AM, NonNull wrote: I want a way to default initialize a class variable to a default object (e.g. by wrapping it in a struct, because initialization to null cannot be changed directly). Such a default object is of course not available at compile time which seems to make this impossible. Can this be done in some way? You can construct objects at compile time. If I understand your question properly: ```d struct Wrapper { Object x = new Object(); alias x this; } void foo(Object o) { assert(o !is null); } void main() { Wrapper w; foo(w); } ``` -Steve
Re: class variable initialization
On Saturday, 15 April 2023 at 14:17:19 UTC, Vijay Nayar wrote: I believe if you do initialization at the class declaration level, then every instance of the class shares the same instance, e.g.: ``` class Var {} class MyClass { Var var = new Var(); } void main() { MyClass c1 = new MyClass(); MyClass c2 = new MyClass(); assert(c1.var is c2.var); } ``` I should have made it clear that want a single shared default object. Your code above solves that problem. So does ``` Var defaultObj; static this() { defaultObj = new Var(); } ``` By wrapping the new variable and the constructor call to initialize it in MyClass, you eliminate the need to call the constructor, which is what I want, but now you add the need to call another constructor. So for my purposes this is just moving the problem of null to another place.
Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 14:10:57 UTC, Dennis wrote: [...] This adds complexity, just to add some 'intermediate' safety between `@system` and `@safe` in a few cases. It's better to keep the rules simple and consistent. Thanks for the answer! While playing around with return ref I came across this: ``` string foo (string s, return ref int i) { return s; } auto bar () { int i; string s; return foo (s, i); } ``` ``` $ dmd rr.d rr.d(10): Error: returning `foo(s, i)` escapes a reference to local variable `i` ``` Does that make sense?
Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 14:10:57 UTC, Dennis wrote: This adds complexity, just to add some 'intermediate' safety between `@system` and `@safe` in a few cases. It's better to keep the rules simple and consistent. To quote my past self: There used to be different rules for lifetime errors in all of these: - explicit `@system` functions - `@system` by default functions (yes, [they were special](https://issues.dlang.org/show_bug.cgi?id=19873)) - inferred functions - `@safe` functions - `@trusted` functions It was really complex and confusing, and I've worked on simplifying it such that all lifetime errors are safety violations like any other. The only exception is directly returning a dangling pointer to a stack variable, which is just an error even in @system code ([issue 19873](https://issues.dlang.org/show_bug.cgi?id=19873)). I don't want to go back to more special cases, especially with the dip1000 by default transition which is complex enough as is. https://forum.dlang.org/post/nzotevvzvbpqscfxs...@forum.dlang.org
Re: class variable initialization
On Saturday, 15 April 2023 at 14:05:17 UTC, NonNull wrote: I want a way to default initialize a class variable to a default object (e.g. by wrapping it in a struct, because initialization to null cannot be changed directly). Such a default object is of course not available at compile time which seems to make this impossible. Can this be done in some way? Assuming you want a default object that is unique per class instance rather than shared among all instances of the same class, then I think the constructor might be where you want to initialize such a member. E.g. ``` class Var { int val; this(int val) { this.val = val; } } class MyClass { Var var; this() { var = new Var(3); } } ``` I believe if you do initialization at the class declaration level, then every instance of the class shares the same instance, e.g.: ``` class Var {} class MyClass { Var var = new Var(); } void main() { MyClass c1 = new MyClass(); MyClass c2 = new MyClass(); assert(c1.var is c2.var); } ```
Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 13:20:09 UTC, kdevel wrote: Under which circumstances is it a mistake to insert the `return` at the indicated position? If there are none why can't it be done implicitly (automatically)? It could be done in the easy example you posted, but generalizing it is harder. When importing a module, the compiler currently doesn't need to analyze function bodies to get the signature of regular (non-auto/template) functions, which would have to change. Programmers can also currently rely on the fact that the signature they see is the signature they get, but not any longer. The identity function is really simple, but as soon as control flow (if-statements) come into play, the annotations and their inference become a conservative approximation, which might give false positives in `@system` code. There would need to be a second system, one which assumes the best instead of assuming the worst. This adds complexity, just to add some 'intermediate' safety between `@system` and `@safe` in a few cases. It's better to keep the rules simple and consistent.
class variable initialization
I want a way to default initialize a class variable to a default object (e.g. by wrapping it in a struct, because initialization to null cannot be changed directly). Such a default object is of course not available at compile time which seems to make this impossible. Can this be done in some way?
Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 13:24:52 UTC, Richard (Rikki) Andrew Cattermole wrote: On 16/04/2023 1:20 AM, kdevel wrote: On Saturday, 15 April 2023 at 12:45:31 UTC, Richard (Rikki) Andrew Cattermole wrote: It was bad analysis by the compiler, which has since been corrected. It should have been applied only to @safe code. But why is the @unsafe programmer now left unprotected in cases like this ``` ref int foo (ref int i) // `--- automatically insert `return` here? { return i; } ``` where the compiler recognizes that the function returns a ref parameter? Under which circumstances is it a mistake to insert the `return` at the indicated position? If there are none why can't it be done implicitly (automatically)? @system (which is currently the default, there is a strong desire to change this), does no safety checks. When I insert `return` before `ref int` and compile the code dmd says ``` returnref2.d(9): Error: returning `foo(i)` escapes a reference to local variable `i` ``` Isn't this a safety check? (The code does not contain any `@`.) My question was if it is problematic if dmd inserted a `return` before any `ref` parameter a function returns. Did the removed code which checked for returning ref parameters have false positives? If not again my question: Under what circumstances would it be a mistake to insert `return` before the respective `ref` parameter?
Re: Returning a reference to be manipulated
On 16/04/2023 1:20 AM, kdevel wrote: On Saturday, 15 April 2023 at 12:45:31 UTC, Richard (Rikki) Andrew Cattermole wrote: It was bad analysis by the compiler, which has since been corrected. It should have been applied only to @safe code. But why is the @unsafe programmer now left unprotected in cases like this ``` ref int foo (ref int i) // `--- automatically insert `return` here? { return i; } ``` where the compiler recognizes that the function returns a ref parameter? Under which circumstances is it a mistake to insert the `return` at the indicated position? If there are none why can't it be done implicitly (automatically)? @system (which is currently the default, there is a strong desire to change this), does no safety checks. You are on your own to do whatever unsafe thing you want. If you want safety checks, use @safe.
Re: Returning a reference to be manipulated
On Saturday, 15 April 2023 at 12:45:31 UTC, Richard (Rikki) Andrew Cattermole wrote: It was bad analysis by the compiler, which has since been corrected. It should have been applied only to @safe code. But why is the @unsafe programmer now left unprotected in cases like this ``` ref int foo (ref int i) // `--- automatically insert `return` here? { return i; } ``` where the compiler recognizes that the function returns a ref parameter? Under which circumstances is it a mistake to insert the `return` at the indicated position? If there are none why can't it be done implicitly (automatically)?
Re: Returning a reference to be manipulated
It was bad analysis by the compiler, which has since been corrected. It should have been applied only to @safe code.
Re: Returning a reference to be manipulated
On Friday, 14 April 2023 at 11:18:21 UTC, Dennis wrote: On Friday, 14 April 2023 at 10:31:58 UTC, kdevel wrote: But in fact it is returned unless it is `return ref`. When using `return ref`, `return scope`, `scope` etc., you should be using the latest compiler and annotate functions you want checked with `@safe`. We are writing at cross puroposes. I am not asking how I could help the compiler. My point is: I have code from 2019 which produced a deprecation warning ``` returnref2.d(3): Deprecation: returning i escapes a reference to parameter i, perhaps annotate with return ``` when compiled with with the compiler of that time (v2.093.1). When I use a recent compiler (v2.102.2) the code compiles without any complaints. I am asking myself what has deprecacted? I mean: Deprecation notes are built into the compiler in order to enable a "soft landing" for a scheduled breaking change. But I cannot see any breaking change at all regarding the code example in https://forum.dlang.org/post/iysfuhjwyalnnmalb...@forum.dlang.org
Re: Memory leak issue between extern (c) and D function
On 4/13/23 20:50, backtrack wrote: > mystruct* getmystruct() > { > mystruct* mystruct = cast(mystruct*)malloc(mystruct.sizeof); > return mystruct; > > } There must be a corresponding function to do the cleaning: void freemystruct(mystruct* ptr) { free ptr; } You have to make sure on the D side that freemystruct() is called once for each getmystruct(). I have the following presentation that covers similar concepts: https://www.youtube.com/watch?v=FNL-CPX4EuM I think this point is most relevant: https://www.youtube.com/watch?v=FNL-CPX4EuM=1833s Ali