Skip to content

Commit 03bec7d

Browse files
griesemerRobert Griesemer
authored and
Robert Griesemer
committed
spec: add Appendix with detailed type unification rules
Change-Id: I0d4ccbc396c48d565c0cbe93c9558ab330a44d02 Reviewed-on: https://go-review.googlesource.com/c/go/+/513275 Auto-Submit: Robert Griesemer <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> TryBot-Bypass: Robert Griesemer <[email protected]>
1 parent 208fc13 commit 03bec7d

File tree

1 file changed

+155
-7
lines changed

1 file changed

+155
-7
lines changed

doc/go_spec.html

+155-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!--{
22
"Title": "The Go Programming Language Specification",
3-
"Subtitle": "Version of July 25, 2023",
3+
"Subtitle": "Version of July 31, 2023",
44
"Path": "/ref/spec"
55
}-->
66

@@ -4620,13 +4620,13 @@ <h4 id="Type_unification">Type unification</h4>
46204620
<p>
46214621
Type inference solves type equations through <i>type unification</i>.
46224622
Type unification recursively compares the LHS and RHS types of an
4623-
equation, where either or both types may be or contain type parameters,
4623+
equation, where either or both types may be or contain bound type parameters,
46244624
and looks for type arguments for those type parameters such that the LHS
46254625
and RHS match (become identical or assignment-compatible, depending on
46264626
context).
46274627
To that effect, type inference maintains a map of bound type parameters
4628-
to inferred type arguments.
4629-
Initially, the type parameters are known but the map is empty.
4628+
to inferred type arguments; this map is consulted and updated during type unification.
4629+
Initially, the bound type parameters are known but the map is empty.
46304630
During type unification, if a new type argument <code>A</code> is inferred,
46314631
the respective mapping <code>P ➞ A</code> from type parameter to argument
46324632
is added to the map.
@@ -4674,9 +4674,12 @@ <h4 id="Type_unification">Type unification</h4>
46744674

46754675
<p>
46764676
Unification uses a combination of <i>exact</i> and <i>loose</i>
4677-
Unification (see Appendix) depending on whether two types have
4678-
to be <a href="#Type_identity">identical</a> or simply
4679-
<a href="#Assignability">assignment-compatible</a>:
4677+
unification depending on whether two types have to be
4678+
<a href="#Type_identity">identical</a>,
4679+
<a href="#Assignability">assignment-compatible</a>, or
4680+
only structurally equal.
4681+
The respective <a href="#Type_unification_rules">type unification rules</a>
4682+
are spelled out in detail in the <a href="#Appendix">Appendix</a>.
46804683
</p>
46814684

46824685
<p>
@@ -8357,3 +8360,148 @@ <h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
83578360
<p>
83588361
A struct or array type has size zero if it contains no fields (or elements, respectively) that have a size greater than zero. Two distinct zero-size variables may have the same address in memory.
83598362
</p>
8363+
8364+
<h2 id="Appendix">Appendix</h2>
8365+
8366+
<h3 id="Type_unification_rules">Type unification rules</h3>
8367+
8368+
<p>
8369+
The type unification rules describe if and how two types unify.
8370+
The precise details are relevant for Go implementations,
8371+
affect the specifics of error messages (such as whether
8372+
a compiler reports a type inference or other error),
8373+
and may explain why type inference fails in unusual code situations.
8374+
But by and large these rules can be ignored when writing Go code:
8375+
type inference is designed to mostly "work as expected",
8376+
and the unification rules are fine-tuned accordingly.
8377+
</p>
8378+
8379+
<p>
8380+
Type unification is controlled by a <i>matching mode</i>, which may
8381+
be <i>exact</i> or <i>loose</i>.
8382+
As unification recursively descends a composite type structure,
8383+
the matching mode used for elements of the type, the <i>element matching mode</i>,
8384+
remains the same as the matching mode except when two types are unified for
8385+
<a href="#Assignability">assignability</a> (<code><sub>A</sub></code>):
8386+
in this case, the matching mode is <i>loose</i> at the top level but
8387+
then changes to <i>exact</i> for element types, reflecting the fact
8388+
that types don't have to be identical to be assignable.
8389+
</p>
8390+
8391+
<p>
8392+
Two types that are not bound type parameters unify exactly if any of
8393+
following conditions is true:
8394+
</p>
8395+
8396+
<ul>
8397+
<li>
8398+
Both types are <a href="#Type_identity">identical</a>.
8399+
</li>
8400+
<li>
8401+
Both types have identical structure and their element types
8402+
unify exactly.
8403+
</li>
8404+
<li>
8405+
Exactly one type is an <a href="#Type_inference">unbound</a>
8406+
type parameter with a <a href="#Core_types">core type</a>,
8407+
and that core type unifies with the other type per the
8408+
unification rules for <code><sub>A</sub></code>
8409+
(loose unification at the top level and exact unification
8410+
for element types).
8411+
</li>
8412+
</ul>
8413+
8414+
<p>
8415+
If both types are bound type parameters, they unify per the given
8416+
matching modes if:
8417+
</p>
8418+
8419+
<ul>
8420+
<li>
8421+
Both type parameters are identical.
8422+
</li>
8423+
<li>
8424+
At most one of the type parameters has a known type argument.
8425+
In this case, the type parameters are <i>joined</i>:
8426+
they both stand for the same type argument.
8427+
If neither type parameter has a known type argument yet,
8428+
a future type argument inferred for one the type parameters
8429+
is simultaneously inferred for both of them.
8430+
</li>
8431+
<li>
8432+
Both type parameters have a known type argument
8433+
and the type arguments unify per the given matching modes.
8434+
</li>
8435+
</ul>
8436+
8437+
<p>
8438+
A single bound type parameter <code>P</code> and another type <code>T</code> unify
8439+
per the given matching modes if:
8440+
</p>
8441+
8442+
<ul>
8443+
<li>
8444+
<code>P</code> doesn't have a known type argument.
8445+
In this case, <code>T</code> is inferred as the type argument for <code>P</code>.
8446+
</li>
8447+
<li>
8448+
<code>P</code> does have a known type argument <code>A</code>,
8449+
<code>A</code> and <code>T</code> unify per the given matching modes,
8450+
and one of the following conditions is true:
8451+
<ul>
8452+
<li>
8453+
Both <code>A</code> and <code>T</code> are interface types:
8454+
In this case, if both <code>A</code> and <code>T</code> are
8455+
also <a href="#Type_definitions">defined</a> types,
8456+
they must be <a href="#Type_identity">identical</a>.
8457+
Otherwise, if neither of them is a defined type, they must
8458+
have the same number of methods
8459+
(unification of <code>A</code> and <code>T</code> already
8460+
established that the methods match).
8461+
</li>
8462+
<li>
8463+
Neither <code>A</code> nor <code>T</code> are interface types:
8464+
In this case, if <code>T</code> is a defined type, <code>T</code>
8465+
replaces <code>A</code> as the inferred type argument for <code>P</code>.
8466+
</li>
8467+
<li>
8468+
In all other cases unification of <code>P</code> and <code>T</code> fails.
8469+
</li>
8470+
</ul>
8471+
</li>
8472+
</ul>
8473+
8474+
<p>
8475+
Finally, two types that are not bound type parameters unify loosely
8476+
(and per the element matching mode) if:
8477+
</p>
8478+
8479+
<ul>
8480+
<li>
8481+
Both types unify exactly.
8482+
</li>
8483+
<li>
8484+
One type is a <a href="#Type_definitions">defined type</a>,
8485+
the other type is a type literal, but not an interface,
8486+
and their underlying types unify per the element matching mode.
8487+
</li>
8488+
<li>
8489+
Both types are interfaces (but not type parameters) with
8490+
identical <a href="#Interface_types">type terms</a>,
8491+
both or neither embed the predeclared type
8492+
<a href="#Predeclared_identifiers">comparable</a>,
8493+
corresponding method types unify per the element matching mode,
8494+
and the method set of one of the interfaces is a subset of
8495+
the method set of the other interface.
8496+
</li>
8497+
<li>
8498+
Only one type is an interface (but not a type parameter),
8499+
corresponding methods of the two types unify per the element matching mode,
8500+
and the method set of the interface is a subset of
8501+
the method set of the other type.
8502+
</li>
8503+
<li>
8504+
Both types have the same structure and their element types
8505+
unify per the element matching mode.
8506+
</li>
8507+
</ul>

0 commit comments

Comments
 (0)