Skip to content

Commit 7042ea6

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: clean up defined type identity check/unification
Factor out check for identical origin. Match unification code with type identity check. Add a test case for #53692. Change-Id: I1238b28297a5ac549e99261c8a085dd46f3dd65f Reviewed-on: https://go-review.googlesource.com/c/go/+/474197 Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Robert Griesemer <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Auto-Submit: Robert Griesemer <[email protected]>
1 parent 269bdcd commit 7042ea6

File tree

5 files changed

+63
-60
lines changed

5 files changed

+63
-60
lines changed

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

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -433,33 +433,23 @@ func (c *comparer) identical(x, y Type, p *ifacePair) bool {
433433

434434
case *Named:
435435
// Two named types are identical if their type names originate
436-
// in the same type declaration.
436+
// in the same type declaration; if they are instantiated they
437+
// must have identical type argument lists.
437438
if y, ok := y.(*Named); ok {
439+
// check type arguments before origins to match unifier
440+
// (for correct source code we need to do all checks so
441+
// order doesn't matter)
438442
xargs := x.TypeArgs().list()
439443
yargs := y.TypeArgs().list()
440-
441444
if len(xargs) != len(yargs) {
442445
return false
443446
}
444-
445-
if len(xargs) > 0 {
446-
// Instances are identical if their original type and type arguments
447-
// are identical.
448-
if !Identical(x.Origin(), y.Origin()) {
447+
for i, xarg := range xargs {
448+
if !Identical(xarg, yargs[i]) {
449449
return false
450450
}
451-
for i, xa := range xargs {
452-
if !Identical(xa, yargs[i]) {
453-
return false
454-
}
455-
}
456-
return true
457451
}
458-
459-
// TODO(gri) Why is x == y not sufficient? And if it is,
460-
// we can just return false here because x == y
461-
// is caught in the very beginning of this function.
462-
return x.obj == y.obj
452+
return indenticalOrigin(x, y)
463453
}
464454

465455
case *TypeParam:
@@ -475,6 +465,12 @@ func (c *comparer) identical(x, y Type, p *ifacePair) bool {
475465
return false
476466
}
477467

468+
// identicalOrigin reports whether x and y originated in the same declaration.
469+
func indenticalOrigin(x, y *Named) bool {
470+
// TODO(gri) is this correct?
471+
return x.Origin().obj == y.Origin().obj
472+
}
473+
478474
// identicalInstance reports if two type instantiations are identical.
479475
// Instantiations are identical if their origin and type arguments are
480476
// identical.

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

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -506,26 +506,24 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
506506
}
507507

508508
case *Named:
509-
// TODO(gri) This code differs now from the parallel code in Checker.identical. Investigate.
509+
// Two named types are identical if their type names originate
510+
// in the same type declaration; if they are instantiated they
511+
// must have identical type argument lists.
510512
if y, ok := y.(*Named); ok {
513+
// check type arguments before origins so they unify
514+
// even if the origins don't match; for better error
515+
// messages (see go.dev/issue/53692)
511516
xargs := x.TypeArgs().list()
512517
yargs := y.TypeArgs().list()
513-
514518
if len(xargs) != len(yargs) {
515519
return false
516520
}
517-
518-
// TODO(gri) This is not always correct: two types may have the same names
519-
// in the same package if one of them is nested in a function.
520-
// Extremely unlikely but we need an always correct solution.
521-
if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
522-
for i, x := range xargs {
523-
if !u.nify(x, yargs[i], p) {
524-
return false
525-
}
521+
for i, xarg := range xargs {
522+
if !u.nify(xarg, yargs[i], p) {
523+
return false
526524
}
527-
return true
528525
}
526+
return indenticalOrigin(x, y)
529527
}
530528

531529
case *TypeParam:

src/go/types/predicates.go

Lines changed: 14 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/go/types/unify.go

Lines changed: 10 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package p
6+
7+
type Cache[K comparable, V any] interface{}
8+
9+
type LRU[K comparable, V any] struct{}
10+
11+
func WithLocking2[K comparable, V any](Cache[K, V]) {}
12+
13+
func _() {
14+
WithLocking2[string](LRU /* ERROR "type LRU[string, int] of LRU[string, int]{} does not match inferred type Cache[string, int] for Cache[string, V]" */ [string, int]{})
15+
}

0 commit comments

Comments
 (0)