Optionally beefed-up shadowing-prevention

Nick Sabalausky a at a.a
Wed Oct 6 18:54:09 PDT 2010


"Nick Sabalausky" <a at a.a> wrote in message 
news:i8j8m6$2utp$1 at digitalmars.com...
> bearophile just put up an interesting enhancement request, and I wanted to 
> discuss it, but figured this would be a better place to discuss:
>
> bearophile's original message reproduced here:
> =========================
> @outer() attribute:  http://d.puremagic.com/issues/show_bug.cgi?id=5007
> ----------------------------
> Generally it's not a good practice to use global values (or values from 
> outer scopes, D has nested functions too, so names may come from the outer 
> function too), but passed arguments increase the amount of used stack and 
> they may slow down the code a little where high-performance is very 
> important.
>
> So in some situations the programmer may need to use global/outer names. 
> But allowing functions to freely access global scope as in C language may 
> lead to bugs, because there is no control over the flow of information 
> between the subsystems of the program, and also because accidental masking 
> of an outer name
> is allowed:
>
> int x = 100;
> int foo(int y) {
>    int x = 5;
>    return x + y; // silently uses local x
> }
> void main() {
>    assert(foo(10) == 15);
> }
>
> For this (and for other purposes) D has introduced the 'pure' attribute 
> for functions that disallows the access to mutable outer state. But 'pure' 
> is a blunt tool, and in some situations it can't be used. To avoid bugs in 
> such
> situations, caused by unwanted usage of outer state, an attribute may be 
> defined, it may be named "@outer".
>
> The purpose of the (optional) @outer attribute is similar to the 'global' 
> attribute in the SPARK language:
>
> # global in out CallCount;
>
> A D function that is annotated with @outer must specify all global 
> variables it uses, and if each of them is just read (in), written to 
> (out), or both (inout).
>
> An example of its possible syntax:
>
> int x = 100;
> int y = 200;
>
> @outer(in x, inout y)
> int foo(int z) {
>    y = x + z;
>    return y;
> }
>
> Here the compiler enforces that foo() uses only the x and y outer defined
> variables, that x is just read and y is both read and written inside 
> foo().
> This tidies up the flow of information.
>
> The @outer attribute is optional, and you may avoid its usage in small
> script-like D programs. But in situations where the D code must be very
> reliable, a simple automatic code review tool may require the usage of 
> @outer
> by all functions/methods.
>
> The @outer(...) need to be shown both in the documentation produced by -D 
> and
> -X (Json too) dmd compilation switches.
> =========================
>

My thoughts:

I like the general idea, but why the need to specify the globals you're 
going to use? Why not something like this:

--------------------
module foo;
int globalVar;
class Foo()
{
    int instanceVar;
    static int classVar;

    @noshadow // Name subject to change
    void bar()
    {
        // These are also errors as function parameters
        int globalVar;   // Error
        int instanceVar; // Error
        int classVar;    // Error

        globalVar   = 1; // Error
        instanceVar = 1; // Error
        classVar    = 1; // Error

        .globalVar       = 1; // Ok
        this.instanceVar = 1; // Ok
        Foo.classVar     = 1; // Ok
    }
}
--------------------

And, of course, let it also be used like like this:

--------------------
module foo;
@noshadow: // Applies to all code below
int globalVar;
class Foo()
{
    int instanceVar;
    static int classVar;

    void bar()
    {
        // Etc...same as before
    }
}
--------------------

And if tracking read/write access to globals or whatever is needed it could 
be done via ddoc or the json output or some other analysis tool.




More information about the Digitalmars-d mailing list