diff options
author | Robert Griesemer <gri@golang.org> | 2022-01-05 15:46:31 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2022-01-06 21:38:59 +0000 |
commit | 61014f00f24df8b144d9d235fe3e25ff64b96521 (patch) | |
tree | 9eaa26bbf277f58527faa5999c94c10e6d25da1e /src/cmd | |
parent | 2bfa6ef63d3cfa89f46cc5f6708c1078f15fb875 (diff) | |
download | go-61014f00f24df8b144d9d235fe3e25ff64b96521.tar.gz go-61014f00f24df8b144d9d235fe3e25ff64b96521.zip |
go/types, types2: implement field access for struct structural constraints
This change implements field the access p.f where the type of p
is a type parameter with a structural constraint that is a struct
with a field f. This is only the fix for the type checker. The
compiler will need a separate CL.
This makes the behavior consistent with the fact that we can
write struct composite literals for type parameters with a
struct structural type.
For #50417.
For #50233.
Change-Id: I87d07e016f97cbf19c45cde19165eae3ec0bad2b
Reviewed-on: https://go-review.googlesource.com/c/go/+/375795
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r-- | src/cmd/compile/internal/types2/lookup.go | 18 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 | 64 |
2 files changed, 80 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go index 7bdf13b4b7..77a70a0510 100644 --- a/src/cmd/compile/internal/types2/lookup.go +++ b/src/cmd/compile/internal/types2/lookup.go @@ -43,7 +43,7 @@ import ( // the method's formal receiver base type, nor was the receiver addressable. // func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) { - // Methods cannot be associated to a named pointer type + // Methods cannot be associated to a named pointer type. // (spec: "The type denoted by T is called the receiver base type; // it must not be a pointer or interface type and it must be declared // in the same package as the method."). @@ -60,7 +60,21 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o } } - return lookupFieldOrMethod(T, addressable, false, pkg, name) + obj, index, indirect = lookupFieldOrMethod(T, addressable, false, pkg, name) + + // If we didn't find anything and if we have a type parameter with a structural constraint, + // see if there is a matching field (but not a method, those need to be declared explicitly + // in the constraint). If the structural constraint is a named pointer type (see above), we + // are ok here because only fields are accepted as results. + if obj == nil && isTypeParam(T) { + if t := structuralType(T); t != nil { + obj, index, indirect = lookupFieldOrMethod(t, addressable, false, pkg, name) + if _, ok := obj.(*Var); !ok { + obj, index, indirect = nil, nil, false // accept fields (variables) only + } + } + } + return } // TODO(gri) The named type consolidation and seen maps below must be diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 new file mode 100644 index 0000000000..c05987e5ea --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue50417.go2 @@ -0,0 +1,64 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Sf struct { + f int +} + +func f0[P Sf](p P) { + _ = p.f + p.f = 0 +} + +func f0t[P ~struct{f int}](p P) { + _ = p.f + p.f = 0 +} + +var _ = f0[Sf] +var _ = f0t[Sf] + +var _ = f0[Sm /* ERROR does not implement */ ] +var _ = f0t[Sm /* ERROR does not implement */ ] + +func f1[P interface{ Sf; m() }](p P) { + _ = p.f + p.f = 0 + p.m() +} + +var _ = f1[Sf /* ERROR missing method m */ ] +var _ = f1[Sm /* ERROR does not implement */ ] + +type Sm struct {} + +func (Sm) m() {} + +type Sfm struct { + f int +} + +func (Sfm) m() {} + +func f2[P interface{ Sfm; m() }](p P) { + _ = p.f + p.f = 0 + p.m() +} + +var _ = f2[Sfm] + +// special case: structural type is a named pointer type + +type PSfm *Sfm + +func f3[P interface{ PSfm }](p P) { + _ = p.f + p.f = 0 + p.m /* ERROR type bound for P has no method m */ () +} + +var _ = f3[PSfm] |