116 Name Resolution
Name resolution determines which declarations a source name denotes. It is separate from function overload resolution: lookup may produce several function declarations, after which the argument types select the best viable overload. This separation supports both ad-hoc polymorphism through overloading and parametric polymorphism through generic declarations.
Qualified names
If the first segment of a qualified name is a component alias, the remaining segments are looked up from the root namespace of that component. Otherwise the qualified name is looked up relative to the current component namespace chain as described in the Namespaces chapter. Qualification names one lookup location; it does not search other components and does not perform argument-dependent lookup.
Every intermediate segment must denote a namespace. The final segment is resolved in the name category required by its context, such as a type, constant, function, fold, or namespace. A declaration of another category does not hide declarations in the required category.
Ordinary unqualified lookup
For a component-local name, lookup examines the current namespace and then successive parent namespaces. The first namespace containing one or more declarations of the required name and category ends this search. For functions, all declarations with that name in the namespace form an overload set; one overload does not hide another overload in the same namespace. Finding a local set prevents functions of that name in ancestor namespaces from being added.
If the component namespace chain supplies no declaration, lookup considers selected imports in the current source file and then the standard prelude. Several selected imports of functions with the same local name contribute to one overload set. Several imported non-function declarations of the same category are ambiguous. A local declaration wins over an imported declaration, as specified by the Using Declarations chapter.
A component alias participates only as the first segment of a qualified name. Merely making a component available under an include root never adds its declarations to ordinary unqualified lookup.
Function lookup and ADL
An unqualified function call or symbolic operator expression performs ordinary unqualified lookup and argument-dependent lookup (ADL). ADL allows an operation to be declared with the types on which it operates without requiring every caller to import the operation explicitly. A qualified call does not perform ADL.
The associated namespaces of an argument type are determined from its static type, never from the run-time value. They include:
- the namespace containing each nominal type occurring in the type expression;
- the namespaces containing its nominal supertypes;
- the corresponding namespaces obtained recursively from generic type arguments and from the members of union and intersection types.
For a nominal type declared at component root, its associated namespace is that component's root namespace. Including supertypes means that an operation declared alongside a base type remains an ADL candidate when called with a subtype, including when the subtype and base type are declared in different components.
ADL contributes accessible functions with the called name from each associated namespace. It does not search parent or child namespaces from an associated namespace. The ordinary and ADL sets are then united. The same declaration reached by more than one route appears only once; declaration identity, rather than spelling or signature, is used for deduplication. Lookup is not ambiguous merely because the resulting set contains several functions. The Function Overload Resolution chapter determines whether one is the unique best match.
namespace Numbers
{
value Complex { Real re; Real im; }
func Complex +(Complex a, Complex b) =
Complex { re = a.re + b.re; im = a.im + b.im };
}
func Numbers.Complex add(Numbers.Complex a, Numbers.Complex b) =
a + b; // Numbers is associated with both operands, so ADL finds Numbers.+
Lookup errors
Lookup fails when it finds no declaration of the required category. Non-function lookup is ambiguous when its rules produce more than one declaration. Function lookup may intentionally produce many declarations; it is an error only if overload resolution finds no viable function or does not find a unique best viable function.