digitalmars.D - safe quiz
- Michel Fortin (43/43) Dec 30 2009 I've encountered the two following situations when playing with @safe
- Walter Bright (3/6) Dec 30 2009 Nobody has gone through Phobos yet and labeled things appropriately.
- Michel Fortin (11/18) Dec 30 2009 I know. But that wasn't really the point of that whole post. The point
- Walter Bright (4/11) Dec 30 2009 I think that shows the type system is working.
- Michel Fortin (38/41) Dec 30 2009 A @safe function is only safe when given safe arguments. If a system
- Michel Fortin (28/47) Dec 30 2009 I should add that I can write this to move the error somewhere else
- Walter Bright (12/58) Dec 30 2009 I think we can work to address those problems while keeping it strict.
I've encountered the two following situations when playing with safe and delegate literals, and I had to label more code as trusted than I expected. Here is some code: safe void test(void function(int) doX, int i) { doX(i); } void main() { test((int i) { writeln(i); }, 1); } Note that doSomething and main are not safe. Should that compile? Currently it doesn't with an error on the "doX(i);" line saying doX isn't safe. (The compiler won't let you label the argument safe either.) I think it should compile because it's main that should be held responsible for the code it gives to test, and since main isn't a safe function it should be allowed to pass something unsafe, even to a safe function. Now let's do the same using a template: safe void test(alias doX)(int i) { doX(i); } void main() { test!((int i) { writeln(i); })(1); } Same here, except that instead of a function pointer we have a template. Should that compile? Basically, it's the same situation as above, and it doesn't compile either. Which makes me think that obviously the same thing will happen with string mixins: safe void test(string doX)(int i) { mixin(doX~";"); } void main() { test!("writeln(i)")(1); } Here, if writeln wasn't safe (and it currently isn't, that should be fixed in Phobos) there is no way this can compile. This is going to be pretty annoying if std.algorithm ever become safe. I'm not sure what should happen in the template case. -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 30 2009
Michel Fortin wrote:Here, if writeln wasn't safe (and it currently isn't, that should be fixed in Phobos) there is no way this can compile. This is going to be pretty annoying if std.algorithm ever become safe.Nobody has gone through Phobos yet and labeled things appropriately. This, of course, needs to be done.
Dec 30 2009
On 2009-12-30 15:10:31 -0500, Walter Bright <newshound1 digitalmars.com> said:Michel Fortin wrote:I know. But that wasn't really the point of that whole post. The point is that it's difficult to pass callable arguments to a safe function or function template. Labeling most function templates as safe in std.algorithm is going to break code that uses those algorithms. You'll see when you (or someone else) attempts it, just like I saw when I added safe to my code. -- Michel Fortin michel.fortin michelf.com http://michelf.com/Here, if writeln wasn't safe (and it currently isn't, that should be fixed in Phobos) there is no way this can compile. This is going to be pretty annoying if std.algorithm ever become safe.Nobody has gone through Phobos yet and labeled things appropriately. This, of course, needs to be done.
Dec 30 2009
Michel Fortin wrote:I know. But that wasn't really the point of that whole post. The point is that it's difficult to pass callable arguments to a safe function or function template. Labeling most function templates as safe in std.algorithm is going to break code that uses those algorithms. You'll see when you (or someone else) attempts it, just like I saw when I added safe to my code.I think that shows the type system is working. If a safe function can call a not safe delegate, then the type system has failed.
Dec 30 2009
On 2009-12-30 20:20:30 -0500, Walter Bright <newshound1 digitalmars.com> said:I think that shows the type system is working.I think it shows that the type system is too strict and easily gets in the way.If a safe function can call a not safe delegate, then the type system has failed.A safe function is only safe when given safe arguments. If a system function calls a safe function by giving it a garbage pointer, that safe function is able to corrupt anything. The same should apply for callable arguments (function pointers and delegates): a system function should be able to give a system delegate to a safe function, and that safe function should be able to call it. It's the caller that should be held responsible for giving an unsafe argument, and if the caller function is safe it shouldn't be allowed to pass an unsafe function as an argument. Here is a pathetic example of something that does not work currently: struct R { safe int opApply(int delegate(ref int) z) { int i = 1; return z(i); // Error: safe function 'opApply' cannot call system delegate 'z' } } system void someSystemFunction() { R r; foreach (i; r) { writeln(i); } } Should I have to write the opApply twice so it can work with both system and safe functions? I sure hope not. Even then, this does not compile either: safe void someSafeFunction() { R r; foreach (i; r) { writeln(i); } // Error: function untitled.R.opApply (int delegate(ref int) z) is not callable using argument types (int delegate(ref int __applyArg0)) } -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 30 2009
On 2009-12-30 23:41:54 -0500, Michel Fortin <michel.fortin michelf.com> said:Here is a pathetic example of something that does not work currently: struct R { safe int opApply(int delegate(ref int) z) { int i = 1; return z(i); // Error: safe function 'opApply' cannot call system delegate 'z' } } system void someSystemFunction() { R r; foreach (i; r) { writeln(i); } } Should I have to write the opApply twice so it can work with both system and safe functions? I sure hope not. Even then, this does not compile either:I should add that I can write this to move the error somewhere else which is more illustrative of my point by tagging the argument as a safe delegate: struct R { safe int opApply(int delegate(ref int) safe z) { int i = 1; return z(i); } } system void someSystemFunction() { R r; foreach (i; r) { writeln(i); } // Error: function untitled.R.opApply (int delegate(ref int) z) is not callable using argument types (int delegate(ref int)) } This version of opApply gives no error if the caller is safe: safe void someSafeFunction() { R r; foreach (i; r) { writeln(i); } } (Except about writeln not being safe, but that's not a language issue.) -- Michel Fortin michel.fortin michelf.com http://michelf.com/
Dec 30 2009
Michel Fortin wrote:On 2009-12-30 20:20:30 -0500, Walter Bright <newshound1 digitalmars.com> said:I think we can work to address those problems while keeping it strict. C++ const is an example of a not strict system which offers (as a consequence) no useful guarantees at all.I think that shows the type system is working.I think it shows that the type system is too strict and easily gets in the way.That's correct.If a safe function can call a not safe delegate, then the type system has failed.A safe function is only safe when given safe arguments. If a system function calls a safe function by giving it a garbage pointer, that safe function is able to corrupt anything.The same should apply for callable arguments (function pointers and delegates): a system function should be able to give a system delegate to a safe function, and that safe function should be able to call it. It's the caller that should be held responsible for giving an unsafe argument, and if the caller function is safe it shouldn't be allowed to pass an unsafe function as an argument.I'll have to think about that one. I'm not sure I agree. But I'm glad you're bringing it up, it's important. I hadn't thought about this issue before.Here is a pathetic example of something that does not work currently: struct R { safe int opApply(int delegate(ref int) z) { int i = 1; return z(i); // Error: safe function 'opApply' cannot call system delegate 'z' } } system void someSystemFunction() { R r; foreach (i; r) { writeln(i); } } Should I have to write the opApply twice so it can work with both system and safe functions? I sure hope not. Even then, this does not compile either: safe void someSafeFunction() { R r; foreach (i; r) { writeln(i); } // Error: function untitled.R.opApply (int delegate(ref int) z) is not callable using argument types (int delegate(ref int __applyArg0)) }There is certainly a problem here in that when the compiler creates the delegate to send to opApply, it doesn't tag it appropriately (or at all). These kinds of issues are to be expected with a new feature like safe, a couple of iterations will be necessary to straighten them out.
Dec 30 2009