@@ -313,15 +313,15 @@ func (fc *funcContext) newVarDecl(init *types.Initializer) *Decl {
313313 return d
314314}
315315
316- // funcDecls translates all package-level function and methods.
317- //
318- // `functions` must contain all package-level function and method declarations
319- // found in the AST. The function returns Decls that define corresponding JS
320- // functions at runtime. For special functions like init() and main() decls will
321- // also contain code necessary to invoke them.
322- func ( fc * funcContext ) funcDecls ( functions [] * ast. FuncDecl ) ([] * Decl , error ) {
323- var funcDecls [] * Decl
324- var mainFunc * types. Func
316+ type funcGroup struct {
317+ fun * ast. FuncDecl
318+ o * types. Func
319+ instances []typeparams. Instance
320+ }
321+
322+ // groupFuncDecls groups all the package-level function and methods
323+ // into generic or non-generic groups.
324+ func ( fc * funcContext ) groupFuncDecls ( functions [] * ast. FuncDecl ) ( mainFunc * funcGroup , fns , expGenFns [] * funcGroup ) {
325325 for _ , fun := range functions {
326326 o := fc .pkgCtx .Defs [fun .Name ].(* types.Func )
327327 instances := fc .knownInstances (o )
@@ -330,29 +330,50 @@ func (fc *funcContext) funcDecls(functions []*ast.FuncDecl) ([]*Decl, error) {
330330 continue
331331 }
332332
333- if fun .Recv == nil {
334- // Auxiliary decl shared by all instances of the function that defines
335- // package-level variable by which they all are referenced,
336- // e.g. init functions and instances of generic functions.
337- funcDecls = append (funcDecls , fc .newFuncVarDecl (fun , o , instances ))
333+ fg := & funcGroup {
334+ fun : fun ,
335+ o : o ,
336+ instances : instances ,
338337 }
339338
340- for _ , inst := range instances {
341- funcDecls = append (funcDecls , fc .newFuncDecl (fun , inst ))
339+ generic := len (instances ) > 1 || ! instances [0 ].IsTrivial ()
340+ if generic && fun .Name .IsExported () {
341+ // function is an exported generic function so it must be processed later
342+ // since it may have instances with type arguments from packages depending
343+ // on the current package.
344+ expGenFns = append (expGenFns , fg )
345+ continue
342346 }
343347
344- if o .Name () == "main" {
345- mainFunc = o // main() function candidate.
348+ fns = append (fns , fg )
349+
350+ if fg .o .Name () == "main" {
351+ mainFunc = fg // main() function candidate.
346352 }
347353 }
348- if fc .pkgCtx .isMain () {
349- if mainFunc == nil {
350- return nil , fmt .Errorf ("missing main function" )
354+
355+ return mainFunc , fns , expGenFns
356+ }
357+
358+ // funcDecls translates all package-level function and methods.
359+ //
360+ // `functions` must contain all package-level function and method declarations
361+ // found in the AST. The function returns Decls that define corresponding JS
362+ // functions at runtime. For special functions like init() and main() decls will
363+ // also contain code necessary to invoke them.
364+ func (fc * funcContext ) funcDecls (functions []* funcGroup ) ([]* Decl , error ) {
365+ var funcDecls []* Decl
366+ for _ , fg := range functions {
367+ if fg .fun .Recv == nil {
368+ // Auxiliary decl shared by all instances of the function that defines
369+ // package-level variable by which they all are referenced,
370+ // e.g. init functions and instances of generic functions.
371+ funcDecls = append (funcDecls , fc .newFuncVarDecl (fg .fun , fg .o , fg .instances ))
372+ }
373+
374+ for _ , inst := range fg .instances {
375+ funcDecls = append (funcDecls , fc .newFuncDecl (fg .fun , inst ))
351376 }
352- // Add a special Decl for invoking main() function after the program has
353- // been initialized. It must come after all other functions, especially all
354- // init() functions, otherwise main() will be invoked too early.
355- funcDecls = append (funcDecls , fc .newCallMainFuncDecl (mainFunc ))
356377 }
357378 return funcDecls , nil
358379}
@@ -479,6 +500,36 @@ func (fc *funcContext) callMainFunc(main *types.Func) ast.Stmt {
479500 return ifStmt
480501}
481502
503+ func (fc * funcContext ) groupNamedTypeDecls (typeNames typesutil.TypeNames ) (typs , expGenTyps typesutil.TypeNames ) {
504+ if ! fc .isRoot () {
505+ panic (bailout (fmt .Errorf ("functionContext.groupNamedTypeDecls() must be only called on the package-level context" )))
506+ }
507+
508+ for _ , o := range typeNames .Slice () {
509+ if o .IsAlias () {
510+ continue
511+ }
512+
513+ instances := fc .knownInstances (o )
514+ if len (instances ) == 0 {
515+ // No instances of the type, skip it.
516+ continue
517+ }
518+
519+ generic := len (instances ) > 1 || ! instances [0 ].IsTrivial ()
520+ if generic && o .Exported () {
521+ // type is an exported generic type so it must be processed later
522+ // since it may have instances with type arguments from packages depending
523+ // on the current package.
524+ expGenTyps .Add (o )
525+ continue
526+ }
527+
528+ typs .Add (o )
529+ }
530+ return typs , expGenTyps
531+ }
532+
482533// namedTypeDecls returns Decls that define all names Go types.
483534//
484535// `typeNames` must contain all named types defined in the package, including
0 commit comments