Here is a simple piece of code that uses interfaces to "strengthen" any delegate arbitrarily (and incorrectly):
alias StrongDelegate = void delegate() @safe @nogc pure nothrow;
alias WeakDelegate = void delegate();
interface Interface {
@safe @nogc pure nothrow
StrongDelegate strengthen(WeakDelegate dlg);
}
class Class : Interface {
@safe @nogc pure nothrow
override StrongDelegate strengthen(StrongDelegate dlg) { return dlg; }
}
Now if you have a Class instance as an Interface, you can freely strengthen any delegate and break the type systsem. e.g:
auto func() {
import std.typecons: scoped;
Interface i = new Class();
i.strengthen({
import std.stdio: writeln;
int i = 0x31323334;
writeln("I'll do whatever I want, @safe-ly: ", *cast(char[4]*)&i);
})();
}
@safe pure nothrow unittest {
func(); // func does un-@safe things, as well as impure and throwing things!
}
Comment #1 by eyal — 2019-12-19T10:16:10Z
NOTE: By "strengthen" I mean adding arbitrary attributes like @nogc or pure to a delegate that does not truly have them.
This bug means D's attribute enforcement, including @safe, is fundamentally broken.
Comment #2 by moonlightsentinel — 2021-01-02T02:10:16Z