diff options
author | Ryan McConnell <rammcconnell@gmail.com> | 2024-01-19 12:12:31 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-01-19 13:12:31 +0100 |
commit | af8b1d0cb9bfa2f3b91b95219f850d075fc745f1 (patch) | |
tree | aca7b18452824744d0f23254c8289a5f1b5ad130 /doc | |
parent | 01097fc1fc70d5c7ce38108d7773e5533fb3743b (diff) | |
download | Nim-af8b1d0cb9bfa2f3b91b95219f850d075fc745f1.tar.gz |
Fixing overload resolution documentation (#23171)
As requested. Let me know where adjustments are wanted.
Diffstat (limited to 'doc')
-rw-r--r-- | doc/manual.md | 86 |
1 files changed, 64 insertions, 22 deletions
diff --git a/doc/manual.md b/doc/manual.md index 9ffd9b2cd..1de7f32b4 100644 --- a/doc/manual.md +++ b/doc/manual.md @@ -2619,13 +2619,20 @@ An expression `b` can be assigned to an expression `a` iff `a` is an Overload resolution =================== -In a call `p(args)` the routine `p` that matches best is selected. If -multiple routines match equally well, the ambiguity is reported during -semantic analysis. +In a call `p(args)` where `p` may refer to more than one +candidate, it is said to be a symbol choice. Overload resolution will attempt to +find the best candidate, thus transforming the symbol choice into a resolved symbol. +The routine `p` that matches best is selected following a series of trials explained below. +In order: Catagory matching, Hierarchical Order Comparison, and finally, Complexity Analysis. -Every arg in args needs to match. There are multiple different categories how an -argument can match. Let `f` be the formal parameter's type and `a` the type -of the argument. +If multiple candidates match equally well after all trials have been tested, the ambiguity +is reported during semantic analysis. + +First Trial: Catagory matching +-------------------------------- + +Every arg in `args` needs to match and there are multiple different categories of matches. +Let `f` be the formal parameter's type and `a` the type of the argument. 1. Exact match: `a` and `f` are of the same type. 2. Literal match: `a` is an integer literal of value `v` @@ -2635,9 +2642,7 @@ of the argument. range. 3. Generic match: `f` is a generic type and `a` matches, for instance `a` is `int` and `f` is a generic (constrained) parameter - type (like in `[T]` or `[T: int|char]`). Constraints given an alias (as in `T`) - shall be used to define `f`, when `f` is composed of `T`, following simple variable - substitution. + type (like in `[T]` or `[T: int|char]`). 4. Subrange or subtype match: `a` is a `range[T]` and `T` matches `f` exactly. Or: `a` is a subtype of `f`. 5. Integral conversion match: `a` is convertible to `f` and `f` and `a` @@ -2645,15 +2650,16 @@ of the argument. 6. Conversion match: `a` is convertible to `f`, possibly via a user defined `converter`. +Each operand may fall into one of the categories above; the operand's +highest priority category. The list above is in order or priority. +If a candidate has more priority matches than all other candidates, it is selected as the +resolved symbol. -There are two major methods of selecting the best matching candidate, namely -counting and disambiguation. Counting takes precedence to disambiguation. In counting, -each parameter is given a category and the number of parameters in each category is counted. For example, if a candidate with one exact match is compared to a candidate with multiple generic matches and zero exact matches, the candidate with an exact match will win. -In the following, `count(p, m)` counts the number of matches of the matching category `m` -for the routine `p`. +Below is a pseudocode interpretation of category matching, `count(p, m)` counts the number +of matches of the matching category `m` for the routine `p`. A routine `p` matches better than a routine `q` if the following algorithm returns true: @@ -2670,15 +2676,51 @@ algorithm returns true: return "ambiguous" ``` -When counting is ambiguous, disambiguation begins. Disambiguation also has two stages, first a -hierarchical type relation comparison, and if that is inconclusive, a complexity comparison. -Where counting relates the type of the operand to the formal parameter, disambiguation relates the -formal parameters with each other to find the most competitive choice. -Parameters are iterated by position and these parameter pairs are compared for their type -relation. The general goal of this comparison is to determine which parameter is least general. +Second Trial: Hierarchical Order Comparison +---------------------------------------------- + +The hierarchical order of a type is analogous to its relative specificity. Consider the type defined: + +```nim +type A[T] = object +``` + +Matching formals for this type include `T`, `object`, `A`, `A[...]` and `A[C]` where `C` is a concrete type, `A[...]` +is a generic typeclass composition and `T` is an unconstrained generic type variable. This list is in order of +specificity with respect to `A` as each subsequent category narrows the set of types that are members of their match set. + +In this trail, the formal parameters of candidates are compared in order (1st parameter, 2nd parameter, etc.) to search for +a candidate that has an unrivaled specificity. If such a formal parameter is found, the candidate it belongs to is chosen +as the resolved symbol. + +Third Trial: Complexity Analysis +---------------------------------- + +A slight clarification: While category matching digests all the formal parameters of a candidate at once (order doesn't matter), +specificity comparison and complexity analysis operate on each formal parameter at a time. The following +is the final trial to disambiguate a symbol choice when a pair of formal parameters have the same hierarchical order. + +The complexity of a type is essentially its number of modifiers and depth of shape. The definition with the *highest* +complexity wins. Consider the following types: + +```nim +type + A[T] = object + B[T, H] = object +``` + +Note: The below examples are not exhaustive. +We shall say that: -Some examples: +1. `A[T]` has a higher complexity than `A` +2. `var A[T]` has a higher complexity than `A[T]` +3. `A[A[T]]` has a higher complexity than `A[T]` +4. `B[T, H]` has a higher complexity than `A[T]` (`A` and `B` are not compatible here, but convoluted versions of this exist) +5. `B[ptr T, H]` has a higher complexity than `B[T, H]` + +Some Examples +--------------- ```nim proc takesInt(x: int) = echo "int" @@ -2749,7 +2791,7 @@ proc p[T: A](param: T) proc p[T: object](param: T) ``` -These signatures are not ambiguous for an instance of `A` even though the formal parameters match ("T" == "T"). +These signatures are not ambiguous for a concrete type of `A` even though the formal parameters match ("T" == "T"). Instead `T` is treated as a variable in that (`T` ?= `T`) depending on the bound type of `T` at the time of overload resolution. |