Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime: endless traceback when panic in generics funtion #58513

Closed
SilverRainZ opened this issue Feb 14, 2023 · 8 comments
Closed

runtime: endless traceback when panic in generics funtion #58513

SilverRainZ opened this issue Feb 14, 2023 · 8 comments
Assignees
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Milestone

Comments

@SilverRainZ
Copy link
Contributor

What version of Go are you using (go version)?

$ go version
go version devel go1.21-261fe25c83 Sat Feb 11 16:16:34 2023 +0000 darwin/amd64
  • Introduced in 833367e (I found it by git bisect)
  • Still can be reproduced in 261fe25 (master)

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env

What did you do?

Run the following code:

package main

const (
	ALL = -1
)

type Iter[T any] interface {
	Next(n int) []T
}

type sliceIter[T any] struct {
	s []T
}

func (i *sliceIter[T]) Next(n int) []T {
	if n == ALL || n > len(i.s) {
		n = len(i.s)
	}
	next := make([]T, n)
	copy(next, i.s[:n])
	i.s = i.s[n:]
	return next
}

// FromSlice constructs an Iter from slice s, in order from left to right.
// An empty Iter (without element) is returned if the given slice is empty
// or nil.
func FromSlice[T any](s []T) Iter[T] {
	return &sliceIter[T]{s}
}

type mapIter[T1, T2 any] struct {
	f func(T1) T2
	i Iter[T1]
}

func (i *mapIter[T1, T2]) Next(n int) []T2 {
	vs := i.i.Next(n)
	if len(vs) == 0 {
		return nil
	}
	next := make([]T2, len(vs))
	for j := range next {
		next[j] = i.f(vs[j])
	}
	return next
}

// Map applies function f to each element of iterator i with Type T1.
// Results of f are returned as a new Iter with Type T2.
func Map[T1, T2 any](f func(T1) T2, i Iter[T1]) Iter[T2] {
	return &mapIter[T1, T2]{f, i}
}

// ToSlice collects elements of iterator to a slice.
//
// If the iterator is empty, empty slice []T{} is returned.
func ToSlice[T any](i Iter[T]) []T {
	all := i.Next(ALL)
	if all == nil {
		return []T{} // Always returns a slice
	} else {
		return all
	}
}

func typeAssert[To, From any](v From) To {
	return any(v).(To)
}

func TypeAssert[To, From any](i Iter[From]) Iter[To] {
	return Map(typeAssert[To, From], i)
}

func main() {
	_ = ToSlice(
		TypeAssert[string](
			FromSlice([]int{1})))
}

What did you expect to see?

Program panics and exits. Output by go1.19.4:

$ go run main.go
panic: interface conversion: interface {} is int, not string

goroutine 1 [running]:
main.typeAssert[...](...)
        /Users/bytedance/workspace/traceback/main.go:68
main.(*mapIter[...]).Next(0xc000090018?, 0xc00004e701)
        /Users/bytedance/workspace/traceback/main.go:44 +0x92
main.ToSlice[...]({0x107b8e8?, 0xc000090018?})
        /Users/bytedance/workspace/traceback/main.go:59 +0x2e
main.main()
        /Users/bytedance/workspace/traceback/main.go:76 +0x69
exit status 2

What did you see instead?

Program panics as expected, but print stack endlessly.

$ ~/git/go/bin/go run main.go
panic: interface conversion: interface {} is int, not string

goroutine 1 [running]:
main.typeAssert[...](0xc00001c001?)
	/Users/bytedance/workspace/traceback/main.go:68 +0x45
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
	/Users/bytedance/workspace/traceback/main.go:72
main.TypeAssert[...](...)
@gopherbot gopherbot added the compiler/runtime Issues related to the Go compiler and/or runtime. label Feb 14, 2023
@ianlancetaylor
Copy link
Contributor

CC @golang/runtime @mdempsky

@mdempsky mdempsky self-assigned this Feb 14, 2023
@mdempsky
Copy link
Member

I think this is #54625.

@mdempsky
Copy link
Member

Minimized test case:

package main

func assert[To any](v any) {
	_ = v.(To)
}

func Assert[To any]() func(any) {
	return assert[To]
}

func main() {
	var fn func(any)
	fn = Assert[string]()
	fn(1)
}

I'm beginning to suspect this is instead another instance of #46234, but for the synthetic function literals that the unified frontend generates in some cases.

@mdempsky
Copy link
Member

Extending the same kludge from 6a801d3 to synthetic closures fixes the issue. That's probably the easiest solution for backporting to 1.20.

@gopherbot Please backport to Go 1.20.

@gopherbot
Copy link

Backport issue(s) opened: #58531 (for 1.20).

Remember to create the cherry-pick CL(s) as soon as the patch is submitted to master, according to https://go.dev/wiki/MinorReleases.

@gopherbot
Copy link

Change https://go.dev/cl/468415 mentions this issue: cmd/compile/internal/noder: correct positions for synthetic closures

@gopherbot
Copy link

Change https://go.dev/cl/468435 mentions this issue: go/ssa: skip typeparam/issue58513.go

gopherbot pushed a commit to golang/tools that referenced this issue Feb 15, 2023
This test case needs to check that the runtime is able to correctly
unwind the call stack, and it uses runtime.Caller for that. However,
this isn't implemented by go/ssa/interp, so it needs to be skipped.
(It's an issue that's fairly specific to how inlining works too, so
unlikely to matter to go/ssa/interp anyway.)

While here, it looks like issue376214.go is now working, so enable
that test too.

Updates golang/go#58513.

Change-Id: I3fa87c77542d85e0e5ce42c2f6d4c451700268cd
Reviewed-on: https://go-review.googlesource.com/c/tools/+/468435
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Tim King <taking@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
@gopherbot
Copy link

Change https://go.dev/cl/468675 mentions this issue: go/ssa/interp: skip typeparam/issue58513.go

gopherbot pushed a commit to golang/tools that referenced this issue Feb 15, 2023
Addendum to go.dev/cl/468435.

Updates golang/go#58513.

Change-Id: Ia8f146580cd51ba0796142c7cd700a65891d1e55
Reviewed-on: https://go-review.googlesource.com/c/tools/+/468675
Reviewed-by: Robert Findley <rfindley@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
Auto-Submit: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
@mknyszek mknyszek added this to the Go1.21 milestone Feb 22, 2023
@mknyszek mknyszek added the NeedsFix The path to resolution is known, but the work has not been done. label Feb 22, 2023
@golang golang locked and limited conversation to collaborators Feb 27, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
compiler/runtime Issues related to the Go compiler and/or runtime. FrozenDueToAge NeedsFix The path to resolution is known, but the work has not been done.
Projects
None yet
Development

No branches or pull requests

5 participants