Thread overview
[Issue 20246] isCallable fails for template opCall overload
Sep 27, 2019
Simen Kjaeraas
Sep 27, 2019
Paul Backus
Sep 28, 2019
Max Samukha
Sep 28, 2019
Max Samukha
Sep 28, 2019
Paul Backus
Aug 10, 2020
Simen Kjaeraas
Aug 10, 2020
Simen Kjaeraas
Dec 17, 2022
Iain Buclaw
September 27, 2019
https://issues.dlang.org/show_bug.cgi?id=20246

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |simen.kjaras@gmail.com

--- Comment #1 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
It's impossible to distinguish between the above case and this:

struct S { enum opCall(T) = true; }

Clearly, the latter is *not* callable.

To illustrate the situation perhaps more clearly:

struct S {
    template opCall(T) {
        static if (is(T == int)) {
            void opCall(T t) {}
        } else {
            enum opCall = 14;
        }
    }
}

The above is perfectly valid code, but should isCallable!S return true?

--
September 27, 2019
https://issues.dlang.org/show_bug.cgi?id=20246

--- Comment #2 from Paul Backus <snarwin+bugzilla@gmail.com> ---
Seems like this is an issue with the interface, then, not the implementation; the question "is S.init callable" is undecidable, so there's not much use trying to pretend we can answer it.

One possible solution would be a trait like `isCallableWith!(S.init, int)`,
that requires the user to specify the argument type(s). That way, we could just
check with __traits(compiles) whether the call is valid or not.

--
September 28, 2019
https://issues.dlang.org/show_bug.cgi?id=20246

Max Samukha <maxsamukha@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxsamukha@gmail.com

--- Comment #3 from Max Samukha <maxsamukha@gmail.com> ---
(In reply to Paul Backus from comment #2)

> One possible solution would be a trait like `isCallableWith!(S.init, int)`,
> that requires the user to specify the argument type(s). That way, we could
> just check with __traits(compiles) whether the call is valid or not.

That does not take into account rvalue-ness of the arguments:

void foo(ref int) {}
store
static if (isCallableWith!(typeof(1)))
    foo(1); // error

isCallableWith would have to accept the actual arguments, (type, rvalue-ness)
pairs, or both.

And if one implements isCallableWith for functions, he should also implement isInstantiatableWith for templates. And that is a case for general __traits(matchFunction/matchTemplate, symbol, args) that would return the overloads callable/instantiatable with args. isCallableWith/isInstantiatableWith could be built on that.

--
September 28, 2019
https://issues.dlang.org/show_bug.cgi?id=20246

--- Comment #4 from Max Samukha <maxsamukha@gmail.com> ---
(In reply to Max Samukha from comment #3)

> isCallableWith!(typeof(1))

Typo: isCallableWith!(foo, typeof(1))

--
September 28, 2019
https://issues.dlang.org/show_bug.cgi?id=20246

--- Comment #5 from Paul Backus <snarwin+bugzilla@gmail.com> ---
(In reply to Max Samukha from comment #3)
> That does not take into account rvalue-ness of the arguments:
> 
> void foo(ref int) {}
> store
> static if (isCallableWith!(typeof(1)))
>     foo(1); // error
> 
> isCallableWith would have to accept the actual arguments, (type,
> rvalue-ness) pairs, or both.

Then perhaps the best solution is to add a note to the documentation of isCallable highlighting its shortcomings, and encourage everyone to instead use __traits(compiles) directly with the actual function call they want to make.

--
August 10, 2020
https://issues.dlang.org/show_bug.cgi?id=20246

Simen Kjaeraas <simen.kjaras@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |zan77137@nifty.com

--- Comment #6 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
*** Issue 21137 has been marked as a duplicate of this issue. ***

--
August 10, 2020
https://issues.dlang.org/show_bug.cgi?id=20246

--- Comment #7 from Simen Kjaeraas <simen.kjaras@gmail.com> ---
It's impossible to solve this in the general case, and even the special cases can't be solved in library code, but a __traits could check if the only member of the template is a callable (potentially also if all possible members would be callables).

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=20246

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--