Bug 11012 – [TDPL] is(typeof(f) == function) fails with some functions

Status
REOPENED
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-09-11T12:34:19Z
Last change time
2024-12-13T18:11:22Z
Keywords
spec
Assigned to
No Owner
Creator
Andrei Alexandrescu
Moved to GitHub: dmd#17610 →

Comments

Comment #0 by andrei — 2013-09-11T12:34:19Z
Consider TDPL example om page 150: auto f = (int i) {}; assert(is(f == function)); That example has a typo, should be: auto f = (int i) {}; assert(is(typeof(f) == function)); That still doesn't work, which brings us to this bug. The type of the function is deduced as void function(int i) pure nothrow @safe and that fails the "is" test when compared against the bare "function" keyword. As "function" by itself does not represent a type, the test should pass for all functions, however qualified.
Comment #1 by maxim — 2013-09-11T13:22:37Z
f is not a function but a function pointer, so the issue is against current design and description of the issue is also misleading by the way. By the way, this is a good opportunity to raise the question about what 'is' expression should return. There are currently two kinds 'function' and 'delegate' for three cases - a function, function pointer and delegate. Currently 'function' maps to function, not to a pointer and 'delegate' maps to delegate which is inconsistent (there is also inconsistency with not mapping 'function' to function pointer as this keyword is related to function pointers in other use cases). If 'function' should map to both pointer and a function, then there should be some means to distingiush between them. Another option is to map 'function' to pointer and function should map to returned type .
Comment #2 by ismailsiege — 2017-06-23T00:11:06Z
void testf(){} void main() { static assert(!is(testf == function)); // OK static assert(is(typeof(testf) == function)); // OK static assert(is(typeof( (){} ) == delegate)); // fails } But "is" doesn't work with function literals themselves in the first place, it is intended to check whether type is equivalent to function pointer or not. Same goes for: static if (is(typeof((int, float){}) P == function)) pragma(msg, P); else static assert(0); // fails
Comment #3 by ismailsiege — 2017-06-23T00:16:45Z
static assert(is(typeof( (){} ) == function)); // fails as well This issue doesn't allow to get lambda parameter types tuple, and this blocks my development. I'll try to have a look at the dmd source.
Comment #4 by ismailsiege — 2017-06-23T10:20:17Z
Ok, I'll agree with Maxim, it's probably as it should be. template isFunctionPointerType(T: FT*, FT) { enum isFunctionPointerType = is(FT == function); } unittest { auto p = (){}; static assert(isFunctionPointerType!(typeof(p))); }
Comment #5 by petar.p.kirov — 2017-06-23T14:14:04Z
(In reply to Alexander from comment #3) > static assert(is(typeof( (){} ) == function)); // fails as well > > This issue doesn't allow to get lambda parameter types tuple, and this > blocks my development. I'll try to have a look at the dmd source. Is the blocking issue that in code similar to the following, there's an error on line 11: --- import std.traits; pragma (msg, ReturnType!( (){} )); // void pragma (msg, Parameters!( (){} )); // () pragma (msg, ReturnType!( (int x, double y) => "test" )); // string pragma (msg, Parameters!( (int x, double y) => "test" )); // (int, double) void lambdaTypeWithParameter(alias lambda, Param)(Param p) { pragma (msg, Parameters!(lambda)); // line 11 - doesn't compile alias RT = typeof(lambda(p)); pragma (msg, RT); // line 15 } void main() { lambdaTypeWithParameter!(x => "test2")(true); // line 15 -> string lambdaTypeWithParameter!(x => x)(2); // line 15 -> int lambdaTypeWithParameter!(x => 3.0 * x)(2); // line 15 -> double } --- ? If that's the case, the error is expected since the lambda in that context is polymorphic - an un-instantiated function template meaning that its parameters are not bound to a specific type.
Comment #6 by petar.p.kirov — 2017-06-23T14:15:21Z
Let's keep the bug open until the language authors take an authoritative decision to keep or fix this issue.
Comment #7 by dfj1esp02 — 2017-06-23T16:02:10Z
How it works now: --- void f(){} static assert(is(typeof(f)==function)); static assert(is(typeof(&f)==function)); --- line 3: Error: static assert (is(void function() == function)) is false Looks like function pointer is not recognized as `function` by `is` expression.
Comment #8 by dfj1esp02 — 2017-06-23T16:12:49Z
static assert(is(typeof(&f)==delegate)); fails too, and spec doesn't specify how `is` expression works, which is definitely a bug.
Comment #9 by ismailsiege — 2017-06-23T18:40:23Z
I'm not sure about it being a bug, though I was before. I think spec should be a little more explicit on the difference between function and function pointer types. For now, this templates solve all my problems: template isFunctionPointerType(T: FT*, FT) { enum isFunctionPointerType = is(FT == function); } template ReturnType(FuncType: FT*, FT) { static if (is(FT RT == return)) alias ReturnType = RT; else static assert(0, "FuncType must be function pointer type"); } template ParamTypes(FuncType: FT*, FT) { static if (is(FT Params == function)) alias ParamTypes = Params; else static assert(0, "FuncType must be function pointer type"); }
Comment #10 by robert.schadek — 2024-12-13T18:11:22Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17610 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB