Bug 17084 – Can't sort array of structs with alias this: swap can't call non-@nogc function doesPointTo
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-01-11T07:00:03Z
Last change time
2020-03-21T03:56:35Z
Keywords
pull
Assigned to
No Owner
Creator
Neia Neutuladh
Comments
Comment #0 by dhasenan — 2017-01-11T07:00:03Z
I have no clue what's going on.
Dustmite-minimized with some hand massaging:
---
import std.algorithm;
struct URL
{
int[] queryParams;
string toString() const { return ""; }
alias toString this;
}
struct Page
{
URL url;
int opCmp(Page) { return 0; }
}
void main()
{
Page[] s;
std.algorithm.sort(s);
}
---
Removing 'alias this' fixes it. Making 'queryParams' not be an array fixes it. (But putting the array in another struct does not.) Inlining the struct fixes the error (incorporating the fields and methods from URL into Page).
Error:
---
/usr/include/dmd/phobos/std/algorithm/mutation.d(2183): Error: @nogc function 'std.algorithm.mutation.swap!(Page).swap' cannot call non-@nogc function 'std.exception.doesPointTo!(Page, Page, void).doesPointTo'
/usr/include/dmd/phobos/std/algorithm/mutation.d(2184): Error: @nogc function 'std.algorithm.mutation.swap!(Page).swap' cannot call non-@nogc function 'std.exception.doesPointTo!(Page, Page, void).doesPointTo'
/usr/include/dmd/phobos/std/algorithm/mutation.d(2185): Error: @nogc function 'std.algorithm.mutation.swap!(Page).swap' cannot call non-@nogc function 'std.exception.doesPointTo!(Page, Page, void).doesPointTo'
/usr/include/dmd/phobos/std/algorithm/mutation.d(2186): Error: @nogc function 'std.algorithm.mutation.swap!(Page).swap' cannot call non-@nogc function 'std.exception.doesPointTo!(Page, Page, void).doesPointTo'
/usr/include/dmd/phobos/std/algorithm/mutation.d(2009): Error: template instance std.algorithm.mutation.swap!(Page) error instantiating
/usr/include/dmd/phobos/std/algorithm/sorting.d(1322): instantiated from here: swapAt!(Page[])
/usr/include/dmd/phobos/std/algorithm/sorting.d(1293): instantiated from here: siftDown!()
/usr/include/dmd/phobos/std/algorithm/sorting.d(1278): instantiated from here: buildHeap!()
/usr/include/dmd/phobos/std/algorithm/sorting.d(1217): instantiated from here: heapSort!()
/usr/include/dmd/phobos/std/algorithm/sorting.d(1047): instantiated from here: quickSortImpl!(binaryFun, Page[])
server.d(19): instantiated from here: sort!("a < b", cast(SwapStrategy)0, Page[])
/usr/include/dmd/phobos/std/algorithm/sorting.d(1283): Error: template instance std.algorithm.sorting.HeapOps!(binaryFun, Page[]).percolate!() error instantiating
/usr/include/dmd/phobos/std/algorithm/sorting.d(1217): instantiated from here: heapSort!()
/usr/include/dmd/phobos/std/algorithm/sorting.d(1047): instantiated from here: quickSortImpl!(binaryFun, Page[])
server.d(19): instantiated from here: sort!("a < b", cast(SwapStrategy)0, Page[])
/usr/include/dmd/phobos/std/algorithm/sorting.d(1222): Error: template instance std.algorithm.sorting.getPivot!(binaryFun, Page[]) error instantiating
/usr/include/dmd/phobos/std/algorithm/sorting.d(1047): instantiated from here: quickSortImpl!(binaryFun, Page[])
server.d(19): instantiated from here: sort!("a < b", cast(SwapStrategy)0, Page[])
Failed: ["dmd", "-v", "-o-", "server.d", "-I."]
---
Comment #1 by b2.temp — 2018-04-22T10:14:00Z
making `URL.toString()` `@nogc` or making `URL.toString` a parameter-less function template also fixes it.
Curiously, if you put this in std.exception:
```d
@safe @nogc unittest
{
import std.algorithm;
static struct URL
{
int[] queryParams;
string toString() const { return ""; }
alias toString this;
}
static struct Page
{
URL url;
int opCmp(Page) { return 0; }
}
Page[] s;
std.algorithm.sort(s);
}
```
and call
```shell
dmd exception.d -unittest -main -oftest && ./test
```
Then it works directly, i.e no need to do anything.
Finally a last way to make it working is to explicitly annotate `doesPointTo()` as `@nogc`. Looking at `doesPointTo` implementation you can verify that it's indeed `@nogc` (just a small change to make for static arrays) so this solution can be a candidate for a PR (i'll try to propose), until better is found.
This issue could rather be a compiler one, e.g a bit like the one where inference of attribute fails when there are mutual calls.