Thread overview
Mixin namespace ambiguity?
Sep 15, 2013
Marek Janukowicz
Sep 16, 2013
Kenji Hara
Sep 16, 2013
Marek Janukowicz
September 15, 2013
The code to reproduce the problem consists of 3 modules:

mix.d:

module mix;

mixin template A( alias x) {

  string a () {
    return x;
  }
}

====================
aux.d:

module aux;

import mix;

mixin A!("a in aux") X;
string b () { return "b in aux"; }

====================
main.d:

module main;

import aux;
import mix;
import std.stdio;

mixin A!("a in main") X;
string b () { return "b in main"; }

void main () {
  writefln( "a: %s", X.a );  // Line 1
  //writefln( "a: %s", a );  // Line 2
  writefln( "b: %s", b ); // Line 3
}

I run it with: dmd -run main.d aux.d mix.d

Line 1 works. Line 3 works. Line 2 fails with:
main.d(13): Error: main.A!("a in main").a at mix.d(5) conflicts with aux.A!
("a in aux").a at mix.d(5)

If I omit mixin identifier ("X"), there is no way I can make the call to "a" work without prepending module name.

My question is: why calling a function with the same name (from different
modules) works when:
- it is just a regular function
- it is a mixed-in function with mixin identifier (even though the
identifier is ambiguous)

and it doesn't when it's a mixed-in function with no mixin identifier.

My first impression is that either both line 1 and 2 should work or neither of them should work. It's no surprise to me that line 3 works (and it matches the documentation), so I basically included that just for reference.

-- 
Marek Janukowicz
September 16, 2013
On Sunday, 15 September 2013 at 18:31:30 UTC, Marek Janukowicz wrote:
> The code to reproduce the problem consists of 3 modules:
>
> mix.d:
>
> module mix;
>
> mixin template A( alias x) {
>
>   string a () {
>     return x;
>   }
> }
>
> ====================
> aux.d:
>
> module aux;
>
> import mix;
>
> mixin A!("a in aux") X;
> string b () { return "b in aux"; }
>
> ====================
> main.d:
>
> module main;
>
> import aux;
> import mix;
> import std.stdio;
> 
> mixin A!("a in main") X;
> string b () { return "b in main"; }
>
> void main () {
>   writefln( "a: %s", X.a );  // Line 1
>   //writefln( "a: %s", a );  // Line 2
>   writefln( "b: %s", b ); // Line 3
> }
>
> I run it with: dmd -run main.d aux.d mix.d
>
> Line 1 works. Line 3 works. Line 2 fails with:
> main.d(13): Error: main.A!("a in main").a at mix.d(5) conflicts with aux.A!
> ("a in aux").a at mix.d(5)
>
> If I omit mixin identifier ("X"), there is no way I can make the call to "a"
> work without prepending module name.
>
> My question is: why calling a function with the same name (from different
> modules) works when:
> - it is just a regular function
> - it is a mixed-in function with mixin identifier (even though the
> identifier is ambiguous)
>
> and it doesn't when it's a mixed-in function with no mixin identifier.
>
> My first impression is that either both line 1 and 2 should work or neither
> of them should work. It's no surprise to me that line 3 works (and it
> matches the documentation), so I basically included that just for reference.

Currently this is not a bug.

Looking from the module 'main', the mixin identifier 'X' declared in main.d is *closer* than the 'X' declared in aux.d, because the latter exists beyond the module import boundary.
Therefore, the use of 'X' in main.d would prefere the `mixin A!("a in main") X`.

On the other hand, when the name search, all mixed-in symbols are treated as if they are just imported at the mixed-in scope.
Therefore, even from main.d, the two mixed-in functions 'a' have same closeness, and the call is ambiguous because they have exactly same signature.

Kenji Hara
September 16, 2013
Kenji Hara wrote:
> Currently this is not a bug.
> 
> Looking from the module 'main', the mixin identifier 'X' declared
> in main.d is *closer* than the 'X' declared in aux.d, because the
> latter exists beyond the module import boundary.
> Therefore, the use of 'X' in main.d would prefere the `mixin
> A!("a in main") X`.

I get this one - if X was eg. a class and I was calling it's static member it would work the same way.

> On the other hand, when the name search, all mixed-in symbols are treated as if they are just imported at the mixed-in scope.

Could you please elaborate a bit more or point me to some documentation where this is described? If the mixins are imported at mixed-in scope, my understanding would be the one in 'main' is closer than the one in 'aux'.

> Therefore, even from main.d, the two mixed-in functions 'a' have same closeness, and the call is ambiguous because they have exactly same signature.


-- 
Marek Janukowicz