January 14, 2023
https://issues.dlang.org/show_bug.cgi?id=23626

          Issue ID: 23626
           Summary: [REG2.096] Template deduction with auto const ref
                    Args... and delegate
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: regression
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: johanengelen@weka.io

Created attachment 1865
  --> https://issues.dlang.org/attachment.cgi?id=1865&action=edit
Files to reproduce the bug

It's unfortunate, i spent a lot of time reducing this to a manageable test case, but it is still 4 files.

Compiles with DMD 2.095.1, fails with 2.096.1, fails with different error with 2.100.0.

> /Users/johan/dcompilers/dmd-2.095.1/osx/bin/dmd  -o- -c static_hash.d space_reclaimer.d tiering_policies.d
Succes.

/Users/johan/dcompilers/dmd-2.096.1/osx/bin/dmd -o- -c static_hash.d
space_reclaimer.d tiering_policies.d
Errors:
space_reclaimer.d(35): Error: template `tracing.__trace_maybeDumpTupleToFile`
cannot deduce function from argument types `!()(void delegate() nothrow @nogc
@system)`, candidates are:
tracing.d(5):        `__trace_maybeDumpTupleToFile(Args...)(auto ref const Args
args)`
space_reclaimer.d(39): Error: template instance
`space_reclaimer.ReclamationBatch.func_2!(void delegate() nothrow @nogc
@system)` error instantiating


/Users/johan/dcompilers/dmd-2.100.0/osx/bin/dmd -o- -c static_hash.d
space_reclaimer.d tiering_policies.d
Errors:
space_reclaimer.d(35): Error: none of the overloads of template
`tracing.__trace_maybeDumpTupleToFile` are callable using argument types
`!()(void delegate() nothrow @nogc @system)`
tracing.d(5):        Candidate is: `__trace_maybeDumpTupleToFile(Args...)(auto
const ref Args args)`
space_reclaimer.d(39): Error: template instance
`space_reclaimer.ReclamationBatch.func_2!(void delegate() nothrow @nogc
@system)` error instantiating

Files:

static_hash.d
```
module static_hash;
struct StaticHashTable(V) {
    V v ;
}
```

space_reclaimer.d
```
import tracing;

auto as(Func)(Func) {}

@nogc void foo() { }

void assertOp(string OPERATION, LHS, RHS)(LHS lhs, RHS) {
  as({
    try {
      try as(lhs);
      catch(Throwable) foo();
    } catch(Throwable) assert(false);
  });
}


struct FixedArray(T, size_t capacity_) {
  int a = getStructInfoEx!FixedArray;

  T* some_function() {
    assertOp !""(1, 1);
    return null;
  }
  alias some_function this;
}


struct ReclamationBatch {

  FixedArray !(uint,1) dummy;

  @nogc nothrow void some_inout_func() inout { }

  void func_2(Dlg)(Dlg dlg) {
    __trace_maybeDumpTupleToFile(dlg);
  }

  void _reclaimBatch() {
    func_2({ some_inout_func; });
  }
}
```

tiering_policies.d
```
interface Timeline {
}


struct Policy {
  alias OldTagCallback = void delegate() @nogc nothrow;
  Timeline timeline;
  OldTagCallback oldTagCB;
}


import static_hash;

struct Tiering {

    StaticHashTable!(Policy) policies;

}
```

tracing.d
```
import std.traits : fullyQualifiedName;

void __trace_maybeDumpTupleToFile(Args...)(auto ref const Args args) nothrow
@nogc { }

int getStructInfoEx(T)() {
   enum Ctx = fullyQualifiedName!T;
   return 0;
}
```

--