Skip to content

Commit 114402d

Browse files
authored
Merge pull request #85322 from slavapestov/type-checker-docs-tweak
docs: Remove obsolete example from TypeChecker.md
2 parents 758e67f + a81a3d3 commit 114402d

File tree

1 file changed

+28
-103
lines changed

1 file changed

+28
-103
lines changed

docs/TypeChecker.md

Lines changed: 28 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -838,90 +838,44 @@ node based on the kind of expression:
838838
the body of the closure is type-checked with that
839839
complete function type.
840840

841-
The solution application step cannot fail for any type checking rule
842-
modeled by the constraint system. However, there are some failures
843-
that are intentionally left to the solution application phase, such as
844-
a postfix '!' applied to a non-optional type.
841+
The solution application step cannot fail.
845842

846843
#### Locators
847844

848845
During constraint generation and solving, numerous constraints are
849846
created, broken apart, and solved. During constraint application as
850847
well as during diagnostics emission, it is important to track the
851848
relationship between the constraints and the actual AST nodes from
852-
which they originally came. For example, consider the following type
853-
checking problem::
854-
```swift
855-
struct X {
856-
// user-defined conversions
857-
func [conversion] __conversion () -> String { /* ... */ }
858-
func [conversion] __conversion () -> Int { /* ... */ }
859-
}
860-
861-
func f(_ i : Int, s : String) { }
862-
863-
var x : X
864-
f(10.5, x)
865-
```
866-
This constraint system generates the constraints "`T(f)` ==Fn `T0 -> T1`"
867-
(for fresh variables `T0` and `T1`), "`(T2, X) <c T0`" (for fresh variable `T2`)
868-
and "`T2` conforms to `ExpressibleByFloatLiteral`". As part of the solution,
869-
after `T0` is replaced with `(i : Int, s : String)`, the second of
870-
these constraints is broken down into "`T2 <c Int`" and "`X <c String`".
871-
These two constraints are interesting for different
872-
reasons: the first will fail, because `Int` does not conform to
873-
`ExpressibleByFloatLiteral`. The second will succeed by selecting one
874-
of the (overloaded) conversion functions.
875-
876-
In both of these cases, we need to map the actual constraint of
877-
interest back to the expressions they refer to. In the first case, we
878-
want to report not only that the failure occurred because `Int` is
879-
not `ExpressibleByFloatLiteral`, but we also want to point out where
880-
the `Int` type actually came from, i.e., in the parameter. In the
881-
second case, we want to determine which of the overloaded conversion
882-
functions was selected to perform the conversion, so that conversion
883-
function can be called by constraint application if all else succeeds.
884-
885-
*Locators* address both issues by tracking the location and derivation
886-
of constraints. Each locator is anchored at a specific AST node
887-
(expression, pattern, declaration etc.) i.e., the function application
888-
`f(10.5, x)`, and contains a path of zero or more derivation steps
889-
from that anchor. For example, the "`T(f)` ==Fn `T0 -> T1`"
890-
constraint has a locator that is anchored at the function application
891-
and a path with the "apply function" derivation step, meaning that
892-
this is the function being applied. Similarly, the "`(T2, X) <c T0`
893-
constraint has a locator anchored at the function application and a
894-
path with the "apply argument" derivation step, meaning that this is
849+
which they originally came.
850+
851+
We need to map constraints back to the expressions they refer to.
852+
853+
*Locators* track the location and derivation of constraints.
854+
Each locator is anchored at a specific AST node
855+
(expression, pattern, declaration etc.). For example, an applicable
856+
function constraint has a locator that is anchored at the function
857+
application expression, and a path with the "apply function"
858+
derivation step. Similarly, an conversion constraint generated for
859+
a function argument has a locator anchored at the function application
860+
and a path with the "apply argument" derivation step, meaning that this is
895861
the argument to the function.
896862

897863
When constraints are simplified, the resulting constraints have
898864
locators with longer paths. For example, when a conversion constraint between two
899-
tuples is simplified conversion constraints between the corresponding
900-
tuple elements, the resulting locators refer to specific elements. For
901-
example, the `T2 <c Int` constraint will be anchored at the function
902-
application (still), and have two derivation steps in its path: the
903-
"apply function" derivation step from its parent constraint followed
904-
by the "tuple element 0" constraint that refers to this specific tuple
905-
element. Similarly, the `X <c String` constraint will have the same
906-
locator, but with "tuple element 1" rather than "tuple element 0". The
907-
`ConstraintLocator` type in the constraint solver has a number of
865+
tuples is simplified down to conversion constraints between the corresponding
866+
tuple elements, the resulting locators refer to specific elements.
867+
868+
The `ConstraintLocator` type in the constraint solver has a number of
908869
different derivation step kinds (called "path elements" in the source)
909870
that describe the various ways in which larger constraints can be
910871
broken down into smaller ones.
911872

912873
##### Overload Choices
913874

914875
Whenever the solver creates a new overload set, that overload set is
915-
associated with a particular locator. Continuing the example from the
916-
parent section, the solver will create an overload set containing the
917-
two user-defined conversions. This overload set is created while
918-
simplifying the constraint `X <c String`, so it uses the locator
919-
from that constraint extended by a "conversion member" derivation
920-
step. The complete locator for this overload set is, therefore::
921-
```
922-
function application -> apply argument -> tuple element #1 -> conversion member
923-
```
924-
When the solver selects a particular overload from the overload set,
876+
associated with a particular locator.
877+
878+
When the solver selects a particular overload an the overload set,
925879
it records the selected overload based on the locator of the overload
926880
set. When it comes time to perform constraint application, the locator
927881
is recreated based on context (as the bottom-up traversal walks the
@@ -942,46 +896,17 @@ the path of the solver, and can be used to query and recover the
942896
important decisions made by the solver. However, the locators
943897
determined by the solver may not directly refer to the most specific
944898
AST node for the purposes of identifying the corresponding source
945-
location. For example, the failed constraint "`Int` conforms to
946-
`ExpressibleByFloatLiteral`" can most specifically by centered on the
947-
floating-point literal `10.5`, but its locator is::
948-
```
949-
function application -> apply argument -> tuple element #0
950-
```
899+
location.
900+
951901
The process of locator simplification maps a locator to its most
952902
specific AST node. Essentially, it starts at the anchor of the
953-
locator (in this case, the application `f(10.5, x)`) and then walks
954-
the path, matching derivation steps to subexpressions. The "function
955-
application" derivation step extracts the argument (`(10.5, x)`).
956-
Then, the "tuple element #0" derivation extracts the tuple
957-
element 0 subexpression, `10.5`, at which point we have traversed
958-
the entire path and now have the most specific expression for
959-
source-location purposes.
960-
961-
Simplification does not always exhaust the complete path. For example,
962-
consider a slight modification to our example, so that the argument to
963-
`f` is provided by another call, we get a different result
964-
entirely::
965-
```swift
966-
func f(_ i : Int, s : String) { }
967-
func g() -> (f : Float, x : X) { }
903+
locator and then walks the path, matching derivation steps to
904+
subexpressions.
905+
906+
For example, the "function application" derivation step extracts
907+
the argument list, and the "tuple element #0" derivation extracts
908+
the sub-expression for the first argument.
968909

969-
f(g())
970-
```
971-
Here, the failing constraint is `Float <c Int`, with the same
972-
locator::
973-
```
974-
function application -> apply argument -> tuple element #0
975-
```
976-
When we simplify this locator, we start with `f(g())`. The "apply
977-
argument" derivation step takes us to the argument expression
978-
`g()`. Here, however, there is no subexpression for the first tuple
979-
element of `g()`, because it's simply part of the tuple returned
980-
from `g`. At this point, simplification ceases, and creates the
981-
simplified locator::
982-
```
983-
function application of g -> tuple element #0
984-
```
985910
### Performance
986911

987912
The performance of the type checker is dependent on a number of

0 commit comments

Comments
 (0)