www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Recursive attribute for virtual functions?

reply 12345swordy <alexanderheistermann gmail.com> writes:
For example

class A
{
      recursive  safe void talk()
     {
         writeln("Hi");
     }

}
class B : A
{
     override void talk() //  safe attribute added by recursive 
attribute and can not be removed
     {
         writeln("Bye");
     }
}

I have notice that potential bugs can slip by the compiler during 
compile time, and I purpose this as way to counter them.

Alex
Mar 27 2018
parent reply ag0aep6g <anonymous example.com> writes:
On 03/27/2018 10:39 PM, 12345swordy wrote:
 class A
 {
       recursive  safe void talk()
[...]
 }
 class B : A
 {
      override void talk() //  safe attribute added by recursive 
 attribute and can not be removed
[...]
 }
It already works like that. B.talk is safe, and you can't make it system. You can mark it as system, that gets overridden by A.talk's safe. https://run.dlang.io/is/BlH8bp
Mar 27 2018
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 27 March 2018 at 20:49:25 UTC, ag0aep6g wrote:
 On 03/27/2018 10:39 PM, 12345swordy wrote:
 class A
 {
       recursive  safe void talk()
[...]
 }
 class B : A
 {
      override void talk() //  safe attribute added by 
 recursive attribute and can not be removed
[...]
 }
It already works like that. B.talk is safe, and you can't make it system. You can mark it as system, that gets overridden by A.talk's safe. https://run.dlang.io/is/BlH8bp
Then explain this then. https://run.dlang.io/is/S2KLs5
Mar 27 2018
next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 03/27/2018 11:02 PM, 12345swordy wrote:
 Then explain this then.
 https://run.dlang.io/is/S2KLs5
B.talk is safe. The compiler ignores the system attribute on B.talk, because A.talk's safe attribute takes precedence.
Mar 27 2018
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 27 March 2018 at 21:05:32 UTC, ag0aep6g wrote:
 On 03/27/2018 11:02 PM, 12345swordy wrote:
 Then explain this then.
 https://run.dlang.io/is/S2KLs5
B.talk is safe. The compiler ignores the system attribute on B.talk, because A.talk's safe attribute takes precedence.
Shouldn't it give a warning then?
Mar 27 2018
next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 03/27/2018 11:10 PM, 12345swordy wrote:
 Shouldn't it give a warning then?
I wouldn't mind a warning, or even an error. Putting both safe and system directly on a function is an error, too.
Mar 27 2018
parent reply arturg <var.spool.mail700 gmail.com> writes:
On Tuesday, 27 March 2018 at 21:25:33 UTC, ag0aep6g wrote:
 On 03/27/2018 11:10 PM, 12345swordy wrote:
 Shouldn't it give a warning then?
I wouldn't mind a warning, or even an error. Putting both safe and system directly on a function is an error, too.
shouldn't it create a overload? for example this fails: class A { void talk() safe {} } class B : A { alias talk = A.talk; void talk() system {} } but this works: class A { void talk() {} } class B : A { alias talk = A.talk; void talk(int) {} } this works also: class C { void talk() system {} void talk() safe {} }
Mar 27 2018
parent reply ag0aep6g <anonymous example.com> writes:
On 03/28/2018 12:19 AM, arturg wrote:
 shouldn't it create a overload?
I don't think so. As far as I know, you can't overload on attributes. [...]
 but this works:
 
 class A
 {
      void talk() {}
 }
 
 class B : A
 {
      alias talk = A.talk;
      void talk(int) {}
 }
Because different parameters make overloads.
 this works also:
 
 class C
 {
      void talk() system {}
      void talk() safe {}
 }
DMD might accept that, but I don't think it works in a meaningful way. How do you call the system one? Looks like the safe one will always be called, even from system code: ---- import std.stdio; void talk() system { writeln(" system"); } void talk() safe { writeln(" safe"); } void main() system { talk(); /* Prints " safe". */ } ----
Mar 27 2018
parent reply arturg <var.spool.mail700 gmail.com> writes:
On Tuesday, 27 March 2018 at 23:23:38 UTC, ag0aep6g wrote:
 DMD might accept that, but I don't think it works in a 
 meaningful way. How do you call the  system one?

 Looks like the  safe one will always be called, even from 
  system code:

 ----
 import std.stdio;

 void talk()  system { writeln(" system"); }
 void talk()  safe { writeln(" safe"); }

 void main()  system
 {
     talk(); /* Prints " safe". */
 }
 ----
you can call them with __traits(getOverloads, T, "name")[index]; you can overload on types attributes and linkage, but seems like you can only merge overloads based on types.
Mar 27 2018
next sibling parent arturg <var.spool.mail700 gmail.com> writes:
On Tuesday, 27 March 2018 at 23:34:20 UTC, arturg wrote:
 On Tuesday, 27 March 2018 at 23:23:38 UTC, ag0aep6g wrote:
 DMD might accept that, but I don't think it works in a 
 meaningful way. How do you call the  system one?

 Looks like the  safe one will always be called, even from 
  system code:

 ----
 import std.stdio;

 void talk()  system { writeln(" system"); }
 void talk()  safe { writeln(" safe"); }

 void main()  system
 {
     talk(); /* Prints " safe". */
 }
 ----
you can call them with __traits(getOverloads, T, "name")[index]; you can overload on types attributes and linkage, but seems like you can only merge overloads based on types.
i have some templates which can be used like this: type.dgAt!("name", index); dgAt!("name", index, somemodule); dgAt!("name", index, "somemodule"); alias fun = aAt!("name", index, someTypeOrModule); type.dgOf!("name", void function(int) safe); dgOf!("name", void function(int) safe, module); dgOf!("name", void function(int) safe, "module"); from!(type, "name").aAt!1; from!(type, "name").aOf!(void function(int)); from!(type, "name").dgAt!1; from!(type, "name").dgOf!(void function(int)); but this fails: type.dgOf!("name", extern(C) void function(int) safe); and this works: alias funtype = extern(C) void function(int) safe; type.dgOf!("name", funtype);
Mar 27 2018
prev sibling parent ag0aep6g <anonymous example.com> writes:
On 03/28/2018 01:34 AM, arturg wrote:
 you can call them with __traits(getOverloads, T, "name")[index];
 
 you can overload on types attributes and linkage, but seems like you can 
 only merge overloads based on types.
I don't think there's value in allowing overloads that can only be called via __traits. Looks like this is an old issue [1] that is currently being fixed. run.dlang.io's "beta" and "nightly" compilers don't accept such overloads [2]. But I can't reproduce that locally. The fix has apparently been reverted because it needs more work. [1] https://issues.dlang.org/show_bug.cgi?id=2789 [2] https://run.dlang.io/is/qlyMti
Mar 27 2018
prev sibling parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, March 27, 2018 21:10:25 12345swordy via Digitalmars-d wrote:
 On Tuesday, 27 March 2018 at 21:05:32 UTC, ag0aep6g wrote:
 On 03/27/2018 11:02 PM, 12345swordy wrote:
 Then explain this then.
 https://run.dlang.io/is/S2KLs5
B.talk is safe. The compiler ignores the system attribute on B.talk, because A.talk's safe attribute takes precedence.
Shouldn't it give a warning then?
Warnings are almost always a terrible idea, since it's bad practice to leave warnings in place, meaning that it's effectively the same as an error except that it doesn't force folks to fix the problem immediately, and thanks to -w, it effectively forks the language, because stuff like is expressions and which template constraints pass or not can change based on whether -w is used or not. IMHO, it was a huge mistake to ever add warnings to the compiler. So, if we were going to do something with this, it should be an error, not a warning. In most cases, D ignores attributes that don't apply, which is sometimes annoying, but it can be very handy in generic code. It can also be helpful when an attribute is applied with : or {}. So, it's not particularly surprising that the compiler would ignore the attribute in this case. That being said, at the moment, I can't think of any reason why it would be beneficial to allow marking a derived function with system directly when the base class function is safe. Marking it with trusted is often valuable, because in that case, the derived function is doing something that's system, but the programmer has validated that it's safe, so it doesn't violate the API of the base class. So, you wouldn't want to treat it like you would a function that was directly marked with safe trusted, but that doesn't mean that system couldn't be disallowed. - Jonathan M Davis
Mar 27 2018
prev sibling parent bauss <jj_1337 live.dk> writes:
On Tuesday, 27 March 2018 at 21:02:11 UTC, 12345swordy wrote:
 On Tuesday, 27 March 2018 at 20:49:25 UTC, ag0aep6g wrote:
 On 03/27/2018 10:39 PM, 12345swordy wrote:
 class A
 {
       recursive  safe void talk()
[...]
 }
 class B : A
 {
      override void talk() //  safe attribute added by 
 recursive attribute and can not be removed
[...]
 }
It already works like that. B.talk is safe, and you can't make it system. You can mark it as system, that gets overridden by A.talk's safe. https://run.dlang.io/is/BlH8bp
Then explain this then. https://run.dlang.io/is/S2KLs5
Your actual test should have been like this: https://run.dlang.io/is/nF9dQk And as you can see it gives an error. You wouldn't be able to do anything that's not safe, so it wouldn't really matter. As soon as you attempted to do something else the compiler would yield an error.
Mar 28 2018