github.com/goplus/gox@v1.14.13-0.20240308130321-6ff7f61cfae8/typeparams.go (about) 1 /* 2 Copyright 2022 The GoPlus Authors (goplus.org) 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 http://www.apache.org/licenses/LICENSE-2.0 7 Unless required by applicable law or agreed to in writing, software 8 distributed under the License is distributed on an "AS IS" BASIS, 9 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 See the License for the specific language governing permissions and 11 limitations under the License. 12 */ 13 14 package gox 15 16 import ( 17 "fmt" 18 "go/ast" 19 "go/constant" 20 "go/token" 21 "go/types" 22 "log" 23 "strings" 24 _ "unsafe" 25 26 "github.com/goplus/gox/internal" 27 "github.com/goplus/gox/internal/goxdbg" 28 ) 29 30 // ---------------------------------------------------------------------------- 31 32 type TypeParam = types.TypeParam 33 type Union = types.Union 34 type Term = types.Term 35 type TypeParamList = types.TypeParamList 36 37 type inferFuncType struct { 38 pkg *Package 39 fn *internal.Elem 40 typ *types.Signature 41 targs []types.Type 42 src ast.Node 43 } 44 45 func newInferFuncType(pkg *Package, fn *internal.Elem, typ *types.Signature, targs []types.Type, src ast.Node) *inferFuncType { 46 return &inferFuncType{pkg: pkg, fn: fn, typ: typ, targs: targs, src: src} 47 } 48 49 func (p *inferFuncType) Type() types.Type { 50 fatal("infer of type") 51 return p.typ 52 } 53 54 func (p *inferFuncType) Underlying() types.Type { 55 fatal("infer of type") 56 return nil 57 } 58 59 func (p *inferFuncType) String() string { 60 return fmt.Sprintf("inferFuncType{typ: %v, targs: %v}", p.typ, p.targs) 61 } 62 63 func (p *inferFuncType) Instance() *types.Signature { 64 tyRet, err := inferFuncTargs(p.pkg, p.fn, p.typ, p.targs) 65 if err != nil { 66 pos := getSrcPos(p.src) 67 p.pkg.cb.panicCodeErrorf(pos, "%v", err) 68 } 69 return tyRet.(*types.Signature) 70 } 71 72 func (p *inferFuncType) InstanceWithArgs(args []*internal.Elem, flags InstrFlags) *types.Signature { 73 tyRet, err := inferFunc(p.pkg, p.fn, p.typ, p.targs, args, flags) 74 if err != nil { 75 pos := getSrcPos(p.src) 76 p.pkg.cb.panicCodeErrorf(pos, "%v", err) 77 } 78 return tyRet.(*types.Signature) 79 } 80 81 func isGenericType(typ types.Type) bool { 82 switch t := typ.(type) { 83 case *types.Named: 84 return t.Obj() != nil && t.TypeArgs() == nil && t.TypeParams() != nil 85 case *types.Signature: 86 return t.TypeParams() != nil 87 } 88 return false 89 } 90 91 func (p *CodeBuilder) instantiate(nidx int, args []*internal.Elem, src ...ast.Node) *CodeBuilder { 92 typ := args[0].Type 93 var tt bool 94 if t, ok := typ.(*TypeType); ok { 95 typ = t.Type() 96 tt = true 97 } 98 p.ensureLoaded(typ) 99 srcExpr := getSrc(src) 100 if !isGenericType(typ) { 101 pos := getSrcPos(srcExpr) 102 if tt { 103 p.panicCodeErrorf(pos, "%v is not a generic type", typ) 104 } else { 105 p.panicCodeErrorf(pos, "invalid operation: cannot index %v (value of type %v)", types.ExprString(args[0].Val), typ) 106 } 107 } 108 targs := make([]types.Type, nidx) 109 indices := make([]ast.Expr, nidx) 110 for i := 0; i < nidx; i++ { 111 targs[i] = args[i+1].Type.(*TypeType).Type() 112 p.ensureLoaded(targs[i]) 113 indices[i] = args[i+1].Val 114 } 115 var tyRet types.Type 116 var err error 117 if tt { 118 tyRet, err = types.Instantiate(p.ctxt, typ, targs, true) 119 if err == nil { 120 tyRet = NewTypeType(tyRet) 121 } 122 } else { 123 sig := typ.(*types.Signature) 124 if nidx >= sig.TypeParams().Len() { 125 tyRet, err = types.Instantiate(p.ctxt, typ, targs, true) 126 } else { 127 tyRet = newInferFuncType(p.pkg, args[0], sig, targs, srcExpr) 128 } 129 } 130 if err != nil { 131 pos := getSrcPos(srcExpr) 132 p.panicCodeErrorf(pos, "%v", err) 133 } 134 if debugMatch { 135 log.Println("==> InferType", tyRet) 136 } 137 elem := &internal.Elem{ 138 Type: tyRet, Src: srcExpr, 139 } 140 if nidx == 1 { 141 elem.Val = &ast.IndexExpr{X: args[0].Val, Index: indices[0]} 142 } else { 143 elem.Val = &ast.IndexListExpr{X: args[0].Val, Indices: indices} 144 } 145 p.stk.Ret(nidx+1, elem) 146 return p 147 } 148 149 type typesContext = types.Context 150 151 func newTypesContext() *typesContext { 152 return types.NewContext() 153 } 154 155 func toRecvType(pkg *Package, typ types.Type) ast.Expr { 156 var star bool 157 if t, ok := typ.(*types.Pointer); ok { 158 typ = t.Elem() 159 star = true 160 } 161 t, ok := typ.(*types.Named) 162 if !ok { 163 panic("unexpected: recv type must types.Named") 164 } 165 expr := toObjectExpr(pkg, t.Obj()) 166 if tparams := t.TypeParams(); tparams != nil { 167 n := tparams.Len() 168 indices := make([]ast.Expr, n) 169 for i := 0; i < n; i++ { 170 indices[i] = toObjectExpr(pkg, tparams.At(i).Obj()) 171 } 172 if n == 1 { 173 expr = &ast.IndexExpr{ 174 X: expr, 175 Index: indices[0], 176 } 177 } else { 178 expr = &ast.IndexListExpr{ 179 X: expr, 180 Indices: indices, 181 } 182 } 183 } 184 if star { 185 expr = &ast.StarExpr{X: expr} 186 } 187 return expr 188 } 189 190 func toNamedType(pkg *Package, t *types.Named) ast.Expr { 191 expr := toObjectExpr(pkg, t.Obj()) 192 if targs := t.TypeArgs(); targs != nil { 193 n := targs.Len() 194 indices := make([]ast.Expr, n) 195 for i := 0; i < n; i++ { 196 indices[i] = toType(pkg, targs.At(i)) 197 } 198 if n == 1 { 199 expr = &ast.IndexExpr{ 200 X: expr, 201 Index: indices[0], 202 } 203 } else { 204 expr = &ast.IndexListExpr{ 205 X: expr, 206 Indices: indices, 207 } 208 } 209 } 210 return expr 211 } 212 213 type operandMode byte 214 215 //type builtinId int 216 217 type operand struct { 218 mode operandMode 219 expr ast.Expr 220 typ types.Type 221 val constant.Value 222 //id builtinId 223 } 224 225 const ( 226 invalid operandMode = iota // operand is invalid 227 novalue // operand represents no value (result of a function call w/o result) 228 builtin // operand is a built-in function 229 typexpr // operand is a type 230 constant_ // operand is a constant; the operand's typ is a Basic type 231 variable // operand is an addressable variable 232 mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment) 233 value // operand is a computed value 234 commaok // like value, but operand may be used in a comma,ok expression 235 commaerr // like commaok, but second value is error, not boolean 236 cgofunc // operand is a cgo function 237 ) 238 239 type positioner interface { 240 Pos() token.Pos 241 } 242 243 //go:linkname checker_infer go/types.(*Checker).infer 244 func checker_infer(check *types.Checker, posn positioner, tparams []*types.TypeParam, targs []types.Type, params *types.Tuple, args []*operand) (result []types.Type) 245 246 func infer(pkg *Package, posn positioner, tparams []*types.TypeParam, targs []types.Type, params *types.Tuple, args []*operand) (result []types.Type, err error) { 247 conf := &types.Config{ 248 Error: func(e error) { 249 err = e 250 if terr, ok := e.(types.Error); ok { 251 err = fmt.Errorf("%s", terr.Msg) 252 } 253 }, 254 } 255 checker := types.NewChecker(conf, pkg.Fset, pkg.Types, nil) 256 result = checker_infer(checker, posn, tparams, targs, params, args) 257 return 258 } 259 260 func getParamsTypes(tuple *types.Tuple, variadic bool) string { 261 n := tuple.Len() 262 if n == 0 { 263 return "" 264 } 265 typs := make([]string, n) 266 for i := 0; i < n; i++ { 267 typs[i] = tuple.At(i).Type().String() 268 } 269 if variadic { 270 typs[n-1] = "..." + tuple.At(n-1).Type().(*types.Slice).Elem().String() 271 } 272 return strings.Join(typs, ", ") 273 } 274 275 func checkInferArgs(pkg *Package, fn *internal.Elem, sig *types.Signature, args []*internal.Elem, flags InstrFlags) ([]*internal.Elem, error) { 276 nargs := len(args) 277 nreq := sig.Params().Len() 278 if sig.Variadic() { 279 if nargs < nreq-1 { 280 caller := types.ExprString(fn.Val) 281 return nil, fmt.Errorf( 282 "not enough arguments in call to %s\n\thave (%v)\n\twant (%v)", caller, getTypes(args), getParamsTypes(sig.Params(), true)) 283 } 284 if flags&InstrFlagEllipsis != 0 { 285 return args, nil 286 } 287 var typ types.Type 288 if nargs < nreq { 289 typ = sig.Params().At(nreq - 1).Type() 290 elem := typ.(*types.Slice).Elem() 291 if t, ok := elem.(*types.TypeParam); ok { 292 return nil, fmt.Errorf("cannot infer %v (%v)", elem, pkg.cb.fset.Position(t.Obj().Pos())) 293 } 294 } else { 295 typ = types.NewSlice(types.Default(args[nreq-1].Type)) 296 } 297 res := make([]*internal.Elem, nreq) 298 for i := 0; i < nreq-1; i++ { 299 res[i] = args[i] 300 } 301 res[nreq-1] = &internal.Elem{Type: typ} 302 return res, nil 303 } else if nreq != nargs { 304 fewOrMany := "not enough" 305 if nargs > nreq { 306 fewOrMany = "too many" 307 } 308 caller := types.ExprString(fn.Val) 309 return nil, fmt.Errorf( 310 "%s arguments in call to %s\n\thave (%v)\n\twant (%v)", fewOrMany, caller, getTypes(args), getParamsTypes(sig.Params(), false)) 311 } 312 return args, nil 313 } 314 315 func inferFunc(pkg *Package, fn *internal.Elem, sig *types.Signature, targs []types.Type, args []*internal.Elem, flags InstrFlags) (types.Type, error) { 316 args, err := checkInferArgs(pkg, fn, sig, args, flags) 317 if err != nil { 318 return nil, err 319 } 320 xlist := make([]*operand, len(args)) 321 for i, arg := range args { 322 xlist[i] = &operand{ 323 mode: value, 324 expr: arg.Val, 325 typ: arg.Type, 326 val: arg.CVal, 327 } 328 } 329 tp := sig.TypeParams() 330 n := tp.Len() 331 tparams := make([]*types.TypeParam, n) 332 for i := 0; i < n; i++ { 333 tparams[i] = tp.At(i) 334 } 335 targs, err = infer(pkg, fn.Val, tparams, targs, sig.Params(), xlist) 336 if err != nil { 337 return nil, err 338 } 339 return types.Instantiate(pkg.cb.ctxt, sig, targs, true) 340 } 341 342 func inferFuncTargs(pkg *Package, fn *internal.Elem, sig *types.Signature, targs []types.Type) (types.Type, error) { 343 tp := sig.TypeParams() 344 n := tp.Len() 345 tparams := make([]*types.TypeParam, n) 346 for i := 0; i < n; i++ { 347 tparams[i] = tp.At(i) 348 } 349 targs, err := infer(pkg, fn.Val, tparams, targs, nil, nil) 350 if err != nil { 351 return nil, err 352 } 353 return types.Instantiate(pkg.cb.ctxt, sig, targs, true) 354 } 355 356 func toFieldListX(pkg *Package, t *types.TypeParamList) *ast.FieldList { 357 if t == nil { 358 return nil 359 } 360 n := t.Len() 361 flds := make([]*ast.Field, n) 362 for i := 0; i < n; i++ { 363 item := t.At(i) 364 names := []*ast.Ident{ast.NewIdent(item.Obj().Name())} 365 typ := toType(pkg, item.Constraint()) 366 flds[i] = &ast.Field{Names: names, Type: typ} 367 } 368 return &ast.FieldList{ 369 List: flds, 370 } 371 } 372 373 func toFuncType(pkg *Package, sig *types.Signature) *ast.FuncType { 374 params := toFieldList(pkg, sig.Params()) 375 results := toFieldList(pkg, sig.Results()) 376 if sig.Variadic() { 377 n := len(params) 378 if n == 0 { 379 panic("TODO: toFuncType error") 380 } 381 toVariadic(params[n-1]) 382 } 383 return &ast.FuncType{ 384 TypeParams: toFieldListX(pkg, sig.TypeParams()), 385 Params: &ast.FieldList{List: params}, 386 Results: &ast.FieldList{List: results}, 387 } 388 } 389 390 func toUnionType(pkg *Package, t *types.Union) ast.Expr { 391 var v ast.Expr 392 n := t.Len() 393 for i := 0; i < n; i++ { 394 term := t.Term(i) 395 typ := toType(pkg, term.Type()) 396 if term.Tilde() { 397 typ = &ast.UnaryExpr{ 398 Op: token.TILDE, 399 X: typ, 400 } 401 } 402 if n == 1 { 403 return typ 404 } 405 if i == 0 { 406 v = typ 407 } else { 408 v = &ast.BinaryExpr{ 409 X: v, 410 Op: token.OR, 411 Y: typ, 412 } 413 } 414 } 415 return v 416 } 417 418 func setTypeParams(pkg *Package, typ *types.Named, spec *ast.TypeSpec, tparams []*TypeParam) { 419 typ.SetTypeParams(tparams) 420 n := len(tparams) 421 if n == 0 { 422 spec.TypeParams = nil 423 return 424 } 425 flds := make([]*ast.Field, n) 426 for i := 0; i < n; i++ { 427 item := tparams[i] 428 names := []*ast.Ident{ast.NewIdent(item.Obj().Name())} 429 typ := toType(pkg, item.Constraint()) 430 flds[i] = &ast.Field{Names: names, Type: typ} 431 } 432 spec.TypeParams = &ast.FieldList{List: flds} 433 } 434 435 func interfaceIsImplicit(t *types.Interface) bool { 436 return t.IsImplicit() 437 } 438 439 // ---------------------------------------------------------------------------- 440 441 func boundTypeParams(p *Package, fn *Element, sig *types.Signature, args []*Element, flags InstrFlags) (*Element, *types.Signature, []*Element, error) { 442 if debugMatch { 443 log.Println("boundTypeParams:", goxdbg.Format(p.Fset, fn.Val), "sig:", sig, "args:", len(args), "flags:", flags) 444 } 445 params := sig.TypeParams() 446 if n := params.Len(); n > 0 { 447 from := 0 448 if (flags & instrFlagGoptFunc) != 0 { 449 from = 1 450 } 451 targs := make([]types.Type, n) 452 for i := 0; i < n; i++ { 453 arg := args[from+i] 454 t, ok := arg.Type.(*TypeType) 455 if !ok { 456 src, pos := p.cb.loadExpr(arg.Src) 457 err := p.cb.newCodeErrorf(pos, "%s (type %v) is not a type", src, arg.Type) 458 return fn, sig, args, err 459 } 460 targs[i] = t.typ 461 } 462 ret, err := types.Instantiate(p.cb.ctxt, sig, targs, true) 463 if err != nil { 464 return fn, sig, args, err 465 } 466 indices := make([]ast.Expr, n) 467 for i := 0; i < n; i++ { 468 indices[i] = args[from+i].Val 469 } 470 fn = &Element{Val: &ast.IndexListExpr{X: fn.Val, Indices: indices}, Type: ret, Src: fn.Src} 471 sig = ret.(*types.Signature) 472 if from > 0 { 473 args = append([]*Element{args[0]}, args[n+1:]...) 474 } else { 475 args = args[n:] 476 } 477 } 478 return fn, sig, args, nil 479 } 480 481 func (p *Package) Instantiate(orig types.Type, targs []types.Type, src ...ast.Node) types.Type { 482 p.cb.ensureLoaded(orig) 483 for _, targ := range targs { 484 p.cb.ensureLoaded(targ) 485 } 486 ctxt := p.cb.ctxt 487 if on, ok := CheckOverloadNamed(orig); ok { 488 var first error 489 for _, t := range on.Types { 490 ret, err := types.Instantiate(ctxt, t, targs, true) 491 if err == nil { 492 return ret 493 } 494 if first == nil { 495 first = err 496 } 497 } 498 p.cb.handleCodeError(getPos(src), first.Error()) 499 return types.Typ[types.Invalid] 500 } 501 if !isGenericType(orig) { 502 p.cb.handleCodeErrorf(getPos(src), "%v is not a generic type", orig) 503 return types.Typ[types.Invalid] 504 } 505 ret, err := types.Instantiate(ctxt, orig, targs, true) 506 if err != nil { 507 p.cb.handleCodeError(getPos(src), err.Error()) 508 } 509 return ret 510 } 511 512 // ----------------------------------------------------------------------------