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

Calling a function literal associated with a function type breaks compilation #320

Closed
knieriem opened this issue May 2, 2019 · 3 comments

Comments

@knieriem
Copy link
Contributor

knieriem commented May 2, 2019

When trying to compile a program calling a function literal of a named type, like in this functional options example, tinygo stops compilation with a message like:

compiler/compiler.go:1341

panic: interface conversion: types.Type is *types.Named, not *types.Signature

It looks as if it is sufficient to call the Underlying method on the Named type before doing the type cast for *types.Signature, as in this patch:

--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -1338,7 +1338,11 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
 		}
 		// This is a func value, which cannot be called directly. We have to
 		// extract the function pointer and context first from the func value.
-		funcPtr, context, err := c.decodeFuncValue(value, instr.Value.Type().(*types.Signature))
+		t := instr.Value.Type()
+		if named, ok := t.(*types.Named); ok {
+			t = named.Underlying()
+		}
+		funcPtr, context, err := c.decodeFuncValue(value, t.(*types.Signature))
 		if err != nil {
 			return llvm.Value{}, err
 		}

I can send in a pull request if needed.

@aykevl
Copy link
Member

aykevl commented May 2, 2019

Thank you for the find! Yes, that's clearly a bug. There are probably a few of those left in the compiler but they can be hard to find unless someone stumbles on it. A patch would be appreciated.

But you can do this even simpler:

--- a/compiler/compiler.go
+++ b/compiler/compiler.go
@@ -1338,7 +1338,11 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
 		}
 		// This is a func value, which cannot be called directly. We have to
 		// extract the function pointer and context first from the func value.
-		funcPtr, context, err := c.decodeFuncValue(value, instr.Value.Type().(*types.Signature))
+		funcPtr, context, err := c.decodeFuncValue(value, instr.Value.Type().Underlying().(*types.Signature))
 		if err != nil {
 			return llvm.Value{}, err
 		}

Every type has an .Underlying() method, and for all types except for *types.Named it returns itself. So this is an easy way of stripping of named types, and is used in many other places in the compiler.

knieriem added a commit to knieriem/tinygo that referenced this issue May 3, 2019
When compiling a piece of code where a function value is called,
the compiler panics if the function value's type is a defined type,
and not just a type literal (function signature): The type assertion
(*types.Signature) fails, because the type of the func value is a
*types.Named.

This patch fixes this by using the type's underlying type, so that a
types.Named is properly turned into its underlying types.Signature,
before the type assertion takes place.
It takes advantage of the property that all types have an underlying type
(both are the same, if a type is not named).

Fixes tinygo-org#320
@knieriem
Copy link
Contributor Author

knieriem commented May 3, 2019

Thanks for pointing out the simplification.

@aykevl
Copy link
Member

aykevl commented May 5, 2019

The fix for this has been merged.

@aykevl aykevl closed this as completed May 5, 2019
directionless pushed a commit to directionless/tinygo that referenced this issue May 9, 2019
When compiling a piece of code where a function value is called,
the compiler panics if the function value's type is a defined type,
and not just a type literal (function signature): The type assertion
(*types.Signature) fails, because the type of the func value is a
*types.Named.

This patch fixes this by using the type's underlying type, so that a
types.Named is properly turned into its underlying types.Signature,
before the type assertion takes place.
It takes advantage of the property that all types have an underlying type
(both are the same, if a type is not named).

Fixes tinygo-org#320
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants