Skip to content

Commit 21b4e01

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: simplify unifier
The unifier was written such that it was possible to specify a different set of type parameters (declared by different generic declarations) for each type x, y being unified, to allow for what is called "bidirectional unification" in the documentation (comments). However, in the current implementation, this mechanism is not used: - For function type inference, we only consider the type parameter list of the generic function (type parameters that appear in the arguments are considered stand-alone types). We use type parameter renaming to avoid any problems in case of recursive generic calls that rely on type inference. - For constraint type inference, the type parameters for the types x and y (i.e., the type parameter and its constraint) are the same and had to be explicitly set to be identical. This CL removes the ability to set separate type parameter lists. Instead a single type parameter list is used during unification and is provided when we initialize a unifier. As a consequence, we don't need to maintain the separate tparamsList data structure: since we have a single list of type parameters we can keep it directly in the unifier. Adjust all the unifier code accordingly and update comments. As an aside, remove the `exact` flag from the unifier as it was never set. However, keep the functionality for now and use a constant (exactUnification) instead. This makes it easy to find the respectice code without incurring any cost. Change-Id: I969ba6dbbed2d65d06ba4e20b97bdc362c806772 Reviewed-on: https://go-review.googlesource.com/c/go/+/463223 Reviewed-by: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 1780807 commit 21b4e01

File tree

4 files changed

+206
-272
lines changed

4 files changed

+206
-272
lines changed

src/cmd/compile/internal/types2/infer.go

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -135,19 +135,18 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
135135
// Unify parameter and argument types for generic parameters with typed arguments
136136
// and collect the indices of generic parameters with untyped arguments.
137137
// Terminology: generic parameter = function parameter with a type-parameterized type
138-
u := newUnifier(false)
139-
u.x.init(tparams)
138+
u := newUnifier(tparams)
140139

141140
// Set the type arguments which we know already.
142141
for i, targ := range targs {
143142
if targ != nil {
144-
u.x.set(i, targ)
143+
u.set(i, targ)
145144
}
146145
}
147146

148147
errorf := func(kind string, tpar, targ Type, arg *operand) {
149148
// provide a better error message if we can
150-
targs, index := u.x.types()
149+
targs, index := u.inferred()
151150
if index == 0 {
152151
// The first type parameter couldn't be inferred.
153152
// If none of them could be inferred, don't try
@@ -213,7 +212,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
213212

214213
// If we've got all type arguments, we're done.
215214
var index int
216-
targs, index = u.x.types()
215+
targs, index = u.inferred()
217216
if index < 0 {
218217
return targs
219218
}
@@ -249,7 +248,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
249248
}
250249

251250
// If we've got all type arguments, we're done.
252-
targs, index = u.x.types()
251+
targs, index = u.inferred()
253252
if index < 0 {
254253
return targs
255254
}
@@ -462,16 +461,13 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
462461
}()
463462
}
464463

465-
// Setup bidirectional unification between constraints
466-
// and the corresponding type arguments (which may be nil!).
467-
u := newUnifier(false)
468-
u.x.init(tparams)
469-
u.y = u.x // type parameters between LHS and RHS of unification are identical
464+
// Unify type parameters with their constraints.
465+
u := newUnifier(tparams)
470466

471467
// Set the type arguments which we know already.
472468
for i, targ := range targs {
473469
if targ != nil {
474-
u.x.set(i, targ)
470+
u.set(i, targ)
475471
}
476472
}
477473

@@ -490,7 +486,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
490486
// here could handle the respective type parameters only,
491487
// but that will come at a cost of extra complexity which
492488
// may not be worth it.)
493-
for n := u.x.unknowns(); n > 0; {
489+
for n := u.unknowns(); n > 0; {
494490
nn := n
495491

496492
for i, tpar := range tparams {
@@ -501,7 +497,7 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
501497
u.tracef("core(%s) = %s (single = %v)", tpar, core, single)
502498
}
503499
// A type parameter can be unified with its core type in two cases.
504-
tx := u.x.at(i)
500+
tx := u.at(i)
505501
switch {
506502
case tx != nil:
507503
// The corresponding type argument tx is known.
@@ -534,15 +530,15 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
534530
// The corresponding type argument tx is unknown and there's a single
535531
// specific type and no tilde.
536532
// In this case the type argument must be that single type; set it.
537-
u.x.set(i, core.typ)
533+
u.set(i, core.typ)
538534

539535
default:
540536
// Unification is not possible and no progress was made.
541537
continue
542538
}
543539

544540
// The number of known type arguments may have changed.
545-
nn = u.x.unknowns()
541+
nn = u.unknowns()
546542
if nn == 0 {
547543
break // all type arguments are known
548544
}
@@ -560,14 +556,14 @@ func (check *Checker) inferB(tparams []*TypeParam, targs []Type) (types []Type,
560556
n = nn
561557
}
562558

563-
// u.x.types() now contains the incoming type arguments plus any additional type
559+
// u.inferred() now contains the incoming type arguments plus any additional type
564560
// arguments which were inferred from core terms. The newly inferred non-nil
565561
// entries may still contain references to other type parameters.
566562
// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
567563
// was given, unification produced the type list [int, []C, *A]. We eliminate the
568564
// remaining type parameters by substituting the type parameters in this type list
569565
// until nothing changes anymore.
570-
types, _ = u.x.types()
566+
types, _ = u.inferred()
571567
if debug {
572568
for i, targ := range targs {
573569
assert(targ == nil || types[i] == targ)

0 commit comments

Comments
 (0)