From 560dc9712d4bc900b5ab32b518ba4de2a9bc588c Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 15 Nov 2021 10:01:43 -0800 Subject: [PATCH] cmd/compile: error when using internal type declarations in generic functions We hope to support this feature one day, but it doesn't work currently. Issue a nice error message instead of having the compiler crash. Update #47631 Change-Id: I0359411410acbaf9a5b9dbb988cd933de1bb8438 Reviewed-on: https://go-review.googlesource.com/c/go/+/364054 Trust: Keith Randall Trust: Dan Scales Run-TryBot: Keith Randall TryBot-Result: Go Bot Reviewed-by: Dan Scales --- src/cmd/compile/internal/noder/stmt.go | 4 +++ test/run.go | 1 + test/typeparam/builtins.go | 13 +++++----- test/typeparam/issue47631.go | 34 ++++++++++++++++++++++++++ test/typeparam/typelist.go | 3 ++- 5 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 test/typeparam/issue47631.go diff --git a/src/cmd/compile/internal/noder/stmt.go b/src/cmd/compile/internal/noder/stmt.go index aedb09e21ee..e329a591566 100644 --- a/src/cmd/compile/internal/noder/stmt.go +++ b/src/cmd/compile/internal/noder/stmt.go @@ -46,6 +46,10 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node { n.SetTypecheck(1) return n case *syntax.DeclStmt: + if _, ok := stmt.DeclList[0].(*syntax.TypeDecl); ok && g.topFuncIsGeneric { + // TODO: remove this restriction. See issue 47631. + base.ErrorfAt(g.pos(stmt), "type declarations inside generic functions are not currently supported") + } n := ir.NewBlockStmt(g.pos(stmt), nil) g.decls(&n.List, stmt.DeclList) return n diff --git a/test/run.go b/test/run.go index ad64304ec8a..bdc2f0a2777 100644 --- a/test/run.go +++ b/test/run.go @@ -2186,6 +2186,7 @@ var unifiedFailures = setOf( "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape" "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap" "typeparam/issue48538.go", // assertion failure, interprets struct key as closure variable + "typeparam/issue47631.go", // unified IR can handle local type declarations ) func setOf(keys ...string) map[string]bool { diff --git a/test/typeparam/builtins.go b/test/typeparam/builtins.go index 844cdae8ab3..73dda77e0ec 100644 --- a/test/typeparam/builtins.go +++ b/test/typeparam/builtins.go @@ -69,24 +69,25 @@ func m1[ C1 interface{ chan int }, C2 interface{ chan int | chan string }, ]() { - type S0 []int _ = make([]int, 10) - _ = make(S0, 10) + _ = make(m1S0, 10) _ = make(S1, 10) _ = make(S1, 10, 20) - type M0 map[string]int _ = make(map[string]int) - _ = make(M0) + _ = make(m1M0) _ = make(M1) _ = make(M1, 10) - type C0 chan int _ = make(chan int) - _ = make(C0) + _ = make(m1C0) _ = make(C1) _ = make(C1, 10) } +// TODO: put these type declarations back inside m1 when issue 47631 is fixed. +type m1S0 []int +type m1M0 map[string]int +type m1C0 chan int // len/cap diff --git a/test/typeparam/issue47631.go b/test/typeparam/issue47631.go new file mode 100644 index 00000000000..7f7cfa6abba --- /dev/null +++ b/test/typeparam/issue47631.go @@ -0,0 +1,34 @@ +// errorcheck -G=3 + +// 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. + +// TODO: one day we will support internal type declarations, at which time this test will be removed. + +package p + +func g[T any]() { + type U []T // ERROR "type declarations inside generic functions are not currently supported" + type V []int // ERROR "type declarations inside generic functions are not currently supported" +} + +type S[T any] struct { +} + +func (s S[T]) m() { + type U []T // ERROR "type declarations inside generic functions are not currently supported" + type V []int // ERROR "type declarations inside generic functions are not currently supported" +} + + +func f() { + type U []int // ok +} + +type X struct { +} + +func (x X) m() { + type U []int // ok +} diff --git a/test/typeparam/typelist.go b/test/typeparam/typelist.go index 8d6a228de55..34ea4b8aa99 100644 --- a/test/typeparam/typelist.go +++ b/test/typeparam/typelist.go @@ -26,11 +26,12 @@ func at[T interface{ ~[]E }, E any](x T, i int) E { // type is itself, its "operational type" is defined by the type list in // the tybe bound, if any. func _[T interface{ ~int }](x T) { - type myint int var _ int = int(x) var _ T = 42 var _ T = T(myint(42)) } +// TODO: put this type declaration back inside the above function when issue 47631 is fixed. +type myint int // Indexing a generic type which has a structural contraints to be an array. func _[T interface{ ~[10]int }](x T) {