Help us shape the future of Go! Take the 2026 Go Developer Survey

Source file src/cmd/compile/internal/types2/methodorder_test.go

     1  // Copyright 2026 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types2_test
     6  
     7  import (
     8  	"internal/testenv"
     9  	"os"
    10  	"path/filepath"
    11  	"strings"
    12  	"testing"
    13  
    14  	. "cmd/compile/internal/types2"
    15  )
    16  
    17  // TestImportedMethodOrder checks that methods of types imported from
    18  // export data appear in source order, as required by objectpath
    19  // (go.dev/issue/81188).
    20  func TestImportedMethodOrder(t *testing.T) {
    21  	testenv.MustHaveGoBuild(t)
    22  
    23  	const src = `package methodorder
    24  
    25  // T mixes generic and non-generic methods.
    26  type T struct{}
    27  
    28  func (T) A()               {}
    29  func (T) B[X any]()        {}
    30  func (T) C()               {}
    31  func (T) D[X, Y any](X, Y) {}
    32  func (T) E()               {}
    33  
    34  // U's underlying type refers to V, whose method body calls a generic
    35  // method of U, so encoding U's underlying type encodes U.G before the
    36  // rest of U.
    37  type U struct{ v *V }
    38  
    39  type V struct{}
    40  
    41  func (v *V) M(u *U) int { return u.G[int]() }
    42  
    43  func (*U) A()            {}
    44  func (*U) B()            {}
    45  func (*U) G[X any]() int { return 0 }
    46  func (*U) Z()            {}
    47  `
    48  	dir := t.TempDir()
    49  	if err := os.WriteFile(filepath.Join(dir, "go.mod"), []byte("module methodorder\n\ngo 1.27\n"), 0666); err != nil {
    50  		t.Fatal(err)
    51  	}
    52  	if err := os.WriteFile(filepath.Join(dir, "methodorder.go"), []byte(src), 0666); err != nil {
    53  		t.Fatal(err)
    54  	}
    55  
    56  	// NOTE(adonovan): I manually edited the cherrypick CL 855582 here
    57  	// to avoid a dependency on a not-yet-existing testimporter package.
    58  	// -vvv-
    59  	// Compile to export data, then import it, so that the method
    60  	// order is that recorded by the encoder (not by source type-checking).
    61  	cmd := testenv.Command(t, testenv.GoToolPath(t), "tool", "compile", "-p", "methodorder", "-importcfg", os.DevNull, "-o", "methodorder.o", "methodorder.go")
    62  	cmd.Dir = dir
    63  	if out, err := cmd.CombinedOutput(); err != nil {
    64  		t.Fatalf("go tool compile failed: %v\n%s", err, out)
    65  	}
    66  	pkg, err := defaultImporter().(ImporterFrom).ImportFrom("./methodorder", dir, 0)
    67  	// -^^^-
    68  
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  	for _, test := range []struct {
    73  		typ  string
    74  		want string
    75  	}{
    76  		{"T", "A B C D E"},
    77  		{"U", "A B G Z"},
    78  	} {
    79  		named := pkg.Scope().Lookup(test.typ).Type().(*Named)
    80  		var names []string
    81  		for i := range named.NumMethods() {
    82  			names = append(names, named.Method(i).Name())
    83  		}
    84  		if got := strings.Join(names, " "); got != test.want {
    85  			t.Errorf("methods of %s = %s; want %s", test.typ, got, test.want)
    86  		}
    87  	}
    88  }
    89  

View as plain text