[Issue 17578] Propagate the common qualifier of fields to the containing type

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sat Jul 1 13:25:57 PDT 2017


https://issues.dlang.org/show_bug.cgi?id=17578

timon.gehr at gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |timon.gehr at gmx.ch

--- Comment #3 from timon.gehr at gmx.ch ---
Refined design from discussion with Walter and Andrei (whenever I say 'shared',
the same applies for the other qualifiers):

Rationale:
- Implicitly changing semantics based on (possibly private) field types breaks
encapsulation: adding an unshared private member can break client code. This is
bad.

- There is already the possibility to declare a struct or class as shared,
which currently just makes all of its members shared. For such types, it is
documented on the outside that all members are shared, so it is fair game to
change behaviour based on those external qualifiers.

Proposal:
- For a shared struct S, S and shared S should be the same type. This type
behaves the same as the current type shared(C). For a shared class C, C and
shared(C) should be different but interconvertible types (reflecting the
difference between shared(T)* and shared(T*)). Methods of a shared class C
(which are shared methods) can be called on receivers of type C in addition to
receivers of type shared(C). Methods of a shared class can override/implement
unshared methods of the parent class/interfaces. If both shared and unshared
overloads are present in the parent class/interfaces, it overrides/implements
/both/ of them.


abstract class ICounter{
    abstract int get();
    abstract void increment();
}

shared class SharedCounter: ICounter{
    int x; // shared
    int get(){ // shared, but implements unshared method
        return x;
    }
    void increment(){
        atomicIncrement(x);
    }
}

class UnsharedCounter: ICounter{
    int x;
    int get(){
        return x;
    }
    void increment(){
        x++;
    }
}

interface IWidget{
    ICounter getCounter();
}

shared class SharedWidget: IWidget{
    SharedCounter c; // note: shared(SharedCounter)==SharedCounter
    SharedCounter getCounter(){
        return c;
    }
}

class UnsharedWidget: IWidget{
    UnsharedCounter c;
    UnsharedCounter getCounter(){
        return c;
    }
}

- Justification of soundness: Because all members of a shared class C are
shared, conversion between C and shared(C) is sound (this is like conversion
between shared(T)* and shared(T*).) In particular, it is sound for shared
methods of C to override/implement unshared methods, because this just amounts
to a conversion C->shared(C) when the parent method is called.

--


More information about the Digitalmars-d-bugs mailing list