From: Robert Griesemer Date: Fri, 19 Oct 2018 04:21:46 +0000 (-0700) Subject: go/types: collect type info for type ...T in variadic functions X-Git-Tag: go1.12beta1~713 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0287d8ed1b12229f2ab493602ffa497caabf747c;p=gostls13.git go/types: collect type info for type ...T in variadic functions Because the code type-checks T rather than ...T (and then corrects the type to []T "manually"), it didn't automatically record the type for the ast.Expr corresponding to ...T. Do it manually. Fixes #28277. Change-Id: I3d9aae310c90b01f52d189e70c48dd9007f72207 Reviewed-on: https://go-review.googlesource.com/c/143317 Reviewed-by: Alan Donovan --- diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index c34ecbf9d1..85de9f6079 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -257,6 +257,16 @@ func TestTypesInfo(t *testing.T) { `(string, bool)`, }, + // issue 28277 + {`package issue28277_a; func f(...int)`, + `...int`, + `[]int`, + }, + {`package issue28277_b; func f(a, b, c ...[]struct{})`, + `...[]struct{}`, + `[][]struct{}`, + }, + // tests for broken code that doesn't parse or type-check {`package x0; func _() { var x struct {f string}; x.f := 0 }`, `x.f`, `string`}, {`package x1; func _() { var z string; type x struct {f string}; y := &x{q: z}}`, `z`, `string`}, @@ -389,6 +399,8 @@ func TestPredicatesInfo(t *testing.T) { {`package t0; type _ int`, `int`, `type`}, {`package t1; type _ []int`, `[]int`, `type`}, {`package t2; type _ func()`, `func()`, `type`}, + {`package t3; type _ func(int)`, `int`, `type`}, + {`package t3; type _ func(...int)`, `...int`, `type`}, // built-ins {`package b0; var _ = len("")`, `len`, `builtin`}, diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index e6d61b7ec7..8512ca1b80 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -451,9 +451,12 @@ func (check *Checker) collectParams(scope *Scope, list *ast.FieldList, variadicO } // For a variadic function, change the last parameter's type from T to []T. - if variadic && len(params) > 0 { + // Since we type-checked T rather than ...T, we also need to retro-actively + // record the type for ...T. + if variadic { last := params[len(params)-1] last.typ = &Slice{elem: last.typ} + check.recordTypeAndValue(list.List[len(list.List)-1].Type, typexpr, last.typ, nil) } return