Repository navigation
fix(compiler): keep the type arguments of generic function values - #530
Merged
paralin merged 1 commit intoOct 24, 2026
Merged
Conversation
A generic function instantiated with several type arguments and used as
a value, as in
sims := map[string]func(){"neuron": embed[Sim, Config]}
lowered to the bare function, so calling the value passed no type
arguments: its type parameters fell back to an empty interface, and
new(C) did not make a *Config, so asserting it to an interface that
*Config implements panicked. lowerIndexExpr already wrapped a function
instantiated with one type argument in lowerGenericFunctionValue;
lowerExpr lowered an IndexListExpr as its function alone.
Lower such an IndexListExpr with lowerGenericFunctionValue too. Since
calls do not pass type arguments to override functions that do not take
them, such as those of the slices override, lowerGenericFunctionValue
leaves those functions as their own values. Add a compliance test for
calls, variables and map values of generic functions.
Signed-off-by: Randall C. O'Reilly <oreilly@ucdavis.edu>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A generic function instantiated with several type arguments and used as a value lowered to the bare function, so calling the value passed no type arguments. For example, a site registers simulations as
and embed calls a function that does
cfg := any(new(C)).(Config). Called through the map, C fell back to an empty interface, new(C) did not make a *neuron.Config, and the assertion panicked with "inline type conversion panic: value is ..., not egui.Config". Called directly, the same instantiation worked.lowerIndexExpr already wraps a function instantiated with one type argument in lowerGenericFunctionValue, which binds the type arguments; lowerExpr lowered an IndexListExpr (two or more type arguments) as its function alone. This lowers such an IndexListExpr with lowerGenericFunctionValue too. Because calls pass no type arguments to override functions that do not take them (the slices override, for example), lowerGenericFunctionValue now leaves those functions as their own values, as the selector call path decides, so
slices.Index[[]int, int]as a value keeps working.The new compliance test generic_func_value_type_args covers calls, variables and map values of a two-parameter generic function, a single-parameter one, and a slices override function; no other compliance output changes. With this change the simulation pages of compcogneuro.org built with goscript load and run.
A related case is not covered here: a generic function used as a value with its type arguments inferred, as in
var f func(int) int = id, also lowers to the bare function. Fixing it means telling value uses from callees in lowerExpr, since several call paths lower their callee through it, so I left it for a separate change.