From 9d46fe917af93e436b347abd44bd0879b8a87de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Tue, 6 Sep 2022 10:26:49 +0100 Subject: [PATCH] avoid a type assertion panic with generic code I was wrongly assumed that, if `used` has an `Elem` method, then `origin` must too. But it does not if it's a type parameter. Add a test case too, which panicked before the fix. Fixes #577. --- CHANGELOG.md | 2 ++ main.go | 9 +++++++-- testdata/scripts/typeparams.txt | 13 +++++++++++-- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5ec030..c2f05aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ This bugfix release continues support for Go 1.18 and 1.19. * Fix an edge case resulting in bad syntax due to comments - [#573] +* Avoid a panic involving generic code - [#577] ## [v0.7.1] - 2022-08-02 @@ -144,6 +145,7 @@ Known bugs: * `garble test` is temporarily disabled, as it is currently broken [#573]: https://github.com/burrowers/garble/issues/573 +[#577]: https://github.com/burrowers/garble/issues/577 [v0.7.1]: https://github.com/burrowers/garble/releases/tag/v0.7.1 diff --git a/main.go b/main.go index 74f8b99..fce82a0 100644 --- a/main.go +++ b/main.go @@ -1385,8 +1385,13 @@ func (tf *transformer) recordType(used, origin types.Type) { type Container interface{ Elem() types.Type } switch used := used.(type) { case Container: - origin := origin.(Container) - tf.recordType(used.Elem(), origin.Elem()) + // origin may be a *types.TypeParam, which is not a Container. + // For now, we haven't found a need to recurse in that case. + // We can edit this code in the future if we find an example, + // because we panic if a field is not in fieldToStruct. + if origin, ok := origin.(Container); ok { + tf.recordType(used.Elem(), origin.Elem()) + } case *types.Named: if tf.recordTypeDone[used] { return diff --git a/testdata/scripts/typeparams.txt b/testdata/scripts/typeparams.txt index 061495c..f2f9898 100644 --- a/testdata/scripts/typeparams.txt +++ b/testdata/scripts/typeparams.txt @@ -15,8 +15,11 @@ func main() { GenericFunc[int, int](1, 2) var _ GenericVector[int] - g := GenericGraph[string]{Content: "Foo"} - g.Edges = make([]GenericGraph[string], 1) + g1 := GenericGraph[string]{Content: "Foo"} + g1.Edges = make([]GenericGraph[string], 1) + + g2 := GenericGraph[*[]byte]{Content: new([]byte)} + g2.Edges = make([]GenericGraph[*[]byte], 1) } func GenericFunc[GenericParamA, B any](x GenericParamA, y B) {} @@ -44,3 +47,9 @@ type CombineEmbeds interface { interface { EmbeddedMethod() } RegularMethod() } + +type Slice[T any] []T + +func sliceOfPointer() Slice[*any] { + return []*any{} +}