Bug 20867 – class subtyping doen't work in separate files

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-05-27T21:21:19Z
Last change time
2022-09-06T16:59:34Z
Assigned to
No Owner
Creator
mw

Attachments

IDFilenameSummaryContent-TypeSize
1791t.dclass subtyping doen't work in separate filestext/plain127
1792queue.dclass subtyping doen't work in separate filestext/plain2211

Comments

Comment #0 by mingwu — 2020-05-27T21:21:19Z
Created attachment 1791 class subtyping doen't work in separate files Put the code on page: https://tour.dlang.org/tour/en/multithreading/synchronization-sharing in to queue.d, then add subtyping and a test func f(): ... private T[] elements; public: alias elements this; // add this line ... // test f() class T{} void f() { auto q = new shared(SafeQueue!(shared T)); writeln(q.length); } If f() is in the same file queue.d, the code can compile; if it's in a separate file, compile will fail. $ cat queue.d -------------------------------------------------------------------------------- import std.stdio; import std.concurrency : receiveOnly, send, spawn, Tid, thisTid; import core.atomic : atomicOp, atomicLoad; /* Queue that can be used safely among different threads. All access to an instance is automatically locked thanks to synchronized keyword. */ synchronized class SafeQueue(T) { // Note: must be private in synchronized // classes otherwise D complains. private T[] elements; public: alias elements this; void push(T value) { elements ~= value; } /// Return T.init if queue empty T pop() { import std.array : empty; T value; if (elements.empty) return value; value = elements[0]; elements = elements[1 .. $]; return value; } } /* Safely print messages independent of number of concurrent threads. Note that variadic parameters are used for args! That is args might be 0 .. N parameters. */ void safePrint(T...)(T args) { // Just executed by one concurrently synchronized { import std.stdio : writeln; writeln(args); } } void threadProducer(shared(SafeQueue!int) queue, shared(int)* queueCounter) { import std.range : iota; // Push values 1 to 10 foreach (i; 1..11) { queue.push(i); safePrint("Pushed ", i); atomicOp!"+="(*queueCounter, 1); } } void threadConsumer(Tid owner, shared(SafeQueue!int) queue, shared(int)* queueCounter) { int popped = 0; while (popped != 10) { auto i = queue.pop(); if (i == int.init) continue; ++popped; // safely fetch current value of // queueCounter using atomicLoad safePrint("Popped ", i, " (Consumer pushed ", atomicLoad(*queueCounter), ")"); } // I'm done! owner.send(true); } void main() { auto queue = new shared(SafeQueue!int); shared int counter = 0; spawn(&threadProducer, queue, &counter); auto consumer = spawn(&threadConsumer, thisTid, queue, &counter); auto stopped = receiveOnly!bool; assert(stopped); } class T{} void f() { auto q = new shared(SafeQueue!(shared T)); writeln(q.length); } -------------------------------------------------------------------------------- $ dmd queue.d # succeed. $ cat t.d # put T and f() in separate file t.d: -------------------------------------------------------------------------------- import std.stdio; import queue; class T{} void f() { auto q = new shared(SafeQueue!(shared T)); writeln(q.length); } -------------------------------------------------------------------------------- $ dmd t.d t.d(9): Error: no property length for type shared(queue.SafeQueue!(shared(T)))
Comment #1 by mingwu — 2020-05-27T21:22:05Z
Created attachment 1792 class subtyping doen't work in separate files Two files: queue.d t.d
Comment #2 by nick — 2022-09-06T16:59:34Z
> private T[] elements; > public: alias elements this; You can't public alias a private symbol by design. You could make a property function as a workaround: public @property _get() => elements; alias _get this; See also Issue 9809.