From 67dd9ee92c454ded14f117e2d958db9ee56e8b02 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Mon, 22 Nov 2021 19:02:56 -0800 Subject: [PATCH] cmd/compile/internal/types2: produce empty type set for invalid ~T If ~T is not permitted because the underlying type of T is not the same as T, there is no type that satisfies ~T. Besides reporting an error, also ensure that the corresponding type set is empty. For #49739. Change-Id: I127f75f170902e7989f7fe7b352dabda9f72e2a5 Reviewed-on: https://go-review.googlesource.com/c/go/+/366278 Trust: Robert Griesemer Reviewed-by: Robert Findley --- .../types2/testdata/fixedbugs/issue49739.go2 | 23 +++++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 16 ++++++++----- 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 new file mode 100644 index 0000000000..46b1e71a3b --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue49739.go2 @@ -0,0 +1,23 @@ +// Copyright 2021 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. + +// Verify that we get an empty type set (not just an error) +// when using an invalid ~A. + +package p + +type A int +type C interface { + ~ /* ERROR invalid use of ~ */ A +} + +func f[_ C]() {} +func g[_ interface{ C }]() {} +func h[_ C | int]() {} + +func _() { + _ = f[int /* ERROR cannot implement C \(empty type set\) */] + _ = g[int /* ERROR cannot implement interface{C} \(empty type set\) */] + _ = h[int] +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 54a8266838..a55e9d1d63 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -367,14 +367,18 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet var allTerms termlist for _, t := range utyp.terms { var terms termlist - switch u := under(t.typ).(type) { - case *Interface: + u := under(t.typ) + if ui, _ := u.(*Interface); ui != nil { // For now we don't permit type parameters as constraints. assert(!isTypeParam(t.typ)) - terms = computeInterfaceTypeSet(check, pos, u).terms - default: - if t.typ == Typ[Invalid] { - continue + terms = computeInterfaceTypeSet(check, pos, ui).terms + } else if t.typ == Typ[Invalid] { + continue + } else { + if t.tilde && !Identical(t.typ, u) { + // There is no underlying type which is t.typ. + // The corresponding type set is empty. + t = nil // ∅ term } terms = termlist{(*term)(t)} }