From 377238e58ea0b228d02d2cb9f969bfe1a0763905 Mon Sep 17 00:00:00 2001 From: Febriananda Wida Pramudita Date: Sun, 22 Dec 2024 17:46:30 +0700 Subject: [PATCH] add change on pointer recv --- src/cmd/compile/internal/noder/irgen.go | 2 +- src/cmd/compile/internal/syntax/nodes.go | 9 +++- src/cmd/compile/internal/syntax/parser.go | 53 ++++++++++++++++++- src/cmd/compile/internal/types2/call.go | 38 ++++++++++++- src/cmd/compile/internal/types2/decl.go | 5 ++ src/cmd/compile/internal/types2/expr.go | 21 +++++++- src/cmd/compile/internal/types2/infer.go | 2 + .../compile/internal/types2/instantiate.go | 10 ++++ src/cmd/compile/internal/types2/interface.go | 2 + src/cmd/compile/internal/types2/lookup.go | 46 +++++++++++++++- src/cmd/compile/internal/types2/object.go | 15 +++--- src/cmd/compile/internal/types2/typeparam.go | 2 + src/cmd/compile/internal/types2/typexpr.go | 6 +++ src/compile.log | 1 + src/go/types/call.go | 2 +- 15 files changed, 199 insertions(+), 15 deletions(-) create mode 100644 src/compile.log diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go index a95fa03e170ed6..67878b46a6e5c8 100644 --- a/src/cmd/compile/internal/noder/irgen.go +++ b/src/cmd/compile/internal/noder/irgen.go @@ -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) diff --git a/src/cmd/compile/internal/syntax/nodes.go b/src/cmd/compile/internal/syntax/nodes.go index de277fc3d8cdab..edc0c31c8c2bbc 100644 --- a/src/cmd/compile/internal/syntax/nodes.go +++ b/src/cmd/compile/internal/syntax/nodes.go @@ -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 @@ -147,7 +153,8 @@ type ( // Value Name struct { - Value string + Value string + IsPointer bool expr } diff --git a/src/cmd/compile/internal/syntax/parser.go b/src/cmd/compile/internal/syntax/parser.go index 66570fe92a823b..fdce146d2fcf78 100644 --- a/src/cmd/compile/internal/syntax/parser.go +++ b/src/cmd/compile/internal/syntax/parser.go @@ -5,6 +5,7 @@ package syntax import ( + "encoding/json" "fmt" "go/build/constraint" "io" @@ -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")() } @@ -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 "[" ... @@ -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")() } diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 7df4e8250e4dcd..65c7250766e363 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -8,6 +8,8 @@ package types2 import ( "cmd/compile/internal/syntax" + "encoding/json" + "fmt" . "internal/types/errors" "strings" ) @@ -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()) @@ -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 @@ -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) { @@ -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 @@ -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 @@ -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 { @@ -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) @@ -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 } diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 6a266de7fd99ab..7b196535da5367 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -6,6 +6,7 @@ package types2 import ( "cmd/compile/internal/syntax" + "encoding/json" "fmt" "go/constant" "internal/buildcfg" @@ -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 } diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 92949a924dede1..93c4f16bd35021 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -8,6 +8,7 @@ package types2 import ( "cmd/compile/internal/syntax" + "encoding/json" "fmt" "go/constant" "go/token" @@ -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") @@ -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 @@ -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) @@ -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: @@ -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: @@ -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 @@ -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 @@ -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< %T %v\n", T, T) + fmt.Printf("[missingMethod] V -> %T %v\n", V, V) + if VPointer, ok := V.(*Pointer); ok { + fmt.Printf("[missingMethod] VPointer.base -> %T %v\n", VPointer.base, VPointer.base) + } else { + fmt.Printf("[missingMethod] V is not pointer\n") + } + + var isPointer bool = false + switch TType := T.(type) { + case *Interface: + if TType.isPointer { + isPointer = true + } + case *Named: + if TType.obj.isPointer { + isPointer = true + } + } + + if isPointer { + V = &Pointer{base: V} + } + methods := under(T).(*Interface).typeSet().methods // T must be an interface if len(methods) == 0 { return nil, false @@ -468,7 +512,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y case ambigSel: *cause = check.sprintf("(ambiguous selector %s.%s)", V, m.Name()) case ptrRecv: - *cause = check.sprintf("(method %s has pointer receiver)", m.Name()) + *cause = check.sprintf("(method BELALANG %s has pointer receiver)", m.Name()) case field: *cause = check.sprintf("(%s.%s is a field, not a method)", V, m.Name()) default: diff --git a/src/cmd/compile/internal/types2/object.go b/src/cmd/compile/internal/types2/object.go index f9a25473a15cd7..b44de702fdb924 100644 --- a/src/cmd/compile/internal/types2/object.go +++ b/src/cmd/compile/internal/types2/object.go @@ -97,6 +97,7 @@ type object struct { order_ uint32 color_ color scopePos_ syntax.Pos + isPointer bool } // color encodes the color of an object (see Checker.objDecl for details). @@ -233,7 +234,7 @@ type PkgName struct { // NewPkgName returns a new PkgName object representing an imported package. // The remaining arguments set the attributes found with all Objects. func NewPkgName(pos syntax.Pos, pkg *Package, name string, imported *Package) *PkgName { - return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos}, imported, false} + return &PkgName{object{nil, pos, pkg, name, Typ[Invalid], 0, black, nopos, false}, imported, false} } // Imported returns the package that was imported. @@ -249,7 +250,7 @@ type Const struct { // NewConst returns a new constant with value val. // The remaining arguments set the attributes found with all Objects. func NewConst(pos syntax.Pos, pkg *Package, name string, typ Type, val constant.Value) *Const { - return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, val} + return &Const{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos, false}, val} } // Val returns the constant's value. @@ -270,7 +271,7 @@ type TypeName struct { // argument for NewNamed, which will set the TypeName's type as a side- // effect. func NewTypeName(pos syntax.Pos, pkg *Package, name string, typ Type) *TypeName { - return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}} + return &TypeName{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos, false}} } // NewTypeNameLazy returns a new defined type like NewTypeName, but it @@ -321,19 +322,19 @@ type Var struct { // NewVar returns a new variable. // The arguments set the attributes found with all Objects. func NewVar(pos syntax.Pos, pkg *Package, name string, typ Type) *Var { - return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}} + return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos, false}} } // NewParam returns a new variable representing a function parameter. func NewParam(pos syntax.Pos, pkg *Package, name string, typ Type) *Var { - return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, used: true} // parameters are always 'used' + return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos, false}, used: true} // parameters are always 'used' } // NewField returns a new variable representing a struct field. // For embedded fields, the name is the unqualified type name // under which the field is accessible. func NewField(pos syntax.Pos, pkg *Package, name string, typ Type, embedded bool) *Var { - return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, embedded: embedded, isField: true} + return &Var{object: object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos, false}, embedded: embedded, isField: true} } // Anonymous reports whether the variable is an embedded field. @@ -383,7 +384,7 @@ func NewFunc(pos syntax.Pos, pkg *Package, name string, sig *Signature) *Func { // as this would violate object.{Type,color} invariants. // TODO(adonovan): propose to disallow NewFunc with nil *Signature. } - return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos}, false, nil} + return &Func{object{nil, pos, pkg, name, typ, 0, colorFor(typ), nopos, false}, false, nil} } // Signature returns the signature (type) of the function or method. diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index e22981e1ad0c00..5d26d103a791ea 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -142,6 +142,8 @@ func (t *TypeParam) iface() *Interface { computeInterfaceTypeSet(t.check, pos, ityp) } + ityp.isPointer = t.obj.isPointer + return ityp } diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 6c121ae0545959..1d5b618082be16 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -79,6 +79,12 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType // informative "not a type/value" error that this function's caller // will issue (see go.dev/issue/25790). typ := obj.Type() + // objJson, errJson := json.Marshal(obj) + // typJson, errTypJson := json.Marshal(typ) + // fmt.Printf("typ: e.Value=%s %T (%s, %v) type(obj)=%T (%s, %v)\n", e.Value, typ, typJson, errTypJson, obj, objJson, errJson) + // if e.Value == "Object" { + // fmt.Println(string(debugPkg.Stack())) + // } if typ == nil || gotType && wantType { check.objDecl(obj, def) typ = obj.Type() // type must have been assigned by Checker.objDecl diff --git a/src/compile.log b/src/compile.log new file mode 100644 index 00000000000000..330bcd6d9c7d98 --- /dev/null +++ b/src/compile.log @@ -0,0 +1 @@ +open main.go: no such file or directory diff --git a/src/go/types/call.go b/src/go/types/call.go index 8f02ffc39729a3..dc866ec5d73cd4 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -615,7 +615,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // 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.posn(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg()) + check.errorf(err.posn(), CannotInferTypeArgs, "in call to KUMBANG %s, %s", call.Fun, err.msg()) } return }