digitalmars.D.learn - what are the rules for nogc and safe attributes inference?
- ikod (12/12) Nov 15 2018 Hello,
- Adam D. Ruppe (2/3) Nov 15 2018 It attempts it if and only if it is a template.
- Steven Schveighoffer (13/17) Nov 15 2018 Well, the general "rule" is, if it's code that must be available to the
- ikod (34/53) Nov 16 2018 Thanks for clarifications, Adam and Steven!
- ikod (21/40) Nov 30 2018 Hello, Steve!
- Neia Neutuladh (17/30) Nov 30 2018 class Nefarious : S!(int, string)
- ikod (25/57) Nov 30 2018 Thanks for explanation, got it.
- Neia Neutuladh (5/13) Nov 30 2018 Interface functions must be abstract. Templated functions are implicitly...
Hello, what are the rules for nogc inference? It looks like sometimes compiler can infer nogc, but not in this simplest case: int x() { return 1; } void main() nogc { x(); } Thanks!
Nov 15 2018
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.
Nov 15 2018
On 11/15/18 4:09 PM, Adam D. Ruppe wrote:On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: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. -Stevewhat are the rules for nogc inference?It attempts it if and only if it is a template.
Nov 15 2018
On Thursday, 15 November 2018 at 21:55:18 UTC, Steven Schveighoffer wrote:On 11/15/18 4:09 PM, Adam D. Ruppe wrote: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.On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: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. -Stevewhat are the rules for nogc inference?It attempts it if and only if it is a template.
Nov 16 2018
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:Aha, aha... Interesting! I had a similar problem with passing a delegate. And it was solved: https://forum.dlang.org/thread/erznqknpyxzxqivawnix forum.dlang.org For your problem, there is a bug report: https://forum.dlang.org/post/wedwfooqdxbwxttpmzim forum.dlang.org https://issues.dlang.org/show_bug.cgi?id=12664 https://issues.dlang.org/show_bug.cgi?id=12647On 11/15/18 4:09 PM, Adam D. Ruppe wrote: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.On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: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. -Stevewhat are the rules for nogc inference?It attempts it if and only if it is a template.
Nov 16 2018
On Friday, 16 November 2018 at 12:12:12 UTC, Alex wrote: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() { }===================================================== 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/erznqknpyxzxqivawnix forum.dlang.org For your problem, there is a bug report: https://forum.dlang.org/post/wedwfooqdxbwxttpmzim forum.dlang.org https://issues.dlang.org/show_bug.cgi?id=12664 https://issues.dlang.org/show_bug.cgi?id=12647
Nov 16 2018
On Thursday, 15 November 2018 at 21:55:18 UTC, Steven Schveighoffer wrote:On 11/15/18 4:09 PM, Adam D. Ruppe wrote: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!On Thursday, 15 November 2018 at 21:00:48 UTC, ikod wrote: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. -Stevewhat are the rules for nogc inference?It attempts it if and only if it is a template.
Nov 30 2018
On Fri, 30 Nov 2018 20:41:03 +0000, 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.
Nov 30 2018
On Friday, 30 November 2018 at 21:03:06 UTC, Neia Neutuladh wrote:On Fri, 30 Nov 2018 20:41:03 +0000, ikod wrote: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!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.
Nov 30 2018
On Fri, 30 Nov 2018 22:10:11 +0000, 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.
Nov 30 2018