Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FwP/add pointer receiver on generic #70959

Draft
wants to merge 1 commit into
base: release-branch.go1.23
Choose a base branch
from
Draft
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
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/noder/irgen.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info, map[*
base.ErrorfAt(m.makeXPos(terr.Pos), terr.Code, "%s", msg)
}

pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info)
pkg, err := conf.Check(base.Ctxt.Pkgpath, files, info) /*HERE MAN*/
base.ExitIfErrors()
if err != nil {
base.FatalfAt(src.NoXPos, "conf.Check error: %v", err)
Expand Down
9 changes: 8 additions & 1 deletion src/cmd/compile/internal/syntax/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ func NewName(pos Pos, value string) *Name {
return n
}

type ExprExported = expr

func (n *Name) GetExprExported() ExprExported {
return n.expr
}

type (
Expr interface {
Node
Expand All @@ -147,7 +153,8 @@ type (

// Value
Name struct {
Value string
Value string
IsPointer bool
expr
}

Expand Down
53 changes: 51 additions & 2 deletions src/cmd/compile/internal/syntax/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package syntax

import (
"encoding/json"
"fmt"
"go/build/constraint"
"io"
Expand Down Expand Up @@ -1867,7 +1868,10 @@ func (p *parser) embeddedTerm() Expr {
}

// ParameterDecl = [ IdentifierList ] [ "..." ] Type .
func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
func (p *parser) paramDeclOrNil(name *Name, follow token) (f *Field) {
if follow == _Rbrack {
fmt.Println("KADAL", name, follow)
}
if trace {
defer p.trace("paramDeclOrNil")()
}
Expand All @@ -1883,14 +1887,44 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
return p.embeddedElem(nil)
}

f := new(Field)
f = new(Field)
f.pos = pos

var isPointer bool = false
if follow == _Rbrack {
fmt.Println("CLURUT", p.tok, p.op == Mul)
}
if follow == _Rbrack && p.tok == _Star && p.op == Mul {
isPointer = true
defer func() {
if f == nil {
return
}
nameType, ok := f.Type.(*Name)
if !ok {
return
}
nameType.IsPointer = isPointer
f.Type = nameType
return
}()
p.next()
fmt.Println("TIKUS", p.tok, p.op)
}

if follow == _Rbrack {
fmt.Println("KADAL1", name, follow, p.tok, _Name, name)
}

if p.tok == _Name || name != nil {
if follow == _Rbrack {
fmt.Println("KADAL2", name, follow)
}
// name
if name == nil {
name = p.name()
}
name.IsPointer = isPointer

if p.tok == _Lbrack {
// name "[" ...
Expand Down Expand Up @@ -1970,6 +2004,21 @@ func (p *parser) paramDeclOrNil(name *Name, follow token) *Field {
// If typ != nil, name must be != nil, and (name, typ) is the first field in the list.
// In the result list, either all fields have a name, or no field has a name.
func (p *parser) paramList(name *Name, typ Expr, close token, requireNames bool) (list []*Field) {
isGenericFuncDecl := false
if name == nil && typ == nil && close == _Rbrack && requireNames {
isGenericFuncDecl = true
}

defer func() {
if !isGenericFuncDecl {
return
}

for _, field := range list {
res, err := json.Marshal(field)
fmt.Printf("- parse: %T %s %v\n", field.Type, res, err)
}
}()
if trace {
defer p.trace("paramList")()
}
Expand Down
38 changes: 37 additions & 1 deletion src/cmd/compile/internal/types2/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ package types2

import (
"cmd/compile/internal/syntax"
"encoding/json"
"fmt"
. "internal/types/errors"
"strings"
)
Expand Down Expand Up @@ -130,6 +132,11 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt
}

func (check *Checker) instantiateSignature(pos syntax.Pos, expr syntax.Expr, typ *Signature, targs []Type, xlist []syntax.Expr) (res *Signature) {
fmt.Println("[instantiateSignature] KW1")
for _, tp := range typ.TypeParams().list() {
fmt.Printf(" - %T %v %s %t\n", tp, tp, tp.obj.name, tp.obj.isPointer)
}

assert(check != nil)
assert(len(targs) == typ.TypeParams().Len())

Expand All @@ -149,6 +156,11 @@ func (check *Checker) instantiateSignature(pos syntax.Pos, expr syntax.Expr, typ

// verify instantiation lazily (was go.dev/issue/50450)
check.later(func() {
fmt.Println("[instantiateSignature] KW2")
for _, tp := range typ.TypeParams().list() {
fmt.Printf(" - %T %v %s %t\n", tp, tp, tp.obj.name, tp.obj.isPointer)
}

tparams := typ.TypeParams().list()
if i, err := check.verify(pos, tparams, targs, check.context()); err != nil {
// best position for error reporting
Expand All @@ -166,6 +178,10 @@ func (check *Checker) instantiateSignature(pos syntax.Pos, expr syntax.Expr, typ
}

func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {
fmt.Printf(" - BEFORE: %T %v %T\n", x.typ, x.typ, call.Fun)
if cf, ok := call.Fun.(*syntax.Name); ok && cf != nil {
fmt.Println(cf.Value, "cf.IsPointer", cf.IsPointer)
}
var inst *syntax.IndexExpr // function instantiation, if any
if iexpr, _ := call.Fun.(*syntax.IndexExpr); iexpr != nil {
if check.indexExpr(x, iexpr) {
Expand Down Expand Up @@ -241,6 +257,9 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {

// a type parameter may be "called" if all types have the same signature
sig, _ := coreType(x.typ).(*Signature)
fmt.Println("[callExpr]")
fmt.Printf(" - AFTER: %T %v\n", x.typ, x.typ)
fmt.Printf(" - %T %v\n", sig, sig)
if sig == nil {
check.errorf(x, InvalidCall, invalidOp+"cannot call non-function %s", x)
x.mode = invalid
Expand All @@ -250,6 +269,10 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {

// Capture wasGeneric before sig is potentially instantiated below.
wasGeneric := sig.TypeParams().Len() > 0
fmt.Println("callExpr", wasGeneric)
for _, tp := range sig.TypeParams().list() {
fmt.Printf(" - %T %v %s %t\n", tp, tp, tp.obj.name, tp.obj.isPointer)
}

// evaluate type arguments, if any
var xlist []syntax.Expr
Expand Down Expand Up @@ -292,6 +315,12 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind {

// evaluate arguments
args, atargs, atxlist := check.genericExprList(call.ArgList)

fmt.Println("callExpr-2", wasGeneric)
for _, tp := range sig.TypeParams().list() {
fmt.Printf(" - %T %v %s %t\n", tp, tp, tp.obj.name, tp.obj.isPointer)
}

sig = check.arguments(call, sig, targs, xlist, args, atargs, atxlist)

if wasGeneric && sig.TypeParams().Len() == 0 {
Expand Down Expand Up @@ -603,6 +632,13 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
// of the generic function arguments, where mi = args[i].typ.(*Signature).TypeParams().Len().

// infer missing type arguments of callee and function arguments
if len(tparams) > 0 {
// fmt.Println("Call:", string(debugPkg.Stack()))
}
for i, tparam := range tparams {
objJson, errJson := json.Marshal(tparam.obj)
fmt.Printf("tparams[%d].obj (%s,%v) %T %s-%t\n", i, objJson, errJson, tparam.obj, tparam.obj.name, tparam.obj.isPointer)
}
if len(tparams) > 0 {
err := check.newError(CannotInferTypeArgs)
targs = check.infer(call.Pos(), tparams, targs, sigParams, args, false, err)
Expand All @@ -612,7 +648,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
// Perhaps instantiate as much as we can, also for arguments.
// This will require changes to how infer returns its results.
if !err.empty() {
check.errorf(err.pos(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg())
check.errorf(err.pos(), CannotInferTypeArgs, "in call to JANGKRIK %s, %s", call.Fun, err.msg())
}
return
}
Expand Down
5 changes: 5 additions & 0 deletions src/cmd/compile/internal/types2/decl.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package types2

import (
"cmd/compile/internal/syntax"
"encoding/json"
"fmt"
"go/constant"
"internal/buildcfg"
Expand Down Expand Up @@ -660,8 +661,12 @@ func (check *Checker) declareTypeParam(name *syntax.Name, scopePos syntax.Pos) *
// constraints to make sure we don't rely on them if they
// are not properly set yet.
tname := NewTypeName(name.Pos(), check.pkg, name.Value, nil)
tname.isPointer = name.IsPointer
tpar := check.newTypeParam(tname, Typ[Invalid]) // assigns type to tname as a side-effect
check.declare(check.scope, name, tname, scopePos)
nameJson, errJson := json.Marshal(name)
fmt.Printf("[declareTypeParam] param %T %s %v\n", name, nameJson, errJson)
fmt.Printf("[declareTypeParam] result %T %v %t %s\n", tpar.obj, tpar.obj, tpar.obj.isPointer, tpar.obj.name)
return tpar
}

Expand Down
21 changes: 20 additions & 1 deletion src/cmd/compile/internal/types2/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package types2

import (
"cmd/compile/internal/syntax"
"encoding/json"
"fmt"
"go/constant"
"go/token"
Expand Down Expand Up @@ -1071,6 +1072,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
x.mode = invalid
x.typ = Typ[Invalid]

// fmt.Printf("[exprInternal] %T %v\n", e, e)
switch e := e.(type) {
case nil:
panic("unreachable")
Expand All @@ -1079,7 +1081,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
goto Error // error was reported before

case *syntax.Name:
check.ident(x, e, nil, false)
check.ident(x, e, nil, false) // come here

case *syntax.DotsType:
// dots are handled explicitly where they are legal
Expand Down Expand Up @@ -1143,6 +1145,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
}).describef(e, "func literal")
}
x.mode = value
fmt.Println("HAH1")
x.typ = sig
} else {
check.errorf(e, InvalidSyntaxTree, "invalid function literal %v", e)
Expand Down Expand Up @@ -1367,6 +1370,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
}

x.mode = value
fmt.Println("HAH2")
x.typ = typ

case *syntax.ParenExpr:
Expand Down Expand Up @@ -1419,6 +1423,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
}
check.typeAssertion(e, x, T, false)
x.mode = commaok
fmt.Println("HAH3")
x.typ = T

case *syntax.TypeSwitchGuard:
Expand Down Expand Up @@ -1485,6 +1490,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
goto Error
}
x.mode = variable
fmt.Println("HAH4")
x.typ = base
}
break
Expand Down Expand Up @@ -1515,6 +1521,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
case *syntax.ArrayType, *syntax.SliceType, *syntax.StructType, *syntax.FuncType,
*syntax.InterfaceType, *syntax.MapType, *syntax.ChanType:
x.mode = typexpr
fmt.Println("HAH5")
x.typ = check.typ(e)
// Note: rawExpr (caller of exprInternal) will call check.recordTypeAndValue
// even though check.typ has already called it. This is fine as both
Expand Down Expand Up @@ -1618,6 +1625,18 @@ func (check *Checker) genericExpr(x *operand, e syntax.Expr) {
// If an error occurred, list[0] is not valid.
func (check *Checker) multiExpr(e syntax.Expr, allowCommaOk bool) (list []*operand, commaOk bool) {
var x operand
callExpr, ok := e.(*syntax.CallExpr)
if ok {
funJson, errJson := json.Marshal(callExpr.Fun)
fmt.Printf("TOKEK %T %s %v", callExpr.Fun, funJson, errJson)
fmt.Println("len(args)=", len(callExpr.ArgList))
for _, arg := range callExpr.ArgList {
argJson, errJson := json.Marshal(arg)
fmt.Printf(" - %T %s %v\n", arg, argJson, errJson)
}

}
fmt.Printf("[multiExpr] %v %T\n", e, e)
check.rawExpr(nil, &x, e, nil, false)
check.exclude(&x, 1<<novalue|1<<builtin|1<<typexpr)

Expand Down
2 changes: 2 additions & 0 deletions src/cmd/compile/internal/types2/infer.go
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
// a failure cause which allows for a better error message.
// Eventually, unify should return an error with cause.
var cause string
fmt.Printf("[infer] %s %t\n", tpar.obj.name, tpar.obj.isPointer)
constraint := tpar.iface()
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, exact) }, &cause); m != nil {
// TODO(gri) better error message (see TODO above)
Expand Down Expand Up @@ -498,6 +499,7 @@ func (check *Checker) renameTParams(pos syntax.Pos, tparams []*TypeParam, typ Ty
renameMap := makeRenameMap(tparams, tparams2)
for i, tparam := range tparams {
tparams2[i].bound = check.subst(pos, tparam.bound, renameMap, nil, check.context())
tparams2[i].obj.isPointer = tparams[i].obj.isPointer
}

return tparams2, check.subst(pos, typ, renameMap, nil, check.context())
Expand Down
10 changes: 10 additions & 0 deletions src/cmd/compile/internal/types2/instantiate.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,15 @@ func (check *Checker) verify(pos syntax.Pos, tparams []*TypeParam, targs []Type,
// need to instantiate it with the type arguments with which we instantiated
// the parameterized type.
bound := check.subst(pos, tpar.bound, smap, nil, ctxt)
fmt.Printf("[checker.verify] tpar.bound=(%v:%T), bound=(%v:%T)\n", tpar.bound, tpar.bound, bound, bound)
if boundNamed, ok := bound.(*Named); ok {
fmt.Printf("[checker.verify] boundNamed.obj=(%s,%t)\n", boundNamed.obj.name, boundNamed.obj.isPointer)
tparIface := tpar.iface()
if tparIface.isPointer {
boundNamed.obj.isPointer = true
bound = boundNamed
}
}
var cause string
if !check.implements(pos, targs[i], bound, true, &cause) {
return i, errors.New(cause)
Expand Down Expand Up @@ -274,6 +283,7 @@ func (check *Checker) implements(pos syntax.Pos, V, T Type, constraint bool, cau
}

// V must implement T's methods, if any.
fmt.Printf("[implements] %T %v\n", T, T)
if m, _ := check.missingMethod(V, T, true, Identical, cause); m != nil /* !Implements(V, T) */ {
if cause != nil {
*cause = check.sprintf("%s does not %s %s %s", V, verb, T, *cause)
Expand Down
2 changes: 2 additions & 0 deletions src/cmd/compile/internal/types2/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ type Interface struct {
complete bool // indicates that all fields (except for tset) are set up

tset *_TypeSet // type set described by this interface, computed lazily

isPointer bool
}

// typeSet returns the type set for interface t.
Expand Down
Loading