var instErrPos poser
if inst != nil {
instErrPos = inst.Pos()
+ x.expr = inst // if we don't have an index expression, keep the existing expression of x
} else {
instErrPos = pos
}
targs = check.typeList(xlist)
if targs == nil {
x.mode = invalid
- x.expr = inst
return nil, nil
}
assert(len(targs) == len(xlist))
// Providing too many type arguments is always an error.
check.errorf(xlist[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want)
x.mode = invalid
- x.expr = inst
return nil, nil
}
if targs == nil {
// error was already reported
x.mode = invalid
- x.expr = inst
return nil, nil
}
got = len(targs)
assert(got == want)
// instantiate function signature
- expr := x.expr // if we don't have an index expression, keep the existing expression of x
- if inst != nil {
- expr = inst
- }
- sig = check.instantiateSignature(x.Pos(), expr, sig, targs, xlist)
+ sig = check.instantiateSignature(x.Pos(), x.expr, sig, targs, xlist)
x.typ = sig
x.mode = value
- x.expr = expr
return nil, nil
}
// IndexExpr wraps an ast.IndexExpr or ast.IndexListExpr.
//
// Orig holds the original ast.Expr from which this IndexExpr was derived.
+//
+// Note: IndexExpr (intentionally) does not wrap ast.Expr, as that leads to
+// accidental misuse such as encountered in golang/go#63933.
+//
+// TODO(rfindley): remove this helper, in favor of just having a helper
+// function that returns indices.
type IndexExpr struct {
- Orig ast.Expr // the wrapped expr, which may be distinct from the IndexListExpr below.
- *ast.IndexListExpr
+ Orig ast.Expr // the wrapped expr, which may be distinct from the IndexListExpr below.
+ X ast.Expr // expression
+ Lbrack token.Pos // position of "["
+ Indices []ast.Expr // index expressions
+ Rbrack token.Pos // position of "]"
+}
+
+func (x *IndexExpr) Pos() token.Pos {
+ return x.Orig.Pos()
}
func UnpackIndexExpr(n ast.Node) *IndexExpr {
switch e := n.(type) {
case *ast.IndexExpr:
- return &IndexExpr{e, &ast.IndexListExpr{
+ return &IndexExpr{
+ Orig: e,
X: e.X,
Lbrack: e.Lbrack,
Indices: []ast.Expr{e.Index},
Rbrack: e.Rbrack,
- }}
+ }
case *ast.IndexListExpr:
- return &IndexExpr{e, e}
+ return &IndexExpr{
+ Orig: e,
+ X: e.X,
+ Lbrack: e.Lbrack,
+ Indices: e.Indices,
+ Rbrack: e.Rbrack,
+ }
}
return nil
}
var instErrPos positioner
if ix != nil {
instErrPos = inNode(ix.Orig, ix.Lbrack)
+ x.expr = ix.Orig // if we don't have an index expression, keep the existing expression of x
} else {
instErrPos = atPos(pos)
}
targs = check.typeList(xlist)
if targs == nil {
x.mode = invalid
- x.expr = ix
return nil, nil
}
assert(len(targs) == len(xlist))
// Providing too many type arguments is always an error.
check.errorf(ix.Indices[got-1], WrongTypeArgCount, "got %d type arguments but want %d", got, want)
x.mode = invalid
- x.expr = ix.Orig
return nil, nil
}
if targs == nil {
// error was already reported
x.mode = invalid
- x.expr = ix // TODO(gri) is this correct?
return nil, nil
}
got = len(targs)
assert(got == want)
// instantiate function signature
- expr := x.expr // if we don't have an index expression, keep the existing expression of x
- if ix != nil {
- expr = ix.Orig
- }
- sig = check.instantiateSignature(x.Pos(), expr, sig, targs, xlist)
-
+ sig = check.instantiateSignature(x.Pos(), x.expr, sig, targs, xlist)
x.typ = sig
x.mode = value
- x.expr = expr
return nil, nil
}
// ok to continue even if indexing failed - map element type is known
x.mode = mapindex
x.typ = elem
- x.expr = e
+ x.expr = e.Orig
return false
}