Bug 17567 – make shared methods callable on unshared objects (and covariant)
Status
RESOLVED
Resolution
WONTFIX
Severity
enhancement
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-06-28T13:40:00Z
Last change time
2017-06-28T19:57:41Z
Assigned to
nobody
Creator
code
Comments
Comment #0 by code — 2017-06-28T13:40:42Z
cat > bug.d << CODE
struct S
{
void func() shared {}
}
void bug()
{
S s;
s.func;
}
dmd -c bug
----
bug.d(9): Error: shared method bug.S.func is not callable using a non-shared object
----
cat > bug2.d << CODE
interface I
{
void func();
}
class C : I
{
void func() shared {}
}
CODE
dmd -c bug
----
bug.d(5): Error: class bug.C interface function 'void func()' is not implemented
----
Both of these use-cases should be supported. Shared on a methods guarantees thread-safety which is compatible with being used in an unshared manner. Therefor shared methods should be fully covariant to unshared methods.
This does not touch shared as type qualifier, `shared(T)` means the type is shared between threads, and hence is obviously not convertible to `T`.
Looks like this would be the first storage class where we'd support covariance and real overloading.
While overloading, e.g. `nothrow` and non-`nothrow` methods is not an error, the compiler always prefers `nothrow`, `pure`, `@safe`, or `@nogc` methods.
But overloading should prefer unshared methods over `shared` ones, e.g. because the methods might avoid using a mutex.
Comment #1 by andrei — 2017-06-28T14:06:15Z
This is not possible. Thanks Timon Gehr for explaining this to me. Consider:
shared int* p;
struct S
{
int x;
void func() shared { p = &x; }
}
void bug()
{
auto p = new S;
p.func;
++p.x;
}
At this point we have threads getting shared access to x, but the current thread believes x is unshared.
Comment #2 by code — 2017-06-28T14:23:11Z
(In reply to Andrei Alexandrescu from comment #1)
> At this point we have threads getting shared access to x, but the current
> thread believes x is unshared.
It already seemed too simple to work out :).
So this would only work with some inout flavor of shared which likely wouldn't be worth the trouble.
Comment #3 by bugzilla — 2017-06-28T19:57:41Z
(In reply to Martin Nowak from comment #2)
> It already seemed too simple to work out :).
We worked out the rules for implicit conversions (used for covariance/contravariance) back when we came up with const/shared/etc. It's best to derive these in isolation, and then apply them without needing to work it out again.
(It's a lot like using the chain rule for derivatives. Derive the chain rule, prove it's correct, then just apply it as a given.)
I've gone through the same process with scope conversions. I kept confusing myself until I finally sat down and worked up a chart with the rules, convinced myself that that was correct, and then just applied them without worrying about it.