diff options
author | Robert Griesemer <gri@golang.org> | 2022-04-20 22:19:49 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2022-05-03 14:51:51 +0000 |
commit | 920b9ab57dc6be573e8da705f13cf17ebab65342 (patch) | |
tree | 11b807db5976b5ab6f6c7a82b305cb4cd959b963 /src/cmd/compile/internal/syntax/printer_test.go | |
parent | 3e00bd0ae4482064aa9eac0695078b1096ee913a (diff) | |
download | go-git-920b9ab57dc6be573e8da705f13cf17ebab65342.tar.gz |
cmd/compile/internal/syntax: accept all valid type parameter lists
Type parameter lists starting with the form [name *T|...] or
[name (X)|...] may look like an array length expression [x].
Only after parsing the entire initial expression and checking
whether the expression contains type elements or is followed
by a comma can we make the final decision.
This change simplifies the existing parsing strategy: instead
of trying to make an upfront decision with limited information
(which is insufficient), the parser now parses the start of a
type parameter list or array length specification as expression.
In a second step, if the expression can be split into a name
followed by a type element, or a name followed by an ordinary
expression which is succeeded by a comma, we assume a type
parameter list (because it can't be an array length).
In all other cases we assume an array length specification.
Fixes #49482.
Change-Id: I269b6291999bf60dc697d33d24a5635f01e065b9
Reviewed-on: https://go-review.googlesource.com/c/go/+/402256
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/syntax/printer_test.go')
-rw-r--r-- | src/cmd/compile/internal/syntax/printer_test.go | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/src/cmd/compile/internal/syntax/printer_test.go b/src/cmd/compile/internal/syntax/printer_test.go index 3eca2316a7..25155e5cc6 100644 --- a/src/cmd/compile/internal/syntax/printer_test.go +++ b/src/cmd/compile/internal/syntax/printer_test.go @@ -57,11 +57,12 @@ var stringTests = [][2]string{ dup("package p"), dup("package p; type _ int; type T1 = struct{}; type ( _ *struct{}; T2 = float32 )"), - // generic type declarations + // generic type declarations (given type separated with blank from LHS) dup("package p; type _[T any] struct{}"), dup("package p; type _[A, B, C interface{m()}] struct{}"), dup("package p; type _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}] struct{}"), + dup("package p; type _[P *struct{}] struct{}"), dup("package p; type _[P *T,] struct{}"), dup("package p; type _[P *T, _ any] struct{}"), {"package p; type _[P (*T),] struct{}", "package p; type _[P *T,] struct{}"}, @@ -69,36 +70,56 @@ var stringTests = [][2]string{ {"package p; type _[P (T),] struct{}", "package p; type _[P T] struct{}"}, {"package p; type _[P (T), _ any] struct{}", "package p; type _[P T, _ any] struct{}"}, - dup("package p; type _[P *struct{}] struct{}"), {"package p; type _[P (*struct{})] struct{}", "package p; type _[P *struct{}] struct{}"}, {"package p; type _[P ([]int)] struct{}", "package p; type _[P []int] struct{}"}, - - dup("package p; type _ [P(T)]struct{}"), - dup("package p; type _ [P((T))]struct{}"), - dup("package p; type _ [P * *T]struct{}"), - dup("package p; type _ [P * T]struct{}"), - dup("package p; type _ [P(*T)]struct{}"), - dup("package p; type _ [P(**T)]struct{}"), - dup("package p; type _ [P * T - T]struct{}"), - - // array type declarations - dup("package p; type _ [P * T]struct{}"), - dup("package p; type _ [P * T - T]struct{}"), + {"package p; type _[P ([]int) | int] struct{}", "package p; type _[P []int | int] struct{}"}, + + // a type literal in an |-expression indicates a type parameter list (blank after type parameter list and type) + dup("package p; type _[P *[]int] struct{}"), + dup("package p; type _[P *T | T, Q T] struct{}"), + dup("package p; type _[P *[]T | T] struct{}"), + dup("package p; type _[P *T | T | T | T | ~T] struct{}"), + dup("package p; type _[P *T | T | T | ~T | T] struct{}"), + dup("package p; type _[P *T | T | struct{} | T] struct{}"), + dup("package p; type _[P <-chan int] struct{}"), + dup("package p; type _[P *T | struct{} | T] struct{}"), + + // a trailing comma always indicates a type parameter list (blank after type parameter list and type) + dup("package p; type _[P *T,] struct{}"), + dup("package p; type _[P *T | T,] struct{}"), + dup("package p; type _[P *T | <-T | T,] struct{}"), + + // slice/array type declarations (no blank between array length and element type) + dup("package p; type _ []byte"), + dup("package p; type _ [n]byte"), + dup("package p; type _ [P(T)]byte"), + dup("package p; type _ [P((T))]byte"), + dup("package p; type _ [P * *T]byte"), + dup("package p; type _ [P * T]byte"), + dup("package p; type _ [P(*T)]byte"), + dup("package p; type _ [P(**T)]byte"), + dup("package p; type _ [P * T - T]byte"), + dup("package p; type _ [P * T - T]byte"), + dup("package p; type _ [P * T | T]byte"), + dup("package p; type _ [P * T | <-T | T]byte"), // generic function declarations dup("package p; func _[T any]()"), dup("package p; func _[A, B, C interface{m()}]()"), dup("package p; func _[T any, A, B, C interface{m()}, X, Y, Z interface{~int}]()"), + // generic functions with elided interfaces in type constraints + dup("package p; func _[P *T]() {}"), + dup("package p; func _[P *T | T | T | T | ~T]() {}"), + dup("package p; func _[P *T | T | struct{} | T]() {}"), + dup("package p; func _[P ~int, Q int | string]() {}"), + dup("package p; func _[P struct{f int}, Q *P]() {}"), + // methods with generic receiver types dup("package p; func (R[T]) _()"), dup("package p; func (*R[A, B, C]) _()"), dup("package p; func (_ *R[A, B, C]) _()"), - // type constraint literals with elided interfaces - dup("package p; func _[P ~int, Q int | string]() {}"), - dup("package p; func _[P struct{f int}, Q *P]() {}"), - // channels dup("package p; type _ chan chan int"), dup("package p; type _ chan (<-chan int)"), |