]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.typeparams] go/types: use a new ast.ListExpr for multi-type instances
authorRob Findley <rfindley@google.com>
Wed, 17 Feb 2021 00:56:38 +0000 (19:56 -0500)
committerRobert Findley <rfindley@google.com>
Thu, 18 Feb 2021 20:38:41 +0000 (20:38 +0000)
Modify go/parser to consistently represent type instantiation as an
ast.IndexExpr, rather than use an ast.CallExpr (with Brackets:true) for
instantiations with multiple type parameters. To enable this, introduce
a new ast expr type: ListExpr.

This brings go/types in line with types2, with the exception of a small
change to funcInst to eliminate redundant errors if values are
erroneously used as types. In a subsequent CL, call.go and expr.go will
be marked as reviewed.

This also catches some type instance syntax using '()' that was
previously accepted incorrectly. Tests are updated accordingly.

Change-Id: I30cd0181c7608f1be7486a9a8b63df993b412e85
Reviewed-on: https://go-review.googlesource.com/c/go/+/293010
Trust: Robert Findley <rfindley@google.com>
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
14 files changed:
src/go/ast/ast.go
src/go/ast/example_test.go
src/go/parser/parser.go
src/go/printer/nodes.go
src/go/types/api_test.go
src/go/types/assignments.go
src/go/types/call.go
src/go/types/examples/functions.go2
src/go/types/expr.go
src/go/types/exprstring.go
src/go/types/resolver.go
src/go/types/testdata/issues.go2
src/go/types/testdata/typeparams.go2
src/go/types/typexpr.go

index 2456020c5ef336681a01317b5dbe02660b2240cf..6eb4d13f4d0fbcec4da61cc4d24de46b3dee83bc 100644 (file)
@@ -372,9 +372,13 @@ type (
                Args     []Expr    // function arguments; or nil
                Ellipsis token.Pos // position of "..." (token.NoPos if there is no "...")
                Rparen   token.Pos // position of ")"
-               // TODO(rFindley) use a new ListExpr type rather than overloading CallExpr
-               //                via Brackets, as is done in the syntax package
-               Brackets bool // if set, "[" and "]" are used instead of "(" and ")"
+       }
+
+       // A ListExpr node represents a list of expressions separated by commas.
+       // ListExpr nodes are used as index in IndexExpr nodes representing type
+       // or function instantiations with more than one type argument.
+       ListExpr struct {
+               ElemList []Expr
        }
 
        // A StarExpr node represents an expression of the form "*" Expression.
@@ -493,12 +497,18 @@ func (x *IndexExpr) Pos() token.Pos      { return x.X.Pos() }
 func (x *SliceExpr) Pos() token.Pos      { return x.X.Pos() }
 func (x *TypeAssertExpr) Pos() token.Pos { return x.X.Pos() }
 func (x *CallExpr) Pos() token.Pos       { return x.Fun.Pos() }
-func (x *StarExpr) Pos() token.Pos       { return x.Star }
-func (x *UnaryExpr) Pos() token.Pos      { return x.OpPos }
-func (x *BinaryExpr) Pos() token.Pos     { return x.X.Pos() }
-func (x *KeyValueExpr) Pos() token.Pos   { return x.Key.Pos() }
-func (x *ArrayType) Pos() token.Pos      { return x.Lbrack }
-func (x *StructType) Pos() token.Pos     { return x.Struct }
+func (x *ListExpr) Pos() token.Pos {
+       if len(x.ElemList) > 0 {
+               return x.ElemList[0].Pos()
+       }
+       return token.NoPos
+}
+func (x *StarExpr) Pos() token.Pos     { return x.Star }
+func (x *UnaryExpr) Pos() token.Pos    { return x.OpPos }
+func (x *BinaryExpr) Pos() token.Pos   { return x.X.Pos() }
+func (x *KeyValueExpr) Pos() token.Pos { return x.Key.Pos() }
+func (x *ArrayType) Pos() token.Pos    { return x.Lbrack }
+func (x *StructType) Pos() token.Pos   { return x.Struct }
 func (x *FuncType) Pos() token.Pos {
        if x.Func.IsValid() || x.Params == nil { // see issue 3870
                return x.Func
@@ -526,12 +536,18 @@ func (x *IndexExpr) End() token.Pos      { return x.Rbrack + 1 }
 func (x *SliceExpr) End() token.Pos      { return x.Rbrack + 1 }
 func (x *TypeAssertExpr) End() token.Pos { return x.Rparen + 1 }
 func (x *CallExpr) End() token.Pos       { return x.Rparen + 1 }
-func (x *StarExpr) End() token.Pos       { return x.X.End() }
-func (x *UnaryExpr) End() token.Pos      { return x.X.End() }
-func (x *BinaryExpr) End() token.Pos     { return x.Y.End() }
-func (x *KeyValueExpr) End() token.Pos   { return x.Value.End() }
-func (x *ArrayType) End() token.Pos      { return x.Elt.End() }
-func (x *StructType) End() token.Pos     { return x.Fields.End() }
+func (x *ListExpr) End() token.Pos {
+       if len(x.ElemList) > 0 {
+               return x.ElemList[len(x.ElemList)-1].End()
+       }
+       return token.NoPos
+}
+func (x *StarExpr) End() token.Pos     { return x.X.End() }
+func (x *UnaryExpr) End() token.Pos    { return x.X.End() }
+func (x *BinaryExpr) End() token.Pos   { return x.Y.End() }
+func (x *KeyValueExpr) End() token.Pos { return x.Value.End() }
+func (x *ArrayType) End() token.Pos    { return x.Elt.End() }
+func (x *StructType) End() token.Pos   { return x.Fields.End() }
 func (x *FuncType) End() token.Pos {
        if x.Results != nil {
                return x.Results.End()
@@ -557,6 +573,7 @@ func (*IndexExpr) exprNode()      {}
 func (*SliceExpr) exprNode()      {}
 func (*TypeAssertExpr) exprNode() {}
 func (*CallExpr) exprNode()       {}
+func (*ListExpr) exprNode()       {}
 func (*StarExpr) exprNode()       {}
 func (*UnaryExpr) exprNode()      {}
 func (*BinaryExpr) exprNode()     {}
index c2b35205bbc8c8d1510b0d94490b50b76b28ad95..e3013f64bed87e3e8ff2e41311688346b5cea41f 100644 (file)
@@ -119,23 +119,22 @@ func main() {
        //     40  .  .  .  .  .  .  .  }
        //     41  .  .  .  .  .  .  .  Ellipsis: -
        //     42  .  .  .  .  .  .  .  Rparen: 4:25
-       //     43  .  .  .  .  .  .  .  Brackets: false
-       //     44  .  .  .  .  .  .  }
-       //     45  .  .  .  .  .  }
-       //     46  .  .  .  .  }
-       //     47  .  .  .  .  Rbrace: 5:1
-       //     48  .  .  .  }
-       //     49  .  .  }
-       //     50  .  }
-       //     51  .  Scope: *ast.Scope {
-       //     52  .  .  Objects: map[string]*ast.Object (len = 1) {
-       //     53  .  .  .  "main": *(obj @ 11)
-       //     54  .  .  }
-       //     55  .  }
-       //     56  .  Unresolved: []*ast.Ident (len = 1) {
-       //     57  .  .  0: *(obj @ 29)
-       //     58  .  }
-       //     59  }
+       //     43  .  .  .  .  .  .  }
+       //     44  .  .  .  .  .  }
+       //     45  .  .  .  .  }
+       //     46  .  .  .  .  Rbrace: 5:1
+       //     47  .  .  .  }
+       //     48  .  .  }
+       //     49  .  }
+       //     50  .  Scope: *ast.Scope {
+       //     51  .  .  Objects: map[string]*ast.Object (len = 1) {
+       //     52  .  .  .  "main": *(obj @ 11)
+       //     53  .  .  }
+       //     54  .  }
+       //     55  .  Unresolved: []*ast.Ident (len = 1) {
+       //     56  .  .  0: *(obj @ 29)
+       //     57  .  }
+       //     58  }
 }
 
 // This example illustrates how to remove a variable declaration
index ccbcef8f260efc24c487b855794482ee382e9025..e12eee79bfbf776d819bc129cc4702431d545c5a 100644 (file)
@@ -754,7 +754,7 @@ func (p *parser) parseArrayFieldOrTypeInstance(x *ast.Ident) (*ast.Ident, ast.Ex
        }
 
        // x[P], x[P1, P2], ...
-       return nil, &ast.CallExpr{Fun: x, Lparen: lbrack, Args: args, Rparen: rbrack, Brackets: true}
+       return nil, &ast.IndexExpr{X: x, Lbrack: lbrack, Index: &ast.ListExpr{ElemList: args}, Rbrack: rbrack}
 }
 
 func (p *parser) parseFieldDecl(scope *ast.Scope) *ast.Field {
@@ -1153,7 +1153,7 @@ func (p *parser) parseMethodSpec(scope *ast.Scope) *ast.Field {
                                        p.exprLev--
                                }
                                rbrack := p.expectClosing(token.RBRACK, "type argument list")
-                               typ = &ast.CallExpr{Fun: ident, Lparen: lbrack, Args: list, Rparen: rbrack, Brackets: true}
+                               typ = &ast.IndexExpr{X: ident, Lbrack: lbrack, Index: &ast.ListExpr{ElemList: list}, Rbrack: rbrack}
                        }
                case p.tok == token.LPAREN:
                        // ordinary method
@@ -1281,7 +1281,7 @@ func (p *parser) parseTypeInstance(typ ast.Expr) ast.Expr {
 
        closing := p.expectClosing(token.RBRACK, "type argument list")
 
-       return &ast.CallExpr{Fun: typ, Lparen: opening, Args: list, Rparen: closing, Brackets: true}
+       return &ast.IndexExpr{X: typ, Lbrack: opening, Index: &ast.ListExpr{ElemList: list}, Rbrack: closing}
 }
 
 // If the result is an identifier, it is not resolved.
@@ -1557,7 +1557,7 @@ func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr {
        }
 
        // instance expression
-       return &ast.CallExpr{Fun: x, Lparen: lbrack, Args: args, Rparen: rbrack, Brackets: true}
+       return &ast.IndexExpr{X: x, Lbrack: lbrack, Index: &ast.ListExpr{ElemList: args}, Rbrack: rbrack}
 }
 
 func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
@@ -1773,17 +1773,12 @@ func (p *parser) parsePrimaryExpr(lhs bool) (x ast.Expr) {
                        // type; accept it but complain if we have a complit
                        t := unparen(x)
                        // determine if '{' belongs to a composite literal or a block statement
-                       switch t := t.(type) {
+                       switch t.(type) {
                        case *ast.BadExpr, *ast.Ident, *ast.SelectorExpr:
                                if p.exprLev < 0 {
                                        return
                                }
                                // x is possibly a composite literal type
-                       case *ast.CallExpr:
-                               if !t.Brackets || p.exprLev < 0 {
-                                       return
-                               }
-                               // x is possibly a composite literal type
                        case *ast.IndexExpr:
                                if p.exprLev < 0 {
                                        return
index cc795532b0c5bdea1fc42f17f4aadf48ec169dca..1c0a14ec157756a9b09ec800efc679e9ae43ef2b 100644 (file)
@@ -870,7 +870,11 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                // TODO(gri): should treat[] like parentheses and undo one level of depth
                p.expr1(x.X, token.HighestPrec, 1)
                p.print(x.Lbrack, token.LBRACK)
-               p.expr0(x.Index, depth+1)
+               if e, _ := x.Index.(*ast.ListExpr); e != nil {
+                       p.exprList(x.Lbrack, e.ElemList, depth+1, commaTerm, x.Rbrack, false)
+               } else {
+                       p.expr0(x.Index, depth+1)
+               }
                p.print(x.Rbrack, token.RBRACK)
 
        case *ast.SliceExpr:
@@ -919,32 +923,25 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int) {
                        depth++
                }
                var wasIndented bool
-               if x.Brackets {
+               if _, ok := x.Fun.(*ast.FuncType); ok {
+                       // conversions to literal function types require parentheses around the type
+                       p.print(token.LPAREN)
                        wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
-                       p.print(x.Lparen, token.LBRACK)
-                       p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
-                       p.print(x.Rparen, token.RBRACK)
+                       p.print(token.RPAREN)
                } else {
-                       if _, ok := x.Fun.(*ast.FuncType); ok {
-                               // conversions to literal function types require parentheses around the type
-                               p.print(token.LPAREN)
-                               wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
-                               p.print(token.RPAREN)
-                       } else {
-                               wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
-                       }
-                       p.print(x.Lparen, token.LPAREN)
-                       if x.Ellipsis.IsValid() {
-                               p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis, false)
-                               p.print(x.Ellipsis, token.ELLIPSIS)
-                               if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
-                                       p.print(token.COMMA, formfeed)
-                               }
-                       } else {
-                               p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
+                       wasIndented = p.possibleSelectorExpr(x.Fun, token.HighestPrec, depth)
+               }
+               p.print(x.Lparen, token.LPAREN)
+               if x.Ellipsis.IsValid() {
+                       p.exprList(x.Lparen, x.Args, depth, 0, x.Ellipsis, false)
+                       p.print(x.Ellipsis, token.ELLIPSIS)
+                       if x.Rparen.IsValid() && p.lineFor(x.Ellipsis) < p.lineFor(x.Rparen) {
+                               p.print(token.COMMA, formfeed)
                        }
-                       p.print(x.Rparen, token.RPAREN)
+               } else {
+                       p.exprList(x.Lparen, x.Args, depth, commaTerm, x.Rparen, false)
                }
+               p.print(x.Rparen, token.RPAREN)
                if wasIndented {
                        p.print(unindent)
                }
index eca11358efbf5498065a53237c544789a1104bbd..20648f1cf6b091d745f861306fbef0a505d73dff 100644 (file)
@@ -325,8 +325,8 @@ func TestTypesInfo(t *testing.T) {
                {broken + `x5; func _() { var x map[string][...]int; x = map[string][...]int{"": {1,2,3}} }`, `x`, `map[string][-1]int`},
 
                // parameterized functions
-               {genericPkg + `p0; func f[T any](T); var _ = f(int)`, `f`, `func[T₁ interface{}](T₁)`},
-               {genericPkg + `p1; func f[T any](T); var _ = f(int)`, `f(int)`, `func(int)`},
+               {genericPkg + `p0; func f[T any](T); var _ = f[int]`, `f`, `func[T₁ interface{}](T₁)`},
+               {genericPkg + `p1; func f[T any](T); var _ = f[int]`, `f[int]`, `func(int)`},
                {genericPkg + `p2; func f[T any](T); func _() { f(42) }`, `f`, `func[T₁ interface{}](T₁)`},
                {genericPkg + `p3; func f[T any](T); func _() { f(42) }`, `f(42)`, `()`},
 
index 3aa06e8939fca76084b0217202c4f2eb8c4b4509..f223cb7574361902da3027a967b43160a0910288 100644 (file)
@@ -303,6 +303,20 @@ func (check *Checker) assignVars(lhs, origRHS []ast.Expr) {
        }
 }
 
+// unpack unpacks an *ast.ListExpr into a list of ast.Expr.
+// TODO(gri) Should find a more efficient solution that doesn't
+//           require introduction of a new slice for simple
+//           expressions.
+func unpackExpr(x ast.Expr) []ast.Expr {
+       if x, _ := x.(*ast.ListExpr); x != nil {
+               return x.ElemList
+       }
+       if x != nil {
+               return []ast.Expr{x}
+       }
+       return nil
+}
+
 func (check *Checker) shortVarDecl(pos positioner, lhs, rhs []ast.Expr) {
        top := len(check.delayed)
        scope := check.scope
index d9a7b440ec13d53d2e3d63a447d1e7a4724050db..b502122a26aeef37b1c4754ad7d72360fb737b32 100644 (file)
@@ -14,25 +14,103 @@ import (
        "unicode"
 )
 
-// TODO(rFindley) this has diverged a bit from types2. Bring it up to date.
-// If call == nil, the "call" was an index expression, and orig is of type *ast.IndexExpr.
-func (check *Checker) call(x *operand, call *ast.CallExpr, orig ast.Expr) exprKind {
-       assert(orig != nil)
-       if call != nil {
-               assert(call == orig)
-               check.exprOrType(x, call.Fun)
-       } else {
-               // We must have an index expression.
-               // x has already been set up (evaluation of orig.X).
-               // Set up fake call so we can use its fields below.
-               expr := orig.(*ast.IndexExpr)
-               call = &ast.CallExpr{Fun: expr.X, Lparen: expr.Lbrack, Args: []ast.Expr{expr.Index}, Rparen: expr.Rbrack, Brackets: true}
+// funcInst type-checks a function instantiaton inst and returns the result in x.
+// The operand x must be the evaluation of inst.X and its type must be a signature.
+func (check *Checker) funcInst(x *operand, inst *ast.IndexExpr) {
+       args, ok := check.exprOrTypeList(unpackExpr(inst.Index))
+       if !ok {
+               x.mode = invalid
+               x.expr = inst
+               return
+       }
+       if len(args) > 0 && args[0].mode != typexpr {
+               check.errorf(args[0], _NotAType, "%s is not a type", args[0])
+               ok = false
+       }
+
+       // check number of type arguments
+       n := len(args)
+       sig := x.typ.(*Signature)
+       if n > len(sig.tparams) {
+               check.errorf(args[n-1], _Todo, "got %d type arguments but want %d", n, len(sig.tparams))
+               x.mode = invalid
+               x.expr = inst
+               return
+       }
+
+       // collect types
+       targs := make([]Type, n)
+       // TODO(rFindley) use a positioner here? instantiate would need to be
+       //                updated accordingly.
+       poslist := make([]token.Pos, n)
+       for i, a := range args {
+               if a.mode != typexpr {
+                       // error was reported earlier
+                       x.mode = invalid
+                       x.expr = inst
+                       return
+               }
+               targs[i] = a.typ
+               poslist[i] = a.Pos()
+       }
+
+       // if we don't have enough type arguments, use constraint type inference
+       var inferred bool
+       if n < len(sig.tparams) {
+               var failed int
+               targs, failed = check.inferB(sig.tparams, targs)
+               if targs == nil {
+                       // error was already reported
+                       x.mode = invalid
+                       x.expr = inst
+                       return
+               }
+               if failed >= 0 {
+                       // at least one type argument couldn't be inferred
+                       assert(targs[failed] == nil)
+                       tpar := sig.tparams[failed]
+                       check.errorf(inNode(inst, inst.Rbrack), 0, "cannot infer %s (%v) (%s)", tpar.name, tpar.pos, targs)
+                       x.mode = invalid
+                       x.expr = inst
+                       return
+               }
+               // all type arguments were inferred sucessfully
+               if debug {
+                       for _, targ := range targs {
+                               assert(targ != nil)
+                       }
+               }
+               n = len(targs)
+               inferred = true
        }
+       assert(n == len(sig.tparams))
+
+       // instantiate function signature
+       for i, typ := range targs {
+               // some positions may be missing if types are inferred
+               var pos token.Pos
+               if i < len(poslist) {
+                       pos = poslist[i]
+               }
+               check.ordinaryType(atPos(pos), typ)
+       }
+       res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature)
+       assert(res.tparams == nil) // signature is not generic anymore
+       if inferred {
+               check.recordInferred(inst, targs, res)
+       }
+       x.typ = res
+       x.mode = value
+       x.expr = inst
+}
+
+func (check *Checker) call(x *operand, call *ast.CallExpr) exprKind {
+       check.exprOrType(x, call.Fun)
 
        switch x.mode {
        case invalid:
                check.use(call.Args...)
-               x.expr = orig
+               x.expr = call
                return statement
 
        case typexpr:
@@ -72,7 +150,7 @@ func (check *Checker) call(x *operand, call *ast.CallExpr, orig ast.Expr) exprKi
                        check.use(call.Args...)
                        check.errorf(call.Args[n-1], _WrongArgCount, "too many arguments in conversion to %s", T)
                }
-               x.expr = orig
+               x.expr = call
                return conversion
 
        case builtin:
@@ -80,7 +158,7 @@ func (check *Checker) call(x *operand, call *ast.CallExpr, orig ast.Expr) exprKi
                if !check.builtin(x, call, id) {
                        x.mode = invalid
                }
-               x.expr = orig
+               x.expr = call
                // a non-constant result implies a function call
                if x.mode != invalid && x.mode != constant_ {
                        check.hasCallOrRecv = true
@@ -95,109 +173,18 @@ func (check *Checker) call(x *operand, call *ast.CallExpr, orig ast.Expr) exprKi
                if sig == nil {
                        check.invalidOp(x, _InvalidCall, "cannot call non-function %s", x)
                        x.mode = invalid
-                       x.expr = orig
+                       x.expr = call
                        return statement
                }
 
                // evaluate arguments
                args, ok := check.exprOrTypeList(call.Args)
-               if ok && call.Brackets && len(args) > 0 && args[0].mode != typexpr {
-                       check.errorf(args[0], _NotAType, "%s is not a type", args[0])
-                       ok = false
-               }
                if !ok {
                        x.mode = invalid
-                       x.expr = orig
-                       return expression
-               }
-
-               // instantiate function if needed
-               if n := len(args); n > 0 && len(sig.tparams) > 0 && args[0].mode == typexpr {
-                       // If the first argument is a type, assume we have explicit type arguments.
-
-                       // check number of type arguments
-                       if n > len(sig.tparams) {
-                               check.errorf(args[n-1], _Todo, "got %d type arguments but want %d", n, len(sig.tparams))
-                               x.mode = invalid
-                               x.expr = orig
-                               return expression
-                       }
-
-                       // collect types
-                       targs := make([]Type, n)
-                       // TODO(rFindley) use a positioner here? instantiate would need to be
-                       //                updated accordingly.
-                       poslist := make([]token.Pos, n)
-                       for i, a := range args {
-                               if a.mode != typexpr {
-                                       // error was reported earlier
-                                       x.mode = invalid
-                                       x.expr = orig
-                                       return expression
-                               }
-                               targs[i] = a.typ
-                               poslist[i] = a.Pos()
-                       }
-
-                       // if we don't have enough type arguments, use constraint type inference
-                       var inferred bool
-                       if n < len(sig.tparams) {
-                               var failed int
-                               targs, failed = check.inferB(sig.tparams, targs)
-                               if targs == nil {
-                                       // error was already reported
-                                       x.mode = invalid
-                                       x.expr = orig
-                                       return expression
-                               }
-                               if failed >= 0 {
-                                       // at least one type argument couldn't be inferred
-                                       assert(targs[failed] == nil)
-                                       tpar := sig.tparams[failed]
-                                       ppos := check.fset.Position(tpar.pos).String()
-                                       check.errorf(inNode(call, call.Rparen), 0, "cannot infer %s (%s) (%s)", tpar.name, ppos, targs)
-                                       x.mode = invalid
-                                       x.expr = orig
-                                       return expression
-                               }
-                               // all type arguments were inferred sucessfully
-                               if debug {
-                                       for _, targ := range targs {
-                                               assert(targ != nil)
-                                       }
-                               }
-                               n = len(targs)
-                               inferred = true
-                       }
-                       assert(n == len(sig.tparams))
-
-                       // instantiate function signature
-                       for i, typ := range targs {
-                               // some positions may be missing if types are inferred
-                               var pos token.Pos
-                               if i < len(poslist) {
-                                       pos = poslist[i]
-                               }
-                               check.ordinaryType(atPos(pos), typ)
-                       }
-                       res := check.instantiate(x.Pos(), sig, targs, poslist).(*Signature)
-                       assert(res.tparams == nil) // signature is not generic anymore
-                       if inferred {
-                               check.recordInferred(orig, targs, res)
-                       }
-                       x.typ = res
-                       x.mode = value
-                       x.expr = orig
+                       x.expr = call
                        return expression
                }
 
-               // If we reach here, orig must have been a regular call, not an index
-               // expression.
-               // TODO(rFindley) with a manually constructed AST it is possible to reach
-               //                this assertion. We should return an invalidAST error here
-               //                rather than panicking.
-               assert(!call.Brackets)
-
                sig = check.arguments(call, sig, args)
 
                // determine result
index c6ad511bd63a0a537ecdca8fb87e21e8b80f109b..fb74ae7ae25c15f8efb715f5629d1ad294e5c7dd 100644 (file)
@@ -50,7 +50,7 @@ func new[T any]() *T {
 // result type from the assignment to keep things simple and
 // easy to understand.
 var _ = new[int]()
-var _ *float64 = new(float64)() // the result type is indeed *float64
+var _ *float64 = new[float64]() // the result type is indeed *float64
 
 // A function may have multiple type parameters, of course.
 func foo[A, B, C any](a A, b []B, c *C) B {
@@ -59,7 +59,7 @@ func foo[A, B, C any](a A, b []B, c *C) B {
 }
 
 // As before, we can pass type parameters explicitly.
-var s = foo[int, string, float64](1, []string{"first"}, new(float64)())
+var s = foo[int, string, float64](1, []string{"first"}, new[float64]())
 
 // Or we can use type inference.
 var _ float64 = foo(42, []float64{1.0}, &s)
index 45cf8c6b417ce082662d7365d68755cfb600296f..77807e3b5b5e776d9f8a6173a8d42641ffc5c9cd 100644 (file)
@@ -1459,7 +1459,8 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 
                if x.mode == value {
                        if sig := asSignature(x.typ); sig != nil && len(sig.tparams) > 0 {
-                               return check.call(x, nil, e)
+                               check.funcInst(x, e)
+                               return expression
                        }
                }
 
@@ -1739,7 +1740,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                x.typ = T
 
        case *ast.CallExpr:
-               return check.call(x, e, e)
+               return check.call(x, e)
 
        case *ast.StarExpr:
                check.exprOrType(x, e.X)
index 0d9ae58dfc5a4d396338ccc368680982661d3640..9e073b1de02e92445bf501afbb822b698f23be38 100644 (file)
@@ -72,6 +72,14 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
                WriteExpr(buf, x.Index)
                buf.WriteByte(']')
 
+       case *ast.ListExpr:
+               for i, e := range x.ElemList {
+                       if i > 0 {
+                               buf.WriteString(", ")
+                       }
+                       WriteExpr(buf, e)
+               }
+
        case *ast.SliceExpr:
                WriteExpr(buf, x.X)
                buf.WriteByte('[')
@@ -98,16 +106,12 @@ func WriteExpr(buf *bytes.Buffer, x ast.Expr) {
 
        case *ast.CallExpr:
                WriteExpr(buf, x.Fun)
-               var l, r byte = '(', ')'
-               if x.Brackets {
-                       l, r = '[', ']'
-               }
-               buf.WriteByte(l)
+               buf.WriteByte('(')
                writeExprList(buf, x.Args)
                if x.Ellipsis.IsValid() {
                        buf.WriteString("...")
                }
-               buf.WriteByte(r)
+               buf.WriteByte(')')
 
        case *ast.StarExpr:
                buf.WriteByte('*')
index 36f9a45cca2b6d5f27d2fc4dccf48a7540eb348f..763ea48d38250ffbc4db7f0534088a88f3a1a80c 100644 (file)
@@ -494,13 +494,10 @@ L: // unpack receiver type
        }
 
        // unpack type parameters, if any
-       switch ptyp := rtyp.(type) {
-       case *ast.IndexExpr:
-               panic("unimplemented")
-       case *ast.CallExpr:
-               rtyp = ptyp.Fun
+       if ptyp, _ := rtyp.(*ast.IndexExpr); ptyp != nil {
+               rtyp = ptyp.X
                if unpackParams {
-                       for _, arg := range ptyp.Args {
+                       for _, arg := range unpackExpr(ptyp.Index) {
                                var par *ast.Ident
                                switch arg := arg.(type) {
                                case *ast.Ident:
index ac2dee36cbe046bd9bb06f98841d63cfd64ba356..2d4bb32c4b3451cbbe0ea18a36c3c03db99590ed 100644 (file)
@@ -21,7 +21,7 @@ func _() {
        eql(x, x)
        eql(y, y)
        eql(y, nil)
-       eql(io.Reader)(nil, nil)
+       eql[io.Reader](nil, nil)
 }
 
 // If we have a receiver of pointer type (below: *T) we must ignore
@@ -55,8 +55,8 @@ func (T) m1()
 func (*T) m2()
 
 func _() {
-       f2(T /* ERROR wrong method signature */ )()
-       f2(*T)()
+       f2[T /* ERROR wrong method signature */]()
+       f2[*T]()
 }
 
 // When a type parameter is used as an argument to instantiate a parameterized
@@ -244,7 +244,7 @@ func append[T interface{}, S sliceOf[T], T2 interface{ type T }](s S, t ...T2) S
 
 var f           func()
 var cancelSlice []context.CancelFunc
-var _ = append(context.CancelFunc, []context.CancelFunc, context.CancelFunc)(cancelSlice, f)
+var _ = append[context.CancelFunc, []context.CancelFunc, context.CancelFunc](cancelSlice, f)
 
 // A generic function must be instantiated with a type, not a value.
 
index bdf6d560828cccdfa088d696e1143af801fe5e9b..2dd8f64dc0b9771357f57e1e138b4e6cce734be0 100644 (file)
@@ -38,7 +38,7 @@ var _ = f(0 /* ERROR cannot use 0 .* as \[\]chan int */ )
 func swap[A, B any](a A, b B) (B, A) { return b, a }
 
 var _ = swap /* ERROR single value is expected */ [int, float32](1, 2)
-var f32, i = swap[int, float32](swap(float32, int)(1, 2))
+var f32, i = swap[int, float32](swap[float32, int](1, 2))
 var _ float32 = f32
 var _ int = i
 
@@ -76,11 +76,11 @@ var _ *int = new[int]()
 func _[T any](map[T /* ERROR incomparable map key type T \(missing comparable constraint\) */]int) // w/o constraint we don't know if T is comparable
 
 func f1[T1 any](struct{T1}) int
-var _ = f1(int)(struct{T1}{})
+var _ = f1[int](struct{T1}{})
 type T1 = int
 
 func f2[t1 any](struct{t1; x float32}) int
-var _ = f2(t1)(struct{t1; x float32}{})
+var _ = f2[t1](struct{t1; x float32}{})
 type t1 = int
 
 
@@ -216,9 +216,9 @@ var _ = f8(1) /* ERROR not enough arguments */
 var _ = f8(1, 2.3)
 var _ = f8(1, 2.3, 3.4, 4.5)
 var _ = f8(1, 2.3, 3.4, 4 /* ERROR does not match */ )
-var _ = f8(int, float64)(1, 2.3, 3.4, 4)
+var _ = f8[int, float64](1, 2.3, 3.4, 4)
 
-var _ = f8(int, float64)(0, 0, nil...) // test case for #18268
+var _ = f8[int, float64](0, 0, nil...) // test case for #18268
 
 // init functions cannot have type parameters
 
@@ -271,7 +271,7 @@ type A[T any] T
 func (a A[T]) m() A[T]
 
 func _[T any]() {
-       f12(A[T])()
+       f12[A[T]]()
 }
 
 // method expressions
index 503f9c71aca63501fc2798e5219aa4d2a6b78eec..53c87f20d54a03f6b3747517f6b141a3e4c1542c 100644 (file)
@@ -208,21 +208,28 @@ func isubst(x ast.Expr, smap map[*ast.Ident]*ast.Ident) ast.Expr {
                        new.X = X
                        return &new
                }
-       case *ast.CallExpr:
-               var args []ast.Expr
-               for i, arg := range n.Args {
-                       new := isubst(arg, smap)
-                       if new != arg {
-                               if args == nil {
-                                       args = make([]ast.Expr, len(n.Args))
-                                       copy(args, n.Args)
+       case *ast.IndexExpr:
+               index := isubst(n.Index, smap)
+               if index != n.Index {
+                       new := *n
+                       new.Index = index
+                       return &new
+               }
+       case *ast.ListExpr:
+               var elems []ast.Expr
+               for i, elem := range n.ElemList {
+                       new := isubst(elem, smap)
+                       if new != elem {
+                               if elems == nil {
+                                       elems = make([]ast.Expr, len(n.ElemList))
+                                       copy(elems, n.ElemList)
                                }
-                               args[i] = new
+                               elems[i] = new
                        }
                }
-               if args != nil {
+               if elems != nil {
                        new := *n
-                       new.Args = args
+                       new.ElemList = elems
                        return &new
                }
        case *ast.ParenExpr:
@@ -460,14 +467,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
                }
 
        case *ast.IndexExpr:
-               return check.instantiatedType(e.X, []ast.Expr{e.Index}, def)
-
-       case *ast.CallExpr:
-               if e.Brackets {
-                       return check.instantiatedType(e.Fun, e.Args, def)
-               } else {
-                       check.errorf(e0, _NotAType, "%s is not a type", e0)
-               }
+               return check.instantiatedType(e.X, unpackExpr(e.Index), def)
 
        case *ast.ParenExpr:
                // Generic types must be instantiated before they can be used in any form.
@@ -1158,10 +1158,6 @@ func embeddedFieldIdent(e ast.Expr) *ast.Ident {
                return e.Sel
        case *ast.IndexExpr:
                return embeddedFieldIdent(e.X)
-       case *ast.CallExpr:
-               if e.Brackets {
-                       return embeddedFieldIdent(e.Fun)
-               }
        }
        return nil // invalid embedded field
 }