Skip to content

Commit 5392240

Browse files
committed
cb.emitTypeAssert: Go does not fully implement chained call safety
1 parent 7dd8ccd commit 5392240

2 files changed

Lines changed: 23 additions & 8 deletions

File tree

codebuild.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,7 @@ func (p *CodeBuilder) Index(nidx int, lhs int, src ...ast.Node) *CodeBuilder {
13021302
}
13031303
argVal := args[0].Val
13041304
if ivKind == ivMapStringAny {
1305-
argVal = &ast.TypeAssertExpr{X: argVal, Type: toMapType(p.pkg, tyMapStringAny)}
1305+
argVal = p.emitTypeAssert(argVal)
13061306
}
13071307
elem := &internal.Elem{
13081308
Val: &ast.IndexExpr{X: argVal, Index: args[1].Val}, Type: tyRet, Src: srcExpr,
@@ -1785,10 +1785,8 @@ retry:
17851785
o.Complete()
17861786

17871787
if o.Empty() { // empty interface (https://github.com/goplus/xgo/issues/2571)
1788-
tyMap := tyMapStringAny
1789-
p.TypeAssert(tyMap, 0)
1790-
arg = p.stk.Get(-1)
1791-
return p.mapIndexExpr(tyMap, name, lhs, arg.Val, srcExpr)
1788+
argVal := p.emitTypeAssert(arg.Val)
1789+
return p.mapIndexExpr(tyMapStringAny, name, lhs, argVal, srcExpr)
17921790
}
17931791

17941792
if kind := p.method(o, name, aliasName, flag, arg, srcExpr); kind != MemberInvalid {
@@ -1828,6 +1826,20 @@ retry:
18281826
return MemberInvalid
18291827
}
18301828

1829+
// See https://github.com/goplus/xgo/issues/2572#issuecomment-3807206716
1830+
func (p *CodeBuilder) emitTypeAssert(argVal ast.Expr) ast.Expr {
1831+
pkg := p.pkg
1832+
e := &ast.TypeAssertExpr{X: argVal, Type: toMapType(pkg, tyMapStringAny)}
1833+
ret := ast.NewIdent(pkg.autoName())
1834+
stmt := &ast.AssignStmt{
1835+
Lhs: []ast.Expr{ret, underscore},
1836+
Tok: token.DEFINE,
1837+
Rhs: []ast.Expr{e},
1838+
}
1839+
p.emitStmt(stmt)
1840+
return ret
1841+
}
1842+
18311843
func (p *CodeBuilder) mapIndexExpr(o *types.Map, name string, lhs int, argVal ast.Expr, src ast.Node) MemberKind {
18321844
tyRet := o.Elem()
18331845
if lhs == 2 { // two-value assignment

package_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3407,11 +3407,14 @@ func TestIndex(t *testing.T) {
34073407
34083408
func foo(x []int, y map[string]int, z interface{}) int {
34093409
v, ok := y["a"]
3410-
v1, ok := z.(map[string]any)["a"]
3410+
_autoGo_1, _ := z.(map[string]any)
3411+
v1, ok := _autoGo_1["a"]
34113412
v2 := y["a"]
34123413
v3, ok := y["b"]
3413-
v4, ok := z.(map[string]any)["c"]
3414-
v5 := z.(map[string]any)["d"]
3414+
_autoGo_2, _ := z.(map[string]any)
3415+
v4, ok := _autoGo_2["c"]
3416+
_autoGo_3, _ := z.(map[string]any)
3417+
v5 := _autoGo_3["d"]
34153418
return x[0]
34163419
}
34173420
func main() {

0 commit comments

Comments
 (0)