1: include "std"; 2: 3: module A { 4: struct X { 5: x: int; 6: } 7: } 8: val e = A::X(5); 9: print e.x; endl;
e.xis transformed by desugaring to the function application
get_x eIf that is so, how is it that the get_x of (A::X) is found, when it is not visible in the top level scope? The answer is that I told a white lie before.
What really happens is that e.x is transformed into a method application. This is exactly the same as a function application, except that overloading uses a special kind of lookup for the method name, called Koenig Lookup, after its inventor, Andrew Koenig.
Koenig lookup works by searching the module in which the type of the expression e is defined: in Felix the type must be generative, which means it must be a declared type such as a named struct or union and not an implicitly defined type like a tuple, pointer, or function type (typedefs do not count here, as in C they just specify an alias, they don't define a type).
In the example, 'get_x' is defined in the module X, because A is defined in the module X, and since e has type 'A', Felix looks in module X for 'get_x'.
Koenig lookup only works for method calls, that is, when you use the syntax e.x.