Skip to content

Commit ee29dbe

Browse files
griesemergopherbot
authored andcommitted
go/types, types2: don't lose alias information during unification
While at it, rename asTypeParam to asBoundTypeParam for clarity. For #67547. Fixes #67628. Change-Id: I2f447c4cd4d72f5315fe9323d82fcb9bf33657c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/588797 Reviewed-by: Robert Griesemer <[email protected]> Auto-Submit: Robert Griesemer <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Commit-Queue: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent c26be72 commit ee29dbe

File tree

3 files changed

+49
-30
lines changed

3 files changed

+49
-30
lines changed

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

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -205,10 +205,10 @@ func (u *unifier) join(x, y *TypeParam) bool {
205205
return true
206206
}
207207

208-
// asTypeParam returns x.(*TypeParam) if x is a type parameter recorded with u.
208+
// asBoundTypeParam returns x.(*TypeParam) if x is a type parameter recorded with u.
209209
// Otherwise, the result is nil.
210-
func (u *unifier) asTypeParam(x Type) *TypeParam {
211-
if x, _ := x.(*TypeParam); x != nil {
210+
func (u *unifier) asBoundTypeParam(x Type) *TypeParam {
211+
if x, _ := Unalias(x).(*TypeParam); x != nil {
212212
if _, found := u.handles[x]; found {
213213
return x
214214
}
@@ -269,7 +269,7 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
269269
// asInterface returns the underlying type of x as an interface if
270270
// it is a non-type parameter interface. Otherwise it returns nil.
271271
func asInterface(x Type) (i *Interface) {
272-
if _, ok := x.(*TypeParam); !ok {
272+
if _, ok := Unalias(x).(*TypeParam); !ok {
273273
i, _ = under(x).(*Interface)
274274
}
275275
return i
@@ -291,11 +291,8 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
291291
u.depth--
292292
}()
293293

294-
x = Unalias(x)
295-
y = Unalias(y)
296-
297294
// nothing to do if x == y
298-
if x == y {
295+
if x == y || Unalias(x) == Unalias(y) {
299296
return true
300297
}
301298

@@ -314,7 +311,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
314311
// Ensure that if we have at least one
315312
// - defined type, make sure one is in y
316313
// - type parameter recorded with u, make sure one is in x
317-
if asNamed(x) != nil || u.asTypeParam(y) != nil {
314+
if asNamed(x) != nil || u.asBoundTypeParam(y) != nil {
318315
if traceInference {
319316
u.tracef("%s ≡ %s\t// swap", y, x)
320317
}
@@ -358,7 +355,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
358355
// isTypeLit(x) is false and y was not changed above. In other
359356
// words, if y was a defined type, it is still a defined type
360357
// (relevant for the logic below).
361-
switch px, py := u.asTypeParam(x), u.asTypeParam(y); {
358+
switch px, py := u.asBoundTypeParam(x), u.asBoundTypeParam(y); {
362359
case px != nil && py != nil:
363360
// both x and y are type parameters
364361
if u.join(px, py) {
@@ -449,7 +446,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
449446
}
450447

451448
// x != y if we get here
452-
assert(x != y)
449+
assert(x != y && Unalias(x) != Unalias(y))
453450

454451
// If u.EnableInterfaceInference is set and we don't require exact unification,
455452
// if both types are interfaces, one interface must have a subset of the
@@ -573,6 +570,10 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
573570
emode |= exact
574571
}
575572

573+
// Continue with unaliased types but don't lose original alias names, if any (go.dev/issue/67628).
574+
xorig, x := x, Unalias(x)
575+
yorig, y := y, Unalias(y)
576+
576577
switch x := x.(type) {
577578
case *Basic:
578579
// Basic types are singletons except for the rune and byte
@@ -751,7 +752,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
751752
case *TypeParam:
752753
// x must be an unbound type parameter (see comment above).
753754
if debug {
754-
assert(u.asTypeParam(x) == nil)
755+
assert(u.asBoundTypeParam(x) == nil)
755756
}
756757
// By definition, a valid type argument must be in the type set of
757758
// the respective type constraint. Therefore, the type argument's
@@ -774,13 +775,13 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
774775
// need to take care of that case separately.
775776
if cx := coreType(x); cx != nil {
776777
if traceInference {
777-
u.tracef("core %s ≡ %s", x, y)
778+
u.tracef("core %s ≡ %s", xorig, yorig)
778779
}
779780
// If y is a defined type, it may not match against cx which
780781
// is an underlying type (incl. int, string, etc.). Use assign
781782
// mode here so that the unifier automatically takes under(y)
782783
// if necessary.
783-
return u.nify(cx, y, assign, p)
784+
return u.nify(cx, yorig, assign, p)
784785
}
785786
}
786787
// x != y and there's nothing to do
@@ -789,7 +790,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
789790
// avoid a crash in case of nil type
790791

791792
default:
792-
panic(sprintf(nil, true, "u.nify(%s, %s, %d)", x, y, mode))
793+
panic(sprintf(nil, true, "u.nify(%s, %s, %d)", xorig, yorig, mode))
793794
}
794795

795796
return false

src/go/types/unify.go

Lines changed: 16 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// -gotypesalias=1
2+
3+
// Copyright 2024 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
func f[P any](x P) P { return x }
10+
11+
func _() {
12+
type A = int
13+
var a A
14+
b := f(a) // type of b is A
15+
// error should report type of b as A, not int
16+
_ = b /* ERROR "mismatched types A and untyped string" */ + "foo"
17+
}

0 commit comments

Comments
 (0)