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

Crash with closure #774

Open
cpunion opened this issue Sep 6, 2024 · 1 comment · May be fixed by #775
Open

Crash with closure #774

cpunion opened this issue Sep 6, 2024 · 1 comment · May be fixed by #775
Labels
bug Something isn't working

Comments

@cpunion
Copy link
Contributor

cpunion commented Sep 6, 2024

package main

func Async[T any](fn func(resolve func(T))) func(func(T)) {
	return func(resolve func(T)) {
		fn(resolve)
	}
}

func ReadFile(fileName string) func(func(error)) {
	return Async(func(resolve func(error)) {
		resolve(nil)
	})
}

func main() {
	a := func(resolve func(error)) {
		println("resolve 1:", resolve)
		ReadFile("2.txt")(func(err error) {
			// println("resolve 2:", resolve) // DEBUG 1
			if err != nil {
				resolve(err)
				return
			}
			println("resolve 3:", resolve)
			ReadFile("3.txt")(func(err error) {
				println("resolve 4:", resolve)
				resolve(err)
			})
		})
	}

	a(func(err error) {
		println("done", err)
	})
}

When enable DEBUG 1, it run success and print same address. But when disable DEBUG 1, printed addresses changed and it crashed.

@cpunion
Copy link
Contributor Author

cpunion commented Sep 6, 2024

A simpler case without generic function also crashed:

package main

func main() {
	func(resolve func(error)) {
		func(err error) {
			if err != nil {
				resolve(err)
				return
			}
			resolve(nil)
		}(nil)
	}(func(err error) {
	})
}

Generates wrong LLVM-IR code:

define void @"main.main$1$1"(ptr %0, %"github.com/goplus/llgo/internal/runtime.iface" %1) {
_llgo_0:
  %2 = call ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface" %1)
  %3 = extractvalue %"github.com/goplus/llgo/internal/runtime.iface" %1, 1
  %4 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
  %5 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %4, i32 0, i32 0
  store ptr %2, ptr %5, align 8
  %6 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %4, i32 0, i32 1
  store ptr %3, ptr %6, align 8
  %7 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %4, align 8
  %8 = call ptr @"github.com/goplus/llgo/internal/runtime.IfaceType"(%"github.com/goplus/llgo/internal/runtime.iface" zeroinitializer)
  %9 = alloca %"github.com/goplus/llgo/internal/runtime.eface", align 8
  %10 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %9, i32 0, i32 0
  store ptr %8, ptr %10, align 8
  %11 = getelementptr inbounds %"github.com/goplus/llgo/internal/runtime.eface", ptr %9, i32 0, i32 1
  store ptr null, ptr %11, align 8
  %12 = load %"github.com/goplus/llgo/internal/runtime.eface", ptr %9, align 8
  %13 = call i1 @"github.com/goplus/llgo/internal/runtime.EfaceEqual"(%"github.com/goplus/llgo/internal/runtime.eface" %7, %"github.com/goplus/llgo/internal/runtime.eface" %12)
  %14 = xor i1 %13, true
  br i1 %14, label %_llgo_1, label %_llgo_2

_llgo_1:                                          ; preds = %_llgo_0
  %15 = load { ptr }, ptr %0, align 8
  %16 = extractvalue { ptr } %15, 0
  %17 = load { ptr, ptr }, ptr %16, align 8
  %18 = extractvalue { ptr, ptr } %17, 1
  %19 = extractvalue { ptr, ptr } %17, 0
  call void %19(ptr %18, %"github.com/goplus/llgo/internal/runtime.iface" zeroinitializer)
  ret void

_llgo_2:                                          ; preds = %_llgo_0
  %20 = extractvalue { ptr } %15, 0
  %21 = load { ptr, ptr }, ptr %20, align 8
  %22 = extractvalue { ptr, ptr } %21, 1
  %23 = extractvalue { ptr, ptr } %21, 0
  call void %23(ptr %22, %"github.com/goplus/llgo/internal/runtime.iface" zeroinitializer)
  ret void
}

%15 is initialized in _llgo_1 (if then branch), but used in _llgo_2 (else branch).

@visualfc visualfc linked a pull request Sep 6, 2024 that will close this issue
@xushiwei xushiwei added the bug Something isn't working label Sep 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants