digitalmars.D.bugs - [Issue 9283] New: "out ref" function attribute proposal to solve ref-accepting ref-returning memory safety issue
- d-bugmail puremagic.com (110/110) Jan 08 2013 http://d.puremagic.com/issues/show_bug.cgi?id=9283
http://d.puremagic.com/issues/show_bug.cgi?id=9283 Summary: "out ref" function attribute proposal to solve ref-accepting ref-returning memory safety issue Product: D Version: D2 Platform: All OS/Version: All Status: NEW Severity: enhancement Priority: P2 Component: DMD AssignedTo: nobody puremagic.com ReportedBy: reachzach gmail.com PST --- This proposal plugs a hole in D's memory safety system. The problem is that the compiler can't easily tell whether the return value of a function which takes a local by reference should be treated as a local or global. It only occurs with reference returns which also take a reference parameter: ref int foh(ref int a) { return a; } ref int go() { int local; return foh(local); // Compiler needs help: treat as local or global? } This issue was only raised with the purpose of making safe code truly safe, but in general this error (if it is an error) should be caught, and there is no computationally cheap way to do it without marking the function signature. I propose that the compiler consider the above code an error by default. If the reference parameter taking local is marked "scope" (assuming I understand the "scope" attribute correctly), the compiler can ignore this issue and move on. Which leaves the case where you need both a returnable reference return and a non-scope reference parameter. For the compiler to run through the function call searching for whether it returns a local or a global is too expensive, and impossible when the PIMPL idiom is being used. Therefore, the choice is either to disallow it, to allow it unsafely, or to make an addition to the function attribute system. The best part about this proposal is that there is a nice-looking way to add the function attribute, using the keyword "out" (before parentheses) to mark a function which promises not to return any of its reference parameters: ref int lugs(ref int a) { return a; } ref int h(ref int a) { return lugs(a); // Okay int local; return lugs(local); // New error: the result of a function which accepts a local as a non-scope reference and returns a reference is treated as local and cannot be escaped unless that function is marked "out" int* p = &lugs(local); // Same error } int d; out ref int saml(ref int a) { return *(new int); // Fine return d; // Fine return a; // Error: a function marked "out" may not escape one of its reference parameters } ref int lugh(ref int a) { return a; } out ref int druh(ref int a) { return lugh(a); // Error: a function marked "out" may not escape the result of a function which accepts its reference parameter as a non-scope reference and returns a reference unless that function is also marked "out" } out int boops(ref int a) {} // Error: a function marked "out" must return a reference out ref int bop(int a) {} // Error: a non-member function marked "out" must accept at least one ref parameter If this system requires flexibility for hardcore systems programming, the expression "cast (out)" has a nice ring to it. // "cast(out)" transforms a local into a global: out ref int lit(ref int a) { return cast(out) a; // Obviously not safe } // It can be used anywhere: ref int hugs(ref int a) { return a; } ref int g(ref int a) { int local; return cast(out) (hugs(local)); // Okay return cast(out) local; // Okay?? return hugs(cast(out) local); // Won't know what hit 'em } Because struct and class member functions which return ref may return their fields, it applies to them even if they take no parameters: struct S { int _i; static int _s; out ref int club() { return _i; } // Error: a member function marked "out" may not escape a non-static field out ref int trob() { return _s; } // Okay out ref int blub() { return cast(out) _i; } //Okay } struct B { int _i; ref int plub() { return _i; } } ref int bub() { B b; return b.plub(); // Error: the result of a local instance's non-static method which returns a reference is considered local and may not be escaped unless that method is marked "out" int* i = &b.plub(); // Same error } The system does give more uses to the word "out", but does not however conflict with existing uses (assuming the attribute "out" may only come before parentheses in function signatures and not after). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 08 2013