Bug 11326 – move functions are not properly constrained and work improperly with templated functions
Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2013-10-22T11:16:43Z
Last change time
2019-11-18T15:48:21Z
Assigned to
No Owner
Creator
Andrej Mitrovic
Comments
Comment #0 by andrej.mitrovich — 2013-10-22T11:16:43Z
-----
import std.range;
struct NotRange
{
int moveAt(T)(T index) { return 0; }
}
struct Range
{
@property int front() { return 0; }
void popFront() { }
@property bool empty() { return false; }
int moveFront()() { assert(0); } // never called because it's a template!
}
void main()
{
NotRange nr;
// Internal error:
// std\range.d(6870): Error: template std.array.front does not match any function template declaration. Candidates are:
// nr.moveFront();
Range r;
moveFront(r);
}
-----
Problems:
- Non-range types are accepted, leading to internal Phobos errors.
- moveFront/moveBack/moveTo check for the presence of a move function via the address operator -- e.g. "static if (is(typeof(&r.moveFront)))", which will fail for templated functions.
Comment #1 by andrej.mitrovich — 2013-10-22T11:42:39Z
Ok as it turns out checking for template member functions is actually very difficult. I don't think we have the proper traits to derive whether something is a templated member function that can be called a certain way belonging to an aggregate and **not** a UFCS function.
The problem is really this:
static if (is(typeof(r.moveFront)))
This will end up calling a UFCS function if there's no member function, that's why the current implementation uses an address-of operator. We need to get rid of these styles of tricks and implement proper introspection utilities, meaning we have helper templates in Phobos or __traits() which can tell us:
- Does symbol "abc" exist for an aggregate
-> We already have hasMember!()
- Is the symbol a function which can be called via "obj.abc()"
-> Not easy to figure out. Just testing "obj.abc()" may end up calling a UFCS function instead. And a simple "&obj.abc" doesn't work for templated functions either (current situation).