-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
More return scope fixes #77
Conversation
|
The ASan 'regressions' are caused by a druntime 2.102 change - exception traces are now malloc'd, not allocated by the GC anymore. And freed in the |
But why do they leak though? You would expect the system to clean up after itself. |
|
I'm not up to speed wrt. whether finalizers are called during program shutdown. And whether the ASan leaks are reported after they have run if they are. |
|
I've run the ASan-enabled tests with LDC v1.32.0 with a custom druntime, featuring some printf outputs.
Maybe the 7+ non-finalized Throwables are still ref'd at program shutdown somewhere? Or their finalization is skipped when terminating the program? Edit: Or maybe these Throwables aren't even GC-allocated? Some are emplaced into their static init symbol in druntime IIRC ( |
Looks like this is it. 7 |
|
Little correction: => IMO safe to add |
|
I can confirm that this fixes the compile errors we previously hit at Symmetry. There are still some deprecations, e.g.: |
|
With more attributes inference, there's a single remaining deprecation when compiling the diff --git a/source/concurrency/operations/then.d b/source/concurrency/operations/then.d
index 9f564e9..93a4570 100644
--- a/source/concurrency/operations/then.d
+++ b/source/concurrency/operations/then.d
@@ -58,7 +58,7 @@ struct ThenSender(Sender, Fun) if (models!(Sender, isSender)) {
alias Value = ReturnType!fun;
Sender sender;
Fun fun;
- auto connect(Receiver)(return Receiver receiver) @safe return scope {
+ auto connect(Receiver)(return Receiver receiver) @safe {
alias R = ThenReceiver!(Receiver, Sender.Value, Fun);
// ensure NRVO
auto op = sender.connect(R(receiver, fun));
diff --git a/source/concurrency/stream/stream.d b/source/concurrency/stream/stream.d
index fb98f54..b8d3af2 100644
--- a/source/concurrency/stream/stream.d
+++ b/source/concurrency/stream/stream.d
@@ -74,7 +74,7 @@ auto fromStreamOp(StreamElementType, SenderValue, alias Op, Args...)(Args args)
alias Value = SenderValue;
Args args;
DG dg;
- auto connect(Receiver)(return Receiver receiver) @safe return scope {
+ auto connect(Receiver)(return Receiver receiver) @safe {
// ensure NRVO
auto op = Op!(Receiver)(args, dg, receiver);
return op;
diff --git a/source/concurrency/stream/tolist.d b/source/concurrency/stream/tolist.d
index efae5bf..0f8f78b 100644
--- a/source/concurrency/stream/tolist.d
+++ b/source/concurrency/stream/tolist.d
@@ -15,7 +15,7 @@ struct ToListSender(Stream) {
alias Properties = StreamProperties!Stream;
alias Value = Properties.ElementType[];
Stream stream;
- auto connect(Receiver)(return Receiver receiver) @safe return scope {
+ auto connect(Receiver)(return Receiver receiver) @safe {
// ensure NRVO
auto op = ToListOp!(Stream, Receiver)(stream, receiver);
return op;
diff --git a/source/concurrency/syncwait.d b/source/concurrency/syncwait.d
index 000816d..f62eb10 100644
--- a/source/concurrency/syncwait.d
+++ b/source/concurrency/syncwait.d
@@ -127,7 +127,7 @@ auto syncWait(Sender)(auto scope ref Sender sender) {
return result;
}
-private Result!(Sender.Value) syncWaitImpl(Sender)(auto scope ref Sender sender, StopSource stopSource) @safe {
+private Result!(Sender.Value) syncWaitImpl(Sender)(auto ref Sender sender, StopSource stopSource) @safe {
import mir.algebraic : Algebraic, Nullable;
static assert(models!(Sender, isSender));
import concurrency.signal; |
|
Oh, just needed another manual diff --git a/source/concurrency/operations/then.d b/source/concurrency/operations/then.d
index 9f564e9..93a4570 100644
--- a/source/concurrency/operations/then.d
+++ b/source/concurrency/operations/then.d
@@ -58,7 +58,7 @@ struct ThenSender(Sender, Fun) if (models!(Sender, isSender)) {
alias Value = ReturnType!fun;
Sender sender;
Fun fun;
- auto connect(Receiver)(return Receiver receiver) @safe return scope {
+ auto connect(Receiver)(return Receiver receiver) @safe {
alias R = ThenReceiver!(Receiver, Sender.Value, Fun);
// ensure NRVO
auto op = sender.connect(R(receiver, fun));
diff --git a/source/concurrency/stream/stream.d b/source/concurrency/stream/stream.d
index fb98f54..b8d3af2 100644
--- a/source/concurrency/stream/stream.d
+++ b/source/concurrency/stream/stream.d
@@ -74,7 +74,7 @@ auto fromStreamOp(StreamElementType, SenderValue, alias Op, Args...)(Args args)
alias Value = SenderValue;
Args args;
DG dg;
- auto connect(Receiver)(return Receiver receiver) @safe return scope {
+ auto connect(Receiver)(return Receiver receiver) @safe {
// ensure NRVO
auto op = Op!(Receiver)(args, dg, receiver);
return op;
diff --git a/source/concurrency/stream/tolist.d b/source/concurrency/stream/tolist.d
index efae5bf..0f8f78b 100644
--- a/source/concurrency/stream/tolist.d
+++ b/source/concurrency/stream/tolist.d
@@ -15,7 +15,7 @@ struct ToListSender(Stream) {
alias Properties = StreamProperties!Stream;
alias Value = Properties.ElementType[];
Stream stream;
- auto connect(Receiver)(return Receiver receiver) @safe return scope {
+ auto connect(Receiver)(return Receiver receiver) @safe {
// ensure NRVO
auto op = ToListOp!(Stream, Receiver)(stream, receiver);
return op;
diff --git a/source/concurrency/syncwait.d b/source/concurrency/syncwait.d
index 000816d..46fbe8e 100644
--- a/source/concurrency/syncwait.d
+++ b/source/concurrency/syncwait.d
@@ -115,7 +115,7 @@ auto syncWait(Sender, StopSource)(auto ref Sender sender, StopSource stopSource)
return syncWaitImpl(sender, (()@trusted=>cast()stopSource)());
}
-auto syncWait(Sender)(auto scope ref Sender sender) {
+auto syncWait(Sender)(auto ref Sender sender) {
import concurrency.signal : globalStopSource;
auto childStopSource = new shared StopSource();
StopToken parentStopToken = parentStopSource ? StopToken(parentStopSource) : StopToken(globalStopSource);
@@ -127,7 +127,7 @@ auto syncWait(Sender)(auto scope ref Sender sender) {
return result;
}
-private Result!(Sender.Value) syncWaitImpl(Sender)(auto scope ref Sender sender, StopSource stopSource) @safe {
+private Result!(Sender.Value) syncWaitImpl(Sender)(auto ref Sender sender, StopSource stopSource) @safe {
import mir.algebraic : Algebraic, Nullable;
static assert(models!(Sender, isSender));
import concurrency.signal; |
|
... but this patch segfaults DMD & LDC v2.101/2 when compiling the |
|
Thanks for looking into this @kinke
Where are these deprecations exactly?
Hmm, removing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
|
No merge yet? |
It turns out there is a slight difference between annotating a member function with
scope returnorreturn scope.The
scopein bothreturn scopeandscope returnmeans you aren't allowed to escape a pointer member. It is also required if you want to call a method on a variable that has ascopeannotation.The
returninscope returnmeans you are allowed to return a reference to a struct's member. Whereas thereturninreturn scopeallows you to return pointer members.Many of the connect functions were annotated with
scope return, but we don't care much about the Sender's lifetime - they are just a collection of values needed to connect the async operation - but rather about the lifetime of Operation returned.