[Issue 23891] New: [DIP1000] delegate sometimes ignores lifetimes
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri May 5 15:47:05 UTC 2023
https://issues.dlang.org/show_bug.cgi?id=23891
Issue ID: 23891
Summary: [DIP1000] delegate sometimes ignores lifetimes
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: major
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: qs.il.paperinik at gmail.com
It seems that when a delegate is invoked, lifetime checks are not done, unless
the delegate is directly named. (Usually, that is the case when the delegate is
an rvalue, but if an expression returns a delegate by reference, which makes it
an lvalue, lifetime checks are not done.
This does not apply to function pointers, function pointers work as expected,
including those returned by a delegate.
Here are some test cases that demonstrate the claims:
```d
struct S
{
int value;
ref int member(int x) return @safe => value;
}
ref int func(return ref S s) @safe => s.member(0);
// THOSE FAIL (AND SHOULD)
ref int h1(ref S s) @safe => return func(s);
ref int h2(ref S s) @safe => return (&func)(s);
ref int h3(ref S s) @safe
{
static f() => &func;
return f()(s); // rvalue function pointer
alias Func = ref int function(return ref S s) @safe;
alias F = Func function() pure nothrow @nogc @safe;
static assert(is(typeof(&f) == F));
}
ref int h4(ref S s) @safe
{
auto fptr = &func;
ref dg() => fptr;
return dg()(s); // unnamed lvalue function pointer
alias Func = ref int function(return ref S s) @safe;
alias DG = ref Func delegate() pure nothrow @nogc @safe;
static assert(is(typeof(&dg) == DG));
}
// THOSE FAIL (AND SHOULD)
ref int f1(ref S s) @safe => s.member(0);
ref int f2(ref S s) @safe => (__traits(child, s, S.member))(0);
ref int f3(ref S s) @safe
{
auto dg = &s.member;
return dg(0);
}
ref int f4(ref S s) @safe
{
auto dg = &__traits(child, s, S.member);
return dg(0);
}
ref int f5(ref S s) @safe
{
static f(ref S s) => &s.member;
auto dg = f(s);
return dg(0); // Note: dg is an lvalue delegate (cf. g4)
}
// THOSE PASS AND SHOULD NOT
ref int g1(ref S s) @safe => (&s.member)(0);
ref int g2(ref S s) @safe => (&__traits(child, s, S.member))(0);
ref int g3(ref S s) @safe
{
auto dg = &s.member;
auto f = ref () => dg;
// f() is not an rvalue:
static assert(__traits(compiles, f() = null));
return f()(0);
}
ref int g4(ref S s) @safe
{
static f(ref S s) => &s.member;
return f(s)(0); // Note: f(s) is an rvalue delegate
// f(s) is of a delegate type that has "return" on it:
alias DG = ref int delegate(int x) return @safe;
static assert(is(typeof(f(s)) == DG));
// f is of type "function that returns DG":
alias F = DG function(ref S s) pure nothrow @nogc @safe;
static assert(is(typeof(&f) == F));
}
```
--
More information about the Digitalmars-d-bugs
mailing list