diff --git a/_cmptest/gotypesissue/README.md b/_cmptest/gotypesissue/README.md new file mode 100644 index 00000000..e8542e00 --- /dev/null +++ b/_cmptest/gotypesissue/README.md @@ -0,0 +1,55 @@ +# go/types Issue Test Cases + +This directory contains test cases for issues with the `go/types` package in llgo. + +## Issue #1357: Scope.Insert segmentation fault + +**Status**: Known issue - requires compiler fix + +**Description**: Calling `types.Scope.Insert()` causes a segmentation fault in llgo but works correctly with standard Go. + +**Root Cause**: Compiler bug in llgo's type metadata generation. When stdlib packages (like `go/types`) access their own unexported map fields with interface values, the generated `*abi.MapType` metadata is invalid/null, causing a segfault in runtime map functions. + +**Test Case**: `scope_insert.go` + +**Expected Behavior** (with standard Go): +```bash +$ go run scope_insert.go +=== Scope Insert Test === + +✓ Insert successful: x +✓ Insert failed as expected: x already exists +✓ Insert successful: y + +Scope contains 2 objects +✓ Scope length check passed + +All objects: + - x: int + - y: string +``` + +**Actual Behavior** (with llgo): +```bash +$ llgo run scope_insert.go +=== Scope Insert Test === + +signal: segmentation fault +``` + +**Technical Details**: +- The issue is in `ssa/abitype.go` (`abiMapOf` function) and `ssa/datastruct.go` (map access operations) +- Type metadata for maps with interface values in stdlib packages is not correctly initialized +- The `MapAccess1`/`MapAssign` runtime functions receive null/invalid type metadata +- This is a self-referential type generation issue specific to stdlib compilation + +**Workaround**: +- Avoid using `go/types`, `go/parser`, and `go/ast` packages in llgo programs +- Use `reflect` package for runtime type information +- Run code analysis with standard Go compiler + +**Related Issues**: +- #642 - Tracking stdlib package implementation status + +**For Developers**: +This test case should pass once the compiler bug is fixed. It serves as a regression test. diff --git a/_cmptest/gotypesissue/scope_insert.go b/_cmptest/gotypesissue/scope_insert.go new file mode 100644 index 00000000..45b43fca --- /dev/null +++ b/_cmptest/gotypesissue/scope_insert.go @@ -0,0 +1,51 @@ +package main + +import ( + "fmt" + "go/types" +) + +func main() { + fmt.Println("=== Scope Insert Test ===\n") + + // Create a scope + scope := types.NewScope(nil, 0, 0, "test") + + // Test 1: Successful insert + obj1 := types.NewVar(0, nil, "x", types.Typ[types.Int]) + if alt := scope.Insert(obj1); alt != nil { + panic(fmt.Sprintf("unexpected: insert failed with conflict: %v", alt)) + } + fmt.Printf("✓ Insert successful: %s\n", obj1.Name()) + + // Test 2: Duplicate insert (will fail) + obj2 := types.NewVar(0, nil, "x", types.Typ[types.String]) + if alt := scope.Insert(obj2); alt != nil { + fmt.Printf("✓ Insert failed as expected: %s already exists\n", alt.Name()) + } else { + panic("unexpected: duplicate insert should have failed") + } + + // Test 3: Insert different name + obj3 := types.NewVar(0, nil, "y", types.Typ[types.String]) + if alt := scope.Insert(obj3); alt != nil { + panic(fmt.Sprintf("unexpected: insert failed with conflict: %v", alt)) + } + fmt.Printf("✓ Insert successful: %s\n", obj3.Name()) + + // View results + fmt.Printf("\nScope contains %d objects\n", scope.Len()) + + // Verify expected count + expectedCount := 2 // x and y + if scope.Len() != expectedCount { + panic(fmt.Sprintf("unexpected: scope should contain %d objects, but has %d", expectedCount, scope.Len())) + } + fmt.Printf("✓ Scope length check passed\n") + + fmt.Println("\nAll objects:") + for _, name := range scope.Names() { + obj := scope.Lookup(name) + fmt.Printf(" - %s: %v\n", name, obj.Type()) + } +}