Skip to content

Commit 3357624

Browse files
committed
cmd/compile/internal/types2: mark implicit interfaces as such
Provide an accessor for clients, and don't print the interface around implicitly wrapped embedded types. For #48424. Change-Id: Ib2c76315508fc749ea4337d52e13d17de80e04da Reviewed-on: https://go-review.googlesource.com/c/go/+/353396 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
1 parent 952df98 commit 3357624

File tree

6 files changed

+32
-9
lines changed

6 files changed

+32
-9
lines changed

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -652,11 +652,12 @@ func (check *Checker) bound(x syntax.Expr) Type {
652652
// embed it in an implicit interface so that only interface type-checking
653653
// needs to take care of such type expressions.
654654
if op, _ := x.(*syntax.Operation); op != nil && (op.Op == syntax.Tilde || op.Op == syntax.Or) {
655-
// TODO(gri) Should mark this interface as "implicit" somehow
656-
// (and propagate the info to types2.Interface) so
657-
// that we can elide the interface again in error
658-
// messages. Could use a sentinel name for the field.
659-
x = &syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}}
655+
t := check.typ(&syntax.InterfaceType{MethodList: []*syntax.Field{{Type: x}}})
656+
// mark t as implicit interface if all went well
657+
if t, _ := t.(*Interface); t != nil {
658+
t.implicit = true
659+
}
660+
return t
660661
}
661662
return check.typ(x)
662663
}

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ type Interface struct {
1616
methods []*Func // ordered list of explicitly declared methods
1717
embeddeds []Type // ordered list of explicitly embedded elements
1818
embedPos *[]syntax.Pos // positions of embedded elements; or nil (for error messages) - use pointer to save space
19+
implicit bool // interface is wrapper for type set literal (non-interface T, ~T, or A|B)
1920
complete bool // indicates that all fields (except for tset) are set up
2021

2122
tset *_TypeSet // type set described by this interface, computed lazily
@@ -82,6 +83,9 @@ func (t *Interface) IsComparable() bool { return t.typeSet().IsComparable() }
8283
// IsMethodSet reports whether the interface t is fully described by its method set.
8384
func (t *Interface) IsMethodSet() bool { return t.typeSet().IsMethodSet() }
8485

86+
// IsImplicit reports whether the interface t is a wrapper for a type set literal.
87+
func (t *Interface) IsImplicit() bool { return t.implicit }
88+
8589
func (t *Interface) Underlying() Type { return t }
8690
func (t *Interface) String() string { return TypeString(t, nil) }
8791

@@ -102,7 +106,6 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType
102106

103107
for _, f := range iface.MethodList {
104108
if f.Name == nil {
105-
// We have an embedded type; possibly a union of types.
106109
addEmbedded(posFor(f.Type), parseUnion(check, flattenUnion(nil, f.Type)))
107110
continue
108111
}

src/cmd/compile/internal/types2/testdata/examples/typesets.go2

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,13 @@ func _() *int {
4646
// A type parameter may not be embedded in an interface;
4747
// so it can also not be used as a constraint.
4848
func _[A any, B A /* ERROR cannot use a type parameter as constraint */ ]() {}
49+
50+
// Error messages refer to the type constraint as it appears in the source.
51+
// (No implicit interface should be exposed.)
52+
func _[T string](x T) T {
53+
return x /* ERROR constrained by string */ * x
54+
}
55+
56+
func _[T int|string](x T) T {
57+
return x /* ERROR constrained by int|string */ * x
58+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ func (t *TypeParam) iface() *Interface {
100100
}
101101

102102
// If we don't have an interface, wrap constraint into an implicit interface.
103-
// TODO(gri) mark it as implicit - see comment in Checker.bound
104103
if ityp == nil {
105104
ityp = NewInterfaceType(nil, []Type{bound})
105+
ityp.implicit = true
106106
t.bound = ityp // update t.bound for next time (optimization)
107107
}
108108

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,15 @@ func (w *typeWriter) typ(typ Type) {
190190
}
191191

192192
case *Interface:
193+
if t.implicit {
194+
if len(t.methods) == 0 && len(t.embeddeds) == 1 {
195+
w.typ(t.embeddeds[0])
196+
break
197+
}
198+
// Something's wrong with the implicit interface.
199+
// Print it as such and continue.
200+
w.string("/* implicit */ ")
201+
}
193202
w.string("interface{")
194203
first := true
195204
for _, m := range t.methods {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ func defPredeclaredTypes() {
8888
res := NewVar(nopos, nil, "", Typ[String])
8989
sig := NewSignatureType(nil, nil, nil, nil, NewTuple(res), false)
9090
err := NewFunc(nopos, nil, "Error", sig)
91-
ityp := &Interface{nil, obj, []*Func{err}, nil, nil, true, nil}
91+
ityp := &Interface{nil, obj, []*Func{err}, nil, nil, false, true, nil}
9292
computeInterfaceTypeSet(nil, nopos, ityp) // prevent races due to lazy computation of tset
9393
typ := NewNamed(obj, ityp, nil)
9494
sig.recv = NewVar(nopos, nil, "", typ)
@@ -99,7 +99,7 @@ func defPredeclaredTypes() {
9999
{
100100
obj := NewTypeName(nopos, nil, "comparable", nil)
101101
obj.setColor(black)
102-
ityp := &Interface{nil, obj, nil, nil, nil, true, &_TypeSet{true, nil, allTermlist}}
102+
ityp := &Interface{nil, obj, nil, nil, nil, false, true, &_TypeSet{true, nil, allTermlist}}
103103
NewNamed(obj, ityp, nil)
104104
def(obj)
105105
}

0 commit comments

Comments
 (0)