Skip to content

compiler: interface typecodes are not passed through defer frames #1033

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

Closed
asdine opened this issue Apr 7, 2020 · 3 comments
Closed

compiler: interface typecodes are not passed through defer frames #1033

asdine opened this issue Apr 7, 2020 · 3 comments
Labels
bug Something isn't working
Milestone

Comments

@asdine
Copy link

asdine commented Apr 7, 2020

I encountered a really weird compilation error, I tried to simplify the code to find the root cause and this is the best I could do:

package main

func main() {
	foo(nil)
}

type Bar struct {
	empty bool
}

func (b *Bar) Close() error {
	return nil
}

type Closer interface {
	Close() error
}

func foo(bar *Bar) error {
	var a int
	// replacing this condition with something simpler (i.e. nb > 10)
	// works fine
	if !bar.empty {
		a = 10
		// this inner branching is important
		if a != 5 {
			return nil
		}
	}

	var c Closer = bar
	// calling defer on an interface method + the branching above causes the bug
	// Replacing this line by func() { b.Close() }() works though
	defer c.Close()

	return nil
}

This causes the following compilation error:

Instruction does not dominate all uses!
  %3 = insertvalue %runtime._interface { i32 ptrtoint (%runtime.typeInInterface* @"typeInInterface:reflect/types.type:pointer:named:exp.Bar" to i32), i8* undef }, i8* %pack.ptr, 1
  %invoke.typecode16 = extractvalue %runtime._interface %3, 0
Instruction does not dominate all uses!
  %3 = insertvalue %runtime._interface { i32 ptrtoint (%runtime.typeInInterface* @"typeInInterface:reflect/types.type:pointer:named:exp.Bar" to i32), i8* undef }, i8* %pack.ptr, 1
  %invoke.func.receiver19 = extractvalue %runtime._interface %3, 1
error: verification error after IR construction

I compiled to wasm using the 0.12.0 docker image with the following params:

docker run ... \
    tinygo/tinygo:0.12.0 tinygo build -o /dist/exp.wasm -target wasm --no-debug exp
@niaow
Copy link
Member

niaow commented Apr 7, 2020

So, it appears that the IR generation for defer is attempting to extract the interface type directly from the source, rather than passing it through the defer frame. This can also be problematic if the defer is in a loop, in which case it could be tricked into interpreting with the wrong type.

@niaow niaow changed the title Compilation error when combining branching and defer on interfaces compiler: interface/function values are not passed through defer frames Apr 8, 2020
@niaow niaow added this to the v0.14 milestone Apr 8, 2020
@niaow
Copy link
Member

niaow commented Apr 8, 2020

v0.13 is getting close to release, so the fix is probably going to have to be pushed back into the next release window.

@niaow niaow added the bug Something isn't working label Apr 8, 2020
@niaow niaow changed the title compiler: interface/function values are not passed through defer frames compiler: interface values are not passed through defer frames Apr 8, 2020
@niaow niaow changed the title compiler: interface values are not passed through defer frames compiler: interface typecodes are not passed through defer frames Apr 8, 2020
@niaow
Copy link
Member

niaow commented Apr 9, 2020

The bug fix was merged and will be included in the next release (v0.13).

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

No branches or pull requests

2 participants