From 1ca9f47d105267d5b4366f8c5fb5ec4055f4acfd Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Sun, 28 Jul 2024 12:13:28 +0100 Subject: [PATCH] Fix Bugzilla 14138 - std.parallelism.task breaks @safety --- std/parallelism.d | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/std/parallelism.d b/std/parallelism.d index fadb4c1759d..658786db230 100644 --- a/std/parallelism.d +++ b/std/parallelism.d @@ -884,11 +884,26 @@ identical to the non-@safe case, but safety introduces some restrictions: */ @trusted auto task(F, Args...)(F fun, Args args) -if (is(typeof(fun(args))) && isSafeTask!F) +if (__traits(compiles, () @safe => fun(args)) && isSafeTask!F) { return new Task!(run, F, Args)(fun, args); } +@safe unittest +{ + static struct Oops { + int convert() { + *cast(int*)0xcafebabe = 0xdeadbeef; + return 0; + } + alias convert this; + } + static void foo(int) @safe {} + + static assert(!__traits(compiles, task(&foo, Oops.init))); + static assert(!__traits(compiles, scopedTask(&foo, Oops.init))); +} + /** These functions allow the creation of `Task` objects on the stack rather than the GC heap. The lifetime of a `Task` created by `scopedTask` @@ -928,7 +943,7 @@ if (is(typeof(delegateOrFp(args))) && !isSafeTask!F) /// Ditto @trusted auto scopedTask(F, Args...)(F fun, Args args) -if (is(typeof(fun(args))) && isSafeTask!F) +if (__traits(compiles, () @safe => fun(args)) && isSafeTask!F) { auto ret = Task!(run, F, Args)(fun, args); ret.isScoped = true;