www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Mixin namespace ambiguity?

reply Marek Janukowicz <marek janukowicz.net> writes:
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
Sep 15 2013
parent reply "Kenji Hara" <k.hara.pg gmail.com> writes:
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
Sep 15 2013
parent Marek Janukowicz <marek janukowicz.net> writes:
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
Sep 16 2013