Re: what are the rules for @nogc and @safe attributes inference?
On Fri, 30 Nov 2018 22:10:11 +, ikod wrote: > Thanks for explanation, got it. > > My case is actually > > interface I(K,V) > { > int get()(K); > } Interface functions must be abstract. Templated functions are implicitly final. Final things can't be abstract. If there's something about types K and V that determine whether you should be able to use the GC or not, you'll have to encode that explicitly.
Re: what are the rules for @nogc and @safe attributes inference?
On Friday, 30 November 2018 at 21:03:06 UTC, Neia Neutuladh wrote: On Fri, 30 Nov 2018 20:41:03 +, ikod wrote: I can't find the reason why nogc/nothrow can't be inferred in this case: class S(K,V) { auto get/*()*/(K a) { return 0; } } void main() @nogc nothrow { S!(int, string) sia; auto v = sia.get(1); } class Nefarious : S!(int, string) { override int get(int a) { // Whoops, I used the GC return new char[a].length; } } The compiler can't prove that a variable of type S!(int, string) will not be of type Nefarious, which uses the GC, so it can't infer @nogc for S.get. However, if you make the function final, then the compiler can infer it to be pure nothrow @nogc @safe. Or if you use a struct instead of a class, structs don't do inheritance, so the compiler can infer attributes without worrying about nefarious inheritance. But everything is ok if you uncomment parentheses after get. Templated functions are implicitly final. Thanks for explanation, got it. My case is actually interface I(K,V) { int get()(K); } class S(K,V) : I!(K, V) { int v; int get()(K a) { return v; } } void main() nothrow { S!(int, string) s = new S!(int, string); s.get(1); } My goal is to allow compiler to infer all properties of s.get without adding nothrow/nogc anywhere. And these templated functions is only way it works for me. Is it ok? Or there is better solution? Thanks!
Re: what are the rules for @nogc and @safe attributes inference?
On Fri, 30 Nov 2018 20:41:03 +, ikod wrote: > I can't find the reason why nogc/nothrow can't be inferred in this case: > > class S(K,V) > { > auto get/*()*/(K a) { > return 0; > } > } > void main() @nogc nothrow { > S!(int, string) sia; > auto v = sia.get(1); > } class Nefarious : S!(int, string) { override int get(int a) { // Whoops, I used the GC return new char[a].length; } } The compiler can't prove that a variable of type S!(int, string) will not be of type Nefarious, which uses the GC, so it can't infer @nogc for S.get. However, if you make the function final, then the compiler can infer it to be pure nothrow @nogc @safe. Or if you use a struct instead of a class, structs don't do inheritance, so the compiler can infer attributes without worrying about nefarious inheritance. > But everything is ok if you uncomment parentheses after get. Templated functions are implicitly final.
Re: what are the rules for @nogc and @safe attributes inference?
On Thursday, 15 November 2018 at 21:55:18 UTC, Steven Schveighoffer wrote: On 11/15/18 4:09 PM, Adam D. Ruppe wrote: On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template. Well, the general "rule" is, if it's code that must be available to the compiler when it's called, then it will be inferred. Examples of code that must be processed every time it's used: 1. Template functions 2. auto-returning functions 3. functions inside templates (like member functions of a templated struct) 4. Inner functions There may be others I didn't think of. Everything else must be manually attributed. The reasoning is that the function may be stubbed in a .di file, and in that case, attribute inference wouldn't be possible. -Steve Hello, Steve! I can't find the reason why nogc/nothrow can't be inferred in this case: class S(K,V) { auto get/*()*/(K a) { return 0; } } void main() @nogc nothrow { S!(int, string) sia; auto v = sia.get(1); } But everything is ok if you uncomment parentheses after get. get is already a member of templated class, what can be wrong with this code? Thanks!
Re: what are the rules for @nogc and @safe attributes inference?
On Friday, 16 November 2018 at 12:12:12 UTC, Alex wrote: = This code compiles as long as `lazy` is commented out. But I'd like to have both lazy parameter and @nogc inferrence for `library_func` so that user is not locked to code @nogc or not. Aha, aha... Interesting! I had a similar problem with passing a delegate. And it was solved: https://forum.dlang.org/thread/erznqknpyxzxqivaw...@forum.dlang.org For your problem, there is a bug report: https://forum.dlang.org/post/wedwfooqdxbwxttpm...@forum.dlang.org https://issues.dlang.org/show_bug.cgi?id=12664 https://issues.dlang.org/show_bug.cgi?id=12647 Thanks for these links. And yes, I have workaround with handmade delegate. It compiles and it is lazy, but also ugly. import std.traits; T library_func(T)(/*not lazy*/ T i) if (!isCallable!T) { return i; } ReturnType!T library_func(T)(/*lazy*/ T i) if (isCallable!T) { return i(); } void user_function_nogc() @nogc { int x = 1; library_func(x+1); } void user_function_gc() { library_func(()=>[1]); } void main() { }
Re: what are the rules for @nogc and @safe attributes inference?
On Friday, 16 November 2018 at 10:25:26 UTC, ikod wrote: On Thursday, 15 November 2018 at 21:55:18 UTC, Steven Schveighoffer wrote: On 11/15/18 4:09 PM, Adam D. Ruppe wrote: On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template. Well, the general "rule" is, if it's code that must be available to the compiler when it's called, then it will be inferred. Examples of code that must be processed every time it's used: 1. Template functions 2. auto-returning functions 3. functions inside templates (like member functions of a templated struct) 4. Inner functions There may be others I didn't think of. Everything else must be manually attributed. The reasoning is that the function may be stubbed in a .di file, and in that case, attribute inference wouldn't be possible. -Steve Thanks for clarifications, Adam and Steven! My problem is next code: = import std.traits; T library_func(T)(/*lazy*/ T i) { // this fuction can be @nogc or not depending on T properties static if (isArray!T) { return i ~ i; } else { return i; } } void user_function_nogc() @nogc { int x = 1; library_func(x+1); } void user_function_gc() { library_func([1]); } void main() { } = This code compiles as long as `lazy` is commented out. But I'd like to have both lazy parameter and @nogc inferrence for `library_func` so that user is not locked to code @nogc or not. Aha, aha... Interesting! I had a similar problem with passing a delegate. And it was solved: https://forum.dlang.org/thread/erznqknpyxzxqivaw...@forum.dlang.org For your problem, there is a bug report: https://forum.dlang.org/post/wedwfooqdxbwxttpm...@forum.dlang.org https://issues.dlang.org/show_bug.cgi?id=12664 https://issues.dlang.org/show_bug.cgi?id=12647
Re: what are the rules for @nogc and @safe attributes inference?
On Thursday, 15 November 2018 at 21:55:18 UTC, Steven Schveighoffer wrote: On 11/15/18 4:09 PM, Adam D. Ruppe wrote: On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template. Well, the general "rule" is, if it's code that must be available to the compiler when it's called, then it will be inferred. Examples of code that must be processed every time it's used: 1. Template functions 2. auto-returning functions 3. functions inside templates (like member functions of a templated struct) 4. Inner functions There may be others I didn't think of. Everything else must be manually attributed. The reasoning is that the function may be stubbed in a .di file, and in that case, attribute inference wouldn't be possible. -Steve Thanks for clarifications, Adam and Steven! My problem is next code: = import std.traits; T library_func(T)(/*lazy*/ T i) { // this fuction can be @nogc or not depending on T properties static if (isArray!T) { return i ~ i; } else { return i; } } void user_function_nogc() @nogc { int x = 1; library_func(x+1); } void user_function_gc() { library_func([1]); } void main() { } = This code compiles as long as `lazy` is commented out. But I'd like to have both lazy parameter and @nogc inferrence for `library_func` so that user is not locked to code @nogc or not.
Re: what are the rules for @nogc and @safe attributes inference?
On 11/15/18 4:09 PM, Adam D. Ruppe wrote: On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template. Well, the general "rule" is, if it's code that must be available to the compiler when it's called, then it will be inferred. Examples of code that must be processed every time it's used: 1. Template functions 2. auto-returning functions 3. functions inside templates (like member functions of a templated struct) 4. Inner functions There may be others I didn't think of. Everything else must be manually attributed. The reasoning is that the function may be stubbed in a .di file, and in that case, attribute inference wouldn't be possible. -Steve
Re: what are the rules for @nogc and @safe attributes inference?
On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: what are the rules for @nogc inference? It attempts it if and only if it is a template.