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  // ----------------------------------------------------------------------------