summary refs log tree commit diff stats
path: root/doc
diff options
context:
space:
mode:
authorRyan McConnell <rammcconnell@gmail.com>2024-01-19 12:12:31 +0000
committerGitHub <noreply@github.com>2024-01-19 13:12:31 +0100
commitaf8b1d0cb9bfa2f3b91b95219f850d075fc745f1 (patch)
treeaca7b18452824744d0f23254c8289a5f1b5ad130 /doc
parent01097fc1fc70d5c7ce38108d7773e5533fb3743b (diff)
downloadNim-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.md86
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.