package types
import (
)
func ( *Checker) ( *operand, *typeparams.IndexExpr) {
if !.allowVersion(.pkg, 1, 18) {
.softErrorf(inNode(.Orig, .Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later")
}
:= .typeList(.Indices)
if == nil {
.mode = invalid
.expr = .Orig
return
}
assert(len() == len(.Indices))
:= .typ.(*Signature)
, := len(), .TypeParams().Len()
if > {
.errorf(.Indices[-1], _WrongTypeArgCount, "got %d type arguments but want %d", , )
.mode = invalid
.expr = .Orig
return
}
if < {
= .infer(.Orig, .TypeParams().list(), , nil, nil)
if == nil {
.mode = invalid
.expr = .Orig
return
}
= len()
}
assert( == )
:= .instantiateSignature(.Pos(), , , .Indices)
assert(.TypeParams().Len() == 0)
.recordInstance(.Orig, , )
.typ =
.mode = value
.expr = .Orig
}
func ( *Checker) ( token.Pos, *Signature, []Type, []ast.Expr) ( *Signature) {
assert( != nil)
assert(len() == .TypeParams().Len())
if trace {
.trace(, "-- instantiating %s with %s", , )
.indent++
defer func() {
.indent--
.trace(, "=> %s (under = %s)", , .Underlying())
}()
}
:= .instance(, , , .bestContext(nil)).(*Signature)
assert(len() <= len())
.later(func() {
:= .TypeParams().list()
if , := .verify(, , ); != nil {
:=
if < len() {
= [].Pos()
}
.softErrorf(atPos(), _InvalidTypeArg, "%s", )
} else {
.mono.recordInstance(.pkg, , , , )
}
})
return
}
func ( *Checker) ( *operand, *ast.CallExpr) exprKind {
:= typeparams.UnpackIndexExpr(.Fun)
if != nil {
if .indexExpr(, ) {
assert(.mode == value)
} else {
= nil
}
.expr = .Fun
.record()
} else {
.exprOrType(, .Fun, true)
}
switch .mode {
case invalid:
.use(.Args...)
.expr =
return statement
case typexpr:
.nonGeneric()
if .mode == invalid {
return conversion
}
:= .typ
.mode = invalid
switch := len(.Args); {
case 0:
.errorf(inNode(, .Rparen), _WrongArgCount, "missing argument in conversion to %s", )
case 1:
.expr(, .Args[0])
if .mode != invalid {
if .Ellipsis.IsValid() {
.errorf(.Args[0], _BadDotDotDotSyntax, "invalid use of ... in conversion to %s", )
break
}
if , := under().(*Interface); != nil && !isTypeParam() {
if !.IsMethodSet() {
.errorf(, _MisplacedConstraintIface, "cannot use interface %s in conversion (contains specific type constraints or is comparable)", )
break
}
}
.conversion(, )
}
default:
.use(.Args...)
.errorf(.Args[-1], _WrongArgCount, "too many arguments in conversion to %s", )
}
.expr =
return conversion
case builtin:
:= .id
if !.builtin(, , ) {
.mode = invalid
}
.expr =
if .mode != invalid && .mode != constant_ {
.hasCallOrRecv = true
}
return predeclaredFuncs[].kind
}
:= .mode == cgofunc
, := coreType(.typ).(*Signature)
if == nil {
.invalidOp(, _InvalidCall, "cannot call non-function %s", )
.mode = invalid
.expr =
return statement
}
var []ast.Expr
var []Type
if != nil {
= .Indices
= .typeList()
if == nil {
.use(.Args...)
.mode = invalid
.expr =
return statement
}
assert(len() == len())
, := len(), .TypeParams().Len()
if > {
.errorf([], _WrongTypeArgCount, "got %d type arguments but want %d", , )
.use(.Args...)
.mode = invalid
.expr =
return statement
}
}
, := .exprList(.Args, false)
:= .TypeParams().Len() > 0
= .arguments(, , , , )
if && .TypeParams().Len() == 0 {
.recordTypeAndValue(.Fun, value, , nil)
}
switch .results.Len() {
case 0:
.mode = novalue
case 1:
if {
.mode = commaerr
} else {
.mode = value
}
.typ = .results.vars[0].typ
default:
.mode = value
.typ = .results
}
.expr =
.hasCallOrRecv = true
if .mode == value && .TypeParams().Len() > 0 && isParameterized(.TypeParams().list(), .typ) {
.mode = invalid
}
return statement
}
func ( *Checker) ( []ast.Expr, bool) ( []*operand, bool) {
switch len() {
case 0:
case 1:
:= [0]
var operand
.multiExpr(&, )
if , := .typ.(*Tuple); && .mode != invalid {
= make([]*operand, .Len())
for , := range .vars {
[] = &operand{mode: value, expr: , typ: .typ}
}
break
}
= []*operand{&}
if && (.mode == mapindex || .mode == commaok || .mode == commaerr) {
:= &operand{mode: value, expr: , typ: Typ[UntypedBool]}
if .mode == commaerr {
.typ = universeError
}
= append(, )
= true
}
default:
= make([]*operand, len())
for , := range {
var operand
.expr(&, )
[] = &
}
}
return
}
func ( *Checker) ( *ast.CallExpr, *Signature, []Type, []*operand, []ast.Expr) ( *Signature) {
=
for , := range {
switch .mode {
case typexpr:
.errorf(, 0, "%s used as value", )
return
case invalid:
return
}
}
:= len()
:= .params.Len()
:= .Ellipsis.IsValid()
:= .params
:= false
if .variadic {
if {
if len(.Args) == 1 && > 1 {
.errorf(inNode(, .Ellipsis), _InvalidDotDotDot, "cannot use ... with %d-valued %s", , .Args[0])
return
}
} else {
if >= -1 {
:= make([]*Var, -1)
copy(, .params.vars)
:= .params.vars[-1]
:= .typ.(*Slice).elem
for len() < {
= append(, NewParam(.pos, .pkg, .name, ))
}
= NewTuple(...)
= true
=
} else {
--
}
}
} else {
if {
.errorf(inNode(, .Ellipsis), _NonVariadicDotDotDot, "cannot use ... in call to non-variadic %s", .Fun)
return
}
}
if != {
var positioner =
:= "not enough"
if > {
= [].expr
= "too many"
} else {
= atPos(.Rparen)
}
var []*Var
if .params != nil {
= .params.vars
}
.errorf(, _WrongArgCount, "%s arguments in call to %s\n\thave %s\n\twant %s",
, .Fun,
.typesSummary(operandTypes(), false),
.typesSummary(varTypes(), .variadic),
)
return
}
if .TypeParams().Len() > 0 {
if !.allowVersion(.pkg, 1, 18) {
switch .Fun.(type) {
case *ast.IndexExpr, *ast.IndexListExpr:
:= typeparams.UnpackIndexExpr(.Fun)
.softErrorf(inNode(.Fun, .Lbrack), _UnsupportedFeature, "function instantiation requires go1.18 or later")
default:
.softErrorf(inNode(, .Lparen), _UnsupportedFeature, "implicit function instantiation requires go1.18 or later")
}
}
:= .infer(, .TypeParams().list(), , , )
if == nil {
return
}
= .instantiateSignature(.Pos(), , , )
assert(.TypeParams().Len() == 0)
.recordInstance(.Fun, , )
if {
= .subst(.Pos(), , makeSubstMap(.TypeParams().list(), ), nil).(*Tuple)
} else {
= .params
}
}
if len() > 0 {
:= .sprintf("argument to %s", .Fun)
for , := range {
.assignment(, .vars[].typ, )
}
}
return
}
var cgoPrefixes = [...]string{
"_Ciconst_",
"_Cfconst_",
"_Csconst_",
"_Ctype_",
"_Cvar_",
"_Cfpvar_fp_",
"_Cfunc_",
"_Cmacro_",
}
func ( *Checker) ( *operand, *ast.SelectorExpr, *Named) {
var (
Object
[]int
bool
)
:= .Sel.Name
if , := .X.(*ast.Ident); {
:= .lookup(.Name)
if , := .(*PkgName); != nil {
assert(.pkg == .pkg)
.recordUse(, )
.used = true
:= .imported
var Object
:= value
if .cgo {
if == "malloc" {
= "_CMalloc"
} else {
= cgofunc
}
for , := range cgoPrefixes {
_, = .scope.LookupParent(+, .pos)
if != nil {
break
}
}
if == nil {
.errorf(.Sel, _UndeclaredImportedName, "%s not declared by package C", )
goto
}
.objDecl(, nil)
} else {
= .scope.Lookup()
if == nil {
if !.fake {
.errorf(.Sel, _UndeclaredImportedName, "%s not declared by package %s", , .name)
}
goto
}
if !.Exported() {
.errorf(.Sel, _UnexportedName, "%s not exported by package %s", , .name)
}
}
.recordUse(.Sel, )
switch exp := .(type) {
case *Const:
assert(.Val() != nil)
.mode = constant_
.typ = .typ
.val = .val
case *TypeName:
.mode = typexpr
.typ = .typ
case *Var:
.mode = variable
.typ = .typ
if .cgo && strings.HasPrefix(.name, "_Cvar_") {
.typ = .typ.(*Pointer).base
}
case *Func:
.mode =
.typ = .typ
if .cgo && strings.HasPrefix(.name, "_Cmacro_") {
.mode = value
.typ = .typ.(*Signature).results.vars[0].typ
}
case *Builtin:
.mode = builtin
.typ = .typ
.id = .id
default:
.dump("%v: unexpected object %v", .Sel.Pos(), )
unreachable()
}
.expr =
return
}
}
.exprOrType(, .X, false)
switch .mode {
case typexpr:
if != nil && .typ == {
.cycleError([]Object{.obj})
goto
}
case builtin:
.errorf(.Sel, _UncalledBuiltin, "cannot select on %s", )
goto
case invalid:
goto
}
, , = LookupFieldOrMethod(.typ, .mode == variable, .pkg, )
if == nil {
if under(.typ) == Typ[Invalid] {
goto
}
if != nil {
.errorf(.Sel, _AmbiguousSelector, "ambiguous selector %s.%s", .expr, )
goto
}
if {
.errorf(.Sel, _InvalidMethodExpr, "cannot call pointer method %s on %s", , .typ)
goto
}
var string
if isInterfacePtr(.typ) {
= .interfacePtrError(.typ)
} else {
= .sprintf("type %s has no field or method %s", .typ, )
if len() > 0 {
var string
if := rune([0]); unicode.IsUpper() {
= string(unicode.ToLower()) + [1:]
} else {
= string(unicode.ToUpper()) + [1:]
}
if , _, _ = LookupFieldOrMethod(.typ, .mode == variable, .pkg, ); != nil {
+= ", but does have " +
}
}
}
.errorf(.Sel, _MissingFieldOrMethod, "%s.%s undefined (%s)", .expr, , )
goto
}
if , := .(*Func); != nil {
.objDecl(, nil)
}
if .mode == typexpr {
, := .(*Func)
if == nil {
.errorf(.Sel, _MissingFieldOrMethod, "%s.%s undefined (type %s has no method %s)", .expr, , .typ, )
goto
}
.recordSelection(, MethodExpr, .typ, , , )
:= .typ.(*Signature)
if .recv == nil {
.error(, _InvalidDeclCycle, "illegal cycle in method declaration")
goto
}
var []*Var
if .params != nil {
= .params.vars
}
:= ""
if len() > 0 && [0].name != "" {
= .recv.name
if == "" {
= "_"
}
}
= append([]*Var{NewVar(.recv.pos, .recv.pkg, , .typ)}, ...)
.mode = value
.typ = &Signature{
tparams: .tparams,
params: NewTuple(...),
results: .results,
variadic: .variadic,
}
.addDeclDep()
} else {
switch obj := .(type) {
case *Var:
.recordSelection(, FieldVal, .typ, , , )
if .mode == variable || {
.mode = variable
} else {
.mode = value
}
.typ = .typ
case *Func:
.recordSelection(, MethodVal, .typ, , , )
:= true
if ! && debug {
:= .typ
if .mode == variable {
if , := .(*Pointer); ! && !IsInterface() {
= &Pointer{base: }
}
}
:= NewMethodSet()
if := .Lookup(.pkg, ); == nil || .obj != {
.dump("%v: (%s).%v -> %s", .Pos(), , .name, )
.dump("%s\n", )
panic("method sets and lookup don't agree")
}
}
.mode = value
:= *.typ.(*Signature)
.recv = nil
.typ = &
.addDeclDep()
default:
unreachable()
}
}
.expr =
return
:
.mode = invalid
.expr =
}
func ( *Checker) ( ...ast.Expr) {
var operand
for , := range {
if != nil {
.rawExpr(&, , nil, false)
}
}
}
func ( *Checker) ( ...ast.Expr) {
var operand
for , := range {
var *Var
var bool
if , := unparen().(*ast.Ident); != nil {
if .Name == "_" {
continue
}
if , := .scope.LookupParent(.Name, token.NoPos); != nil {
if , := .(*Var); != nil && .pkg == .pkg {
=
= .used
}
}
}
.rawExpr(&, , nil, false)
if != nil {
.used =
}
}
}