[Issue 23955] New: Can't access non-eponymous members in IFTI template
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Jun 2 15:41:34 UTC 2023
https://issues.dlang.org/show_bug.cgi?id=23955
Issue ID: 23955
Summary: Can't access non-eponymous members in IFTI template
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Keywords: rejects-valid
Severity: normal
Priority: P3
Component: dmd
Assignee: nobody at puremagic.com
Reporter: dlang-bugzilla at thecybershadow.net
////// test.d //////
template foo()
{
alias T = int;
void foo(T v)
{
}
}
void main()
{
foo!()(1); // OK
foo (1); // NG
}
////////////////////
Compiler says:
test.d(5): Error: undefined identifier `T`
test.d(13): Error: template `test.foo` is not callable using argument types
`!()(int)`
test.d(1): Candidate is: `foo()(T v)`
I think this is an effect of how IFTI resolution is done
(https://dlang.org/spec/template.html#ifti). However,
- This limitation is not explicitly documented.
- The error message is misleading.
- This particular case should work. The argument does not have any provenance
from the template parameters (of which there are none).
In practice, this limitation makes "This Parameters"
(https://dlang.org/spec/template.html#template_this_parameter) a lot less
useful, as it's not possible to use the constness of "this" or something like
typeof(This.field) in the function signature.
Consider for example:
struct S
{
int[] arr;
void getArr(scope void delegate(int[]) fn) { fn(arr); }
}
Now, we want to make getArr callable with a const S. Attempt #1, add a const
overload:
void getArr(scope void delegate(int[]) fn) { fn(arr); }
void getArr(scope void delegate(const(int)[]) fn) const { fn(arr); }
Oops, now calling getArr on a mutable object with a lambda causes "matches
both" errors.
OK, no overloads. Attempt #2, let's try inout:
void getArr(scope void delegate(inout(int)[]) fn) inout { fn(arr); }
Oops, that doesn't actually work, inout is not smart enough to propagate to
delegates. The inout on the delegate parameter always resolves to const.
OK, no inout. Attempt #3, let's try This parameters:
template getArr(this This) {
void getArr(scope void delegate(typeof(This.arr)) fn) { fn(arr); }
}
Oops, that doesn't work because of the bug described here. Attempt #4, just use
typeof(this.arr) instead:
template getArr(this This) {
void getArr(scope void delegate(typeof(this.arr)) fn) { fn(arr); }
}
Oops, "this" in the parameter list does not yet have the qualifiers applied to
it, so it's always mutable. SOL!
--
More information about the Digitalmars-d-bugs
mailing list