From 54ad7f33e4981a87bdd7dfac4d61ac5d21e195c3 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 18 Oct 2022 11:12:48 -0700 Subject: [PATCH] go/types, types2: add test verifying types/values of type parameter "constants" Fixes #51093. Change-Id: Ida4025a125243159a2107dcc064a0d9addf0a675 Reviewed-on: https://go-review.googlesource.com/c/go/+/443756 Run-TryBot: Robert Griesemer Auto-Submit: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer --- .../compile/internal/types2/issues_test.go | 53 +++++++++++++++++++ src/go/types/issues_test.go | 53 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go index efd27bf7cc..afce7e2715 100644 --- a/src/cmd/compile/internal/types2/issues_test.go +++ b/src/cmd/compile/internal/types2/issues_test.go @@ -673,3 +673,56 @@ func TestIssue55030(t *testing.T) { makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u}))) } } + +func TestIssue51093(t *testing.T) { + // Each test stands for a conversion of the form P(val) + // where P is a type parameter with typ as constraint. + // The test ensures that P(val) has the correct type P + // and is not a constant. + var tests = []struct { + typ string + val string + }{ + {"bool", "false"}, + {"int", "-1"}, + {"uint", "1.0"}, + {"rune", "'a'"}, + {"float64", "3.5"}, + {"complex64", "1.25"}, + {"string", "\"foo\""}, + + // some more complex constraints + {"~byte", "1"}, + {"~int | ~float64 | complex128", "1"}, + {"~uint64 | ~rune", "'X'"}, + } + + for _, test := range tests { + src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val) + types := make(map[syntax.Expr]TypeAndValue) + mustTypecheck(t, "p", src, &Info{Types: types}) + + var n int + for x, tv := range types { + if x, _ := x.(*syntax.CallExpr); x != nil { + // there must be exactly one CallExpr which is the P(val) conversion + n++ + tpar, _ := tv.Type.(*TypeParam) + if tpar == nil { + t.Fatalf("%s: got type %s, want type parameter", syntax.String(x), tv.Type) + } + if name := tpar.Obj().Name(); name != "P" { + t.Fatalf("%s: got type parameter name %s, want P", syntax.String(x), name) + } + // P(val) must not be constant + if tv.Value != nil { + t.Errorf("%s: got constant value %s (%s), want no constant", syntax.String(x), tv.Value, tv.Value.String()) + } + } + } + + if n != 1 { + t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1) + } + } +} diff --git a/src/go/types/issues_test.go b/src/go/types/issues_test.go index de8e0ad5f1..b96f68d575 100644 --- a/src/go/types/issues_test.go +++ b/src/go/types/issues_test.go @@ -702,3 +702,56 @@ func TestIssue55030(t *testing.T) { makeSig(NewTypeParam(P, NewInterfaceType(nil, []Type{u}))) } } + +func TestIssue51093(t *testing.T) { + // Each test stands for a conversion of the form P(val) + // where P is a type parameter with typ as constraint. + // The test ensures that P(val) has the correct type P + // and is not a constant. + var tests = []struct { + typ string + val string + }{ + {"bool", "false"}, + {"int", "-1"}, + {"uint", "1.0"}, + {"rune", "'a'"}, + {"float64", "3.5"}, + {"complex64", "1.25"}, + {"string", "\"foo\""}, + + // some more complex constraints + {"~byte", "1"}, + {"~int | ~float64 | complex128", "1"}, + {"~uint64 | ~rune", "'X'"}, + } + + for _, test := range tests { + src := fmt.Sprintf("package p; func _[P %s]() { _ = P(%s) }", test.typ, test.val) + types := make(map[ast.Expr]TypeAndValue) + mustTypecheck(t, "p", src, &Info{Types: types}) + + var n int + for x, tv := range types { + if x, _ := x.(*ast.CallExpr); x != nil { + // there must be exactly one CallExpr which is the P(val) conversion + n++ + tpar, _ := tv.Type.(*TypeParam) + if tpar == nil { + t.Fatalf("%s: got type %s, want type parameter", ExprString(x), tv.Type) + } + if name := tpar.Obj().Name(); name != "P" { + t.Fatalf("%s: got type parameter name %s, want P", ExprString(x), name) + } + // P(val) must not be constant + if tv.Value != nil { + t.Errorf("%s: got constant value %s (%s), want no constant", ExprString(x), tv.Value, tv.Value.String()) + } + } + } + + if n != 1 { + t.Fatalf("%s: got %d CallExpr nodes; want 1", src, 1) + } + } +}