Skip to content

Commit b8248fa

Browse files
committed
go/types, types2: disable field accesses through type parameters
This is a feature that is not understood well enough and may have subtle repercussions impacting future changes. Disable for Go 1.18. The actual change is trivial: disable a branch through a flag. The remaining changes are adjustments to tests. Fixes #51576. Change-Id: Ib77b038b846711a808315a8889b3904e72367bce Reviewed-on: https://go-review.googlesource.com/c/go/+/391135 Trust: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> Reviewed-by: Robert Findley <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 7026eeb commit b8248fa

File tree

13 files changed

+177
-74
lines changed

13 files changed

+177
-74
lines changed

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
7070
// see if there is a matching field (but not a method, those need to be declared
7171
// explicitly in the constraint). If the constraint is a named pointer type (see
7272
// above), we are ok here because only fields are accepted as results.
73-
if obj == nil && isTypeParam(T) {
73+
const enableTParamFieldLookup = false // see issue #51576
74+
if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
7475
if t := coreType(T); t != nil {
7576
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
7677
if _, ok := obj.(*Var); !ok {

src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2

+14-10
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
// Field accesses through type parameters are disabled
6+
// until we have a more thorough understanding of the
7+
// implications on the spec. See issue #51576.
8+
59
package p
610

711
type Sf struct {
812
f int
913
}
1014

1115
func f0[P Sf](p P) {
12-
_ = p.f
13-
p.f = 0
16+
_ = p.f // ERROR p\.f undefined
17+
p.f /* ERROR p\.f undefined */ = 0
1418
}
1519

1620
func f0t[P ~struct{f int}](p P) {
17-
_ = p.f
18-
p.f = 0
21+
_ = p.f // ERROR p\.f undefined
22+
p.f /* ERROR p\.f undefined */ = 0
1923
}
2024

2125
var _ = f0[Sf]
@@ -25,8 +29,8 @@ var _ = f0[Sm /* ERROR does not implement */ ]
2529
var _ = f0t[Sm /* ERROR does not implement */ ]
2630

2731
func f1[P interface{ Sf; m() }](p P) {
28-
_ = p.f
29-
p.f = 0
32+
_ = p.f // ERROR p\.f undefined
33+
p.f /* ERROR p\.f undefined */ = 0
3034
p.m()
3135
}
3236

@@ -44,8 +48,8 @@ type Sfm struct {
4448
func (Sfm) m() {}
4549

4650
func f2[P interface{ Sfm; m() }](p P) {
47-
_ = p.f
48-
p.f = 0
51+
_ = p.f // ERROR p\.f undefined
52+
p.f /* ERROR p\.f undefined */ = 0
4953
p.m()
5054
}
5155

@@ -56,8 +60,8 @@ var _ = f2[Sfm]
5660
type PSfm *Sfm
5761

5862
func f3[P interface{ PSfm }](p P) {
59-
_ = p.f
60-
p.f = 0
63+
_ = p.f // ERROR p\.f undefined
64+
p.f /* ERROR p\.f undefined */ = 0
6165
p.m /* ERROR type P has no field or method m */ ()
6266
}
6367

src/cmd/compile/internal/types2/testdata/fixedbugs/issue50782.go2

+10-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
// Field accesses through type parameters are disabled
6+
// until we have a more thorough understanding of the
7+
// implications on the spec. See issue #51576.
8+
59
package p
610

711
// The first example from the issue.
@@ -18,9 +22,12 @@ type numericAbs[T Numeric] interface {
1822
// AbsDifference computes the absolute value of the difference of
1923
// a and b, where the absolute value is determined by the Abs method.
2024
func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
21-
// TODO: the error below should probably be positioned on the '-'.
22-
d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
23-
return d.Abs()
25+
// Field accesses are not permitted for now. Keep an error so
26+
// we can find and fix this code once the situation changes.
27+
return a.Value // ERROR a\.Value undefined
28+
// TODO: The error below should probably be positioned on the '-'.
29+
// d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
30+
// return d.Abs()
2431
}
2532

2633
// The second example from the issue.

src/go/types/lookup.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
7070
// see if there is a matching field (but not a method, those need to be declared
7171
// explicitly in the constraint). If the constraint is a named pointer type (see
7272
// above), we are ok here because only fields are accepted as results.
73-
if obj == nil && isTypeParam(T) {
73+
const enableTParamFieldLookup = false // see issue #51576
74+
if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
7475
if t := coreType(T); t != nil {
7576
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
7677
if _, ok := obj.(*Var); !ok {

src/go/types/testdata/fixedbugs/issue50417.go2

+14-10
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,24 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
// Field accesses through type parameters are disabled
6+
// until we have a more thorough understanding of the
7+
// implications on the spec. See issue #51576.
8+
59
package p
610

711
type Sf struct {
812
f int
913
}
1014

1115
func f0[P Sf](p P) {
12-
_ = p.f
13-
p.f = 0
16+
_ = p.f // ERROR p\.f undefined
17+
p.f /* ERROR p\.f undefined */ = 0
1418
}
1519

1620
func f0t[P ~struct{f int}](p P) {
17-
_ = p.f
18-
p.f = 0
21+
_ = p.f // ERROR p\.f undefined
22+
p.f /* ERROR p\.f undefined */ = 0
1923
}
2024

2125
var _ = f0[Sf]
@@ -25,8 +29,8 @@ var _ = f0[Sm /* ERROR does not implement */ ]
2529
var _ = f0t[Sm /* ERROR does not implement */ ]
2630

2731
func f1[P interface{ Sf; m() }](p P) {
28-
_ = p.f
29-
p.f = 0
32+
_ = p.f // ERROR p\.f undefined
33+
p.f /* ERROR p\.f undefined */ = 0
3034
p.m()
3135
}
3236

@@ -44,8 +48,8 @@ type Sfm struct {
4448
func (Sfm) m() {}
4549

4650
func f2[P interface{ Sfm; m() }](p P) {
47-
_ = p.f
48-
p.f = 0
51+
_ = p.f // ERROR p\.f undefined
52+
p.f /* ERROR p\.f undefined */ = 0
4953
p.m()
5054
}
5155

@@ -56,8 +60,8 @@ var _ = f2[Sfm]
5660
type PSfm *Sfm
5761

5862
func f3[P interface{ PSfm }](p P) {
59-
_ = p.f
60-
p.f = 0
63+
_ = p.f // ERROR p\.f undefined
64+
p.f /* ERROR p\.f undefined */ = 0
6165
p.m /* ERROR type P has no field or method m */ ()
6266
}
6367

src/go/types/testdata/fixedbugs/issue50782.go2

+10-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5+
// Field accesses through type parameters are disabled
6+
// until we have a more thorough understanding of the
7+
// implications on the spec. See issue #51576.
8+
59
package p
610

711
// The first example from the issue.
@@ -18,9 +22,12 @@ type numericAbs[T Numeric] interface {
1822
// AbsDifference computes the absolute value of the difference of
1923
// a and b, where the absolute value is determined by the Abs method.
2024
func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
21-
// TODO: the error below should probably be positioned on the '-'.
22-
d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
23-
return d.Abs()
25+
// Field accesses are not permitted for now. Keep an error so
26+
// we can find and fix this code once the situation changes.
27+
return a.Value // ERROR a\.Value undefined
28+
// TODO: The error below should probably be positioned on the '-'.
29+
// d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
30+
// return d.Abs()
2431
}
2532

2633
// The second example from the issue.

test/typeparam/absdiff2.go

+23-9
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,16 @@ type Numeric interface {
2323

2424
// numericAbs matches a struct containing a numeric type that has an Abs method.
2525
type numericAbs[T Numeric] interface {
26-
~struct{ Value T }
26+
~struct{ Value_ T }
2727
Abs() T
28+
Value() T
2829
}
2930

3031
// absDifference computes the absolute value of the difference of
3132
// a and b, where the absolute value is determined by the Abs method.
3233
func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
33-
d := a.Value - b.Value
34-
dt := U{Value: d}
34+
d := a.Value() - b.Value()
35+
dt := U{Value_: d}
3536
return dt.Abs()
3637
}
3738

@@ -50,20 +51,29 @@ type Complex interface {
5051
// orderedAbs is a helper type that defines an Abs method for
5152
// a struct containing an ordered numeric type.
5253
type orderedAbs[T orderedNumeric] struct {
53-
Value T
54+
Value_ T
5455
}
5556

5657
func (a orderedAbs[T]) Abs() T {
57-
if a.Value < 0 {
58-
return -a.Value
58+
if a.Value_ < 0 {
59+
return -a.Value_
5960
}
60-
return a.Value
61+
return a.Value_
62+
}
63+
64+
// Field accesses through type parameters are disabled
65+
// until we have a more thorough understanding of the
66+
// implications on the spec. See issue #51576.
67+
// Use accessor method instead.
68+
69+
func (a orderedAbs[T]) Value() T {
70+
return a.Value_
6171
}
6272

6373
// complexAbs is a helper type that defines an Abs method for
6474
// a struct containing a complex type.
6575
type complexAbs[T Complex] struct {
66-
Value T
76+
Value_ T
6777
}
6878

6979
func realimag(x any) (re, im float64) {
@@ -82,13 +92,17 @@ func realimag(x any) (re, im float64) {
8292

8393
func (a complexAbs[T]) Abs() T {
8494
// TODO use direct conversion instead of realimag once #50937 is fixed
85-
r, i := realimag(a.Value)
95+
r, i := realimag(a.Value_)
8696
// r := float64(real(a.Value))
8797
// i := float64(imag(a.Value))
8898
d := math.Sqrt(r*r + i*i)
8999
return T(complex(d, 0))
90100
}
91101

102+
func (a complexAbs[T]) Value() T {
103+
return a.Value_
104+
}
105+
92106
// OrderedAbsDifference returns the absolute value of the difference
93107
// between a and b, where a and b are of an ordered type.
94108
func OrderedAbsDifference[T orderedNumeric](a, b T) T {

test/typeparam/absdiffimp2.dir/a.go

+23-9
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ type Numeric interface {
1717

1818
// numericAbs matches a struct containing a numeric type that has an Abs method.
1919
type numericAbs[T Numeric] interface {
20-
~struct{ Value T }
20+
~struct{ Value_ T }
2121
Abs() T
22+
Value() T
2223
}
2324

2425
// absDifference computes the absolute value of the difference of
2526
// a and b, where the absolute value is determined by the Abs method.
2627
func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
27-
d := a.Value - b.Value
28-
dt := U{Value: d}
28+
d := a.Value() - b.Value()
29+
dt := U{Value_: d}
2930
return dt.Abs()
3031
}
3132

@@ -44,20 +45,29 @@ type Complex interface {
4445
// orderedAbs is a helper type that defines an Abs method for
4546
// a struct containing an ordered numeric type.
4647
type orderedAbs[T orderedNumeric] struct {
47-
Value T
48+
Value_ T
4849
}
4950

5051
func (a orderedAbs[T]) Abs() T {
51-
if a.Value < 0 {
52-
return -a.Value
52+
if a.Value_ < 0 {
53+
return -a.Value_
5354
}
54-
return a.Value
55+
return a.Value_
56+
}
57+
58+
// Field accesses through type parameters are disabled
59+
// until we have a more thorough understanding of the
60+
// implications on the spec. See issue #51576.
61+
// Use accessor method instead.
62+
63+
func (a orderedAbs[T]) Value() T {
64+
return a.Value_
5565
}
5666

5767
// complexAbs is a helper type that defines an Abs method for
5868
// a struct containing a complex type.
5969
type complexAbs[T Complex] struct {
60-
Value T
70+
Value_ T
6171
}
6272

6373
func realimag(x any) (re, im float64) {
@@ -76,13 +86,17 @@ func realimag(x any) (re, im float64) {
7686

7787
func (a complexAbs[T]) Abs() T {
7888
// TODO use direct conversion instead of realimag once #50937 is fixed
79-
r, i := realimag(a.Value)
89+
r, i := realimag(a.Value_)
8090
// r := float64(real(a.Value))
8191
// i := float64(imag(a.Value))
8292
d := math.Sqrt(r*r + i*i)
8393
return T(complex(d, 0))
8494
}
8595

96+
func (a complexAbs[T]) Value() T {
97+
return a.Value_
98+
}
99+
86100
// OrderedAbsDifference returns the absolute value of the difference
87101
// between a and b, where a and b are of an ordered type.
88102
func OrderedAbsDifference[T orderedNumeric](a, b T) T {

test/typeparam/issue50417.go

+6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ package main
88

99
func main() {}
1010

11+
// Field accesses through type parameters are disabled
12+
// until we have a more thorough understanding of the
13+
// implications on the spec. See issue #51576.
14+
15+
/*
1116
type Sf struct {
1217
f int
1318
}
@@ -138,3 +143,4 @@ func f8[P Int4](p P) {
138143
}
139144
140145
var _ = f8[*Sf]
146+
*/

test/typeparam/issue50417b.go

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66

77
package main
88

9+
func main() {}
10+
11+
// Field accesses through type parameters are disabled
12+
// until we have a more thorough understanding of the
13+
// implications on the spec. See issue #51576.
14+
15+
/*
916
import "fmt"
1017
1118
type MyStruct struct {
@@ -48,3 +55,4 @@ func main() {
4855
panic(fmt.Sprintf("got %d, want %d", got, want))
4956
}
5057
}
58+
*/

0 commit comments

Comments
 (0)