Thread overview
template instance does not match template declaration
Feb 25, 2022
kdevel
Feb 25, 2022
kdevel
Feb 25, 2022
Paul Backus
Feb 25, 2022
kdevel
Feb 26, 2022
Paul Backus
February 25, 2022
$ dmd --version
DMD64 D Compiler v2.098.1
[...]
module main; // main.d
import std.traits;
import model;

void main ()
{
   enum Q = Parameters!read;
}
module model; // model.d
import std.file : read; // this line provokes the error

int read (string filename)
{
   import std.file;
   auto data = std.file.read (filename);
   return 0;
}
$ dmd -i main
main.d(7): Error: template instance `model.Parameters!(read)` does not match template declaration `Parameters(func...)`
  with `func = (read)`
  must satisfy the following constraint:
`       isCallable!func`

It seems the template parameter f becomes not aliased to model.read in the presence of the selective import. Bug or feature?

February 25, 2022
>
module main; // main.d
import std.traits;
import model;

void main ()
{
   enum Q = Parameters!read;
}

Will not compile with selective import commented out. Hence main.d must read (alias instead of enum):

module main; // main.d
import std.traits;
import model;

void main ()
{
   alias Q = Parameters!(read);
}
February 25, 2022

On Friday, 25 February 2022 at 23:05:00 UTC, kdevel wrote:

>

It seems the template parameter f becomes not aliased to model.read in the presence of the selective import. Bug or feature?

I'd call this a bug. Currently, selective imports are implemented using aliases under the hood, which means that the compiler sees your model module as having two overloads of read:

alias read = std.file.read; // from selective import

int read (string filename)
{
    // etc.
}

When you pass an overload set to a template that isn't written to handle multiple overloads, it will usually just choose whichever overload comes first in the source code. And since the public import statement comes earlier in your source file than the definition of read, the std.file.read alias is the one that gets chosen when you write Parameters!read.

February 25, 2022

On Friday, 25 February 2022 at 23:17:14 UTC, Paul Backus wrote:
[...]

>

Currently, selective imports are implemented using aliases under the hood, which means that the compiler sees your model module as having two overloads of read:

alias read = std.file.read; // from selective import

int read (string filename)
{
    // etc.
}

When you pass an overload set to a template that isn't written to handle multiple overloads, it will usually just choose whichever overload comes first in the source code. And since the public import statement comes earlier in your source file than the definition of read, the std.file.read alias is the one that gets chosen when you write Parameters!read.

What about this:

module model; // model.d
import std.file : read; // this line provokes the error

private int read (string filename) // now it's private
{
   import std.file;
   auto data = std.file.read (filename);
   return 0;
}

Now dmd reports:

main.d(7): Error: undefined identifier `read`

Is the lookup and the processing done in different parts/stages of the compiler?

February 26, 2022

On Friday, 25 February 2022 at 23:34:59 UTC, kdevel wrote:

>

What about this:

module model; // model.d
import std.file : read; // this line provokes the error

private int read (string filename) // now it's private
{
   import std.file;
   auto data = std.file.read (filename);
   return 0;
}

Now dmd reports:

main.d(7): Error: undefined identifier `read`

Is the lookup and the processing done in different parts/stages of the compiler?

I'm not familiar enough with the details of this part of the compiler to say. But it sure looks like there's something screwy going on here.