Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cl/_testgo/tplocalclosureiface/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ package main

// DARWIN-ARM64-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.eface" @"main.boxFuncs$1[int]"(ptr swiftself
// LINUX-AMD64-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.eface" @"main.boxFuncs$1[int]"(ptr nest
// CHECK: insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr [[INT_BOX:@"_llgo_main\.box\[int\]\.p[0-9]+"]], ptr undef }
// CHECK: insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr [[INT_BOX:@"_llgo_main\.box\[int\]"]], ptr undef }
// CHECK-LABEL: define linkonce i1 @"main.boxFuncs$2[int]"(
// CHECK: icmp eq ptr %{{.*}}, [[INT_BOX]]
// DARWIN-ARM64-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.eface" @"main.boxFuncs$1[string]"(ptr swiftself
// LINUX-AMD64-LABEL: define linkonce %"{{.*}}/runtime/internal/runtime.eface" @"main.boxFuncs$1[string]"(ptr nest
// CHECK: insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr [[STRING_BOX:@"_llgo_main\.box\[string\]\.p[0-9]+"]], ptr undef }
// CHECK: insertvalue %"{{.*}}/runtime/internal/runtime.eface" { ptr [[STRING_BOX:@"_llgo_main\.box\[string\]"]], ptr undef }
// CHECK-LABEL: define linkonce i1 @"main.boxFuncs$2[string]"(
// CHECK: icmp eq ptr %{{.*}}, [[STRING_BOX]]

Expand Down
5 changes: 4 additions & 1 deletion cl/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -2570,7 +2570,10 @@ func (p *context) patchLocalGenericNamed(t *types.Named) (*types.Named, bool) {
if isPatchedLocalGenericName(t.Obj().Name()) {
return nil, false
}
obj := types.NewTypeName(t.Obj().Pos(), t.Obj().Pkg(), p.localNamedName(t, false), nil)
// The generated name already carries the local type's complete identity.
// Keep this detached object positionless so ABI naming does not append a
// loader-relative token.Pos that changes between package-cache processes.
obj := types.NewTypeName(token.NoPos, t.Obj().Pkg(), p.localNamedName(t, false), nil)
return types.NewNamed(obj, t.Underlying(), nil), true
}

Expand Down
3 changes: 3 additions & 0 deletions cl/funcname_nested_closure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ func localType[T any]() any {
if !ok {
t.Fatalf("patchLocalGenericNamed(%v) was not patched", local)
}
if pos := patched.Obj().Pos(); pos.IsValid() {
t.Fatalf("patched local generic type position = %v, want token.NoPos", pos)
}
name := patched.Obj().Name()
if !strings.Contains(name, "[") || strings.Contains(name, "·") {
t.Fatalf("patched local generic name = %q, want type args without ordinal suffix", name)
Expand Down
52 changes: 52 additions & 0 deletions internal/build/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,58 @@ func TestDeadcodeBuildColdAndHotPackageCache(t *testing.T) {
}
}

func TestGenericLocalTypeColdAndHotPackageCache(t *testing.T) {
repoRoot, err := filepath.Abs(filepath.Join("..", ".."))
if err != nil {
t.Fatal(err)
}
fixture := filepath.Join(repoRoot, "internal", "build", "testdata", "genericlocalcache")
const (
cacheRootEnv = "LLGO_TEST_GENERIC_LOCAL_CACHE_ROOT"
cachePhaseEnv = "LLGO_TEST_GENERIC_LOCAL_CACHE_PHASE"
)
if cacheRoot := os.Getenv(cacheRootEnv); cacheRoot != "" {
cacheRootFunc = func() string { return cacheRoot }
t.Setenv("LLGO_ROOT", repoRoot)
t.Setenv(llgoBuildCache, "1")

conf := NewDefaultConf(ModeTest)
conf.OutFile = filepath.Join(t.TempDir(), os.Getenv(cachePhaseEnv))
conf.RunArgs = []string{"-test.run=^TestLocalRuntimeType$"}
pkgs, err := Build(Invocation{Args: []string{"."}, Config: conf, Dir: fixture})
if err != nil {
t.Fatal(err)
}
switch phase := os.Getenv(cachePhaseEnv); phase {
case "cold":
for _, pkg := range pkgs {
if pkg.CacheHit {
t.Fatalf("cold build unexpectedly hit package cache for %s", pkg.PkgPath)
}
}
case "hot":
for _, pkg := range pkgs {
if pkg.CacheHit {
return
}
}
t.Fatal("hot build did not reuse any package archives")
default:
t.Fatalf("unknown cache phase %q", phase)
}
return
}

cacheRoot := t.TempDir()
for _, phase := range []string{"cold", "hot"} {
cmd := exec.Command(os.Args[0], "-test.run=^TestGenericLocalTypeColdAndHotPackageCache$", "-test.count=1")
cmd.Env = append(os.Environ(), cacheRootEnv+"="+cacheRoot, cachePhaseEnv+"="+phase)
if out, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("%s cache build: %v\n%s", phase, err, out)
}
}
}

func TestResolveOutputsUsesInvocationDirectory(t *testing.T) {
dir := t.TempDir()
out := &OutFmtDetails{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package genericlocalcache

import (
"reflect"
"testing"
)

func localRuntimeType[T any]() reflect.Type {
type local struct {
value T
}
return reflect.TypeOf(local{})
}

func TestLocalRuntimeType(t *testing.T) {
intType := localRuntimeType[int]()
stringType := localRuntimeType[string]()
if intType == stringType {
t.Fatalf("generic local runtime types are identical: %v", intType)
}
}
Loading