package types
import (
)
func ( *Checker) ( *operand, *ast.Ident, *Named, bool) {
.mode = invalid
.expr =
, := .scope.LookupParent(.Name, .pos)
switch {
case nil:
if .Name == "_" {
if := .recvTParamMap[]; != nil {
.mode = typexpr
.typ =
} else {
.error(, _InvalidBlank, "cannot use _ as value or type")
}
} else {
.errorf(, _UndeclaredName, "undeclared name: %s", .Name)
}
return
case universeAny, universeComparable:
if !.allowVersion(.pkg, 1, 18) {
.errorf(, _UndeclaredName, "undeclared name: %s (requires version go1.18 or later)", .Name)
return
}
}
.recordUse(, )
:= .Type()
if , := .(*TypeName); == nil || && {
.objDecl(, )
= .Type()
}
assert( != nil)
if := .dotImportMap[dotImportKey{, .Name()}]; != nil {
.used = true
}
switch obj := .(type) {
case *PkgName:
.errorf(, _InvalidPkgUse, "use of package %s not in selector", .name)
return
case *Const:
.addDeclDep()
if == Typ[Invalid] {
return
}
if == universeIota {
if .iota == nil {
.errorf(, _InvalidIota, "cannot use iota outside constant declaration")
return
}
.val = .iota
} else {
.val = .val
}
assert(.val != nil)
.mode = constant_
case *TypeName:
if .isBrokenAlias() {
.errorf(, _InvalidDeclCycle, "invalid use of type alias %s in recursive type (see issue #50729)", .name)
return
}
.mode = typexpr
case *Var:
if .pkg == .pkg {
.used = true
}
.addDeclDep()
if == Typ[Invalid] {
return
}
.mode = variable
case *Func:
.addDeclDep()
.mode = value
case *Builtin:
.id = .id
.mode = builtin
case *Nil:
.mode = value
default:
unreachable()
}
.typ =
}
func ( *Checker) ( ast.Expr) Type {
return .definedType(, nil)
}
func ( *Checker) ( ast.Expr) Type {
:= .definedType(, nil)
.validVarType(, )
return
}
func ( *Checker) ( ast.Expr, Type) {
if isTypeParam() {
return
}
.later(func() {
if , := under().(*Interface); != nil {
:= computeInterfaceTypeSet(, .Pos(), )
if !.IsMethodSet() {
if .comparable {
.softErrorf(, _MisplacedConstraintIface, "interface is (or embeds) comparable")
} else {
.softErrorf(, _MisplacedConstraintIface, "interface contains type constraints")
}
}
}
})
}
func ( *Checker) ( ast.Expr, *Named) Type {
:= .typInternal(, )
assert(isTyped())
if isGeneric() {
.errorf(, _WrongTypeArgCount, "cannot use generic type %s without instantiation", )
= Typ[Invalid]
}
.recordTypeAndValue(, typexpr, , nil)
return
}
func ( *Checker) ( ast.Expr, *string) Type {
:= .typInternal(, nil)
assert(isTyped())
if != Typ[Invalid] && !isGeneric() {
if != nil {
* = .sprintf("%s is not a generic type", )
}
= Typ[Invalid]
}
.recordTypeAndValue(, typexpr, , nil)
return
}
func ( Type) string {
return strings.ReplaceAll(fmt.Sprintf("%T", ), "types.", "")
}
func ( *Checker) ( ast.Expr, *Named) ( Type) {
if trace {
.trace(.Pos(), "-- type %s", )
.indent++
defer func() {
.indent--
var Type
if != nil {
= safeUnderlying()
}
if == {
.trace(.Pos(), "=> %s // %s", , goTypeName())
} else {
.trace(.Pos(), "=> %s (under = %s) // %s", , , goTypeName())
}
}()
}
switch e := .(type) {
case *ast.BadExpr:
case *ast.Ident:
var operand
.ident(&, , , true)
switch .mode {
case typexpr:
:= .typ
.setUnderlying()
return
case invalid:
case novalue:
.errorf(&, _NotAType, "%s used as type", &)
default:
.errorf(&, _NotAType, "%s is not a type", &)
}
case *ast.SelectorExpr:
var operand
.selector(&, , )
switch .mode {
case typexpr:
:= .typ
.setUnderlying()
return
case invalid:
case novalue:
.errorf(&, _NotAType, "%s used as type", &)
default:
.errorf(&, _NotAType, "%s is not a type", &)
}
case *ast.IndexExpr, *ast.IndexListExpr:
:= typeparams.UnpackIndexExpr()
if !.allowVersion(.pkg, 1, 18) {
.softErrorf(inNode(, .Lbrack), _UnsupportedFeature, "type instantiation requires go1.18 or later")
}
return .instantiatedType(, )
case *ast.ParenExpr:
return .definedType(.X, )
case *ast.ArrayType:
if .Len == nil {
:= new(Slice)
.setUnderlying()
.elem = .varType(.Elt)
return
}
:= new(Array)
.setUnderlying()
.len = .arrayLength(.Len)
.elem = .varType(.Elt)
if .len >= 0 {
return
}
case *ast.Ellipsis:
.error(, _InvalidDotDotDot, "invalid use of '...'")
.use(.Elt)
case *ast.StructType:
:= new(Struct)
.setUnderlying()
.structType(, )
return
case *ast.StarExpr:
:= new(Pointer)
.base = Typ[Invalid]
.setUnderlying()
.base = .varType(.X)
return
case *ast.FuncType:
:= new(Signature)
.setUnderlying()
.funcType(, nil, )
return
case *ast.InterfaceType:
:= .newInterface()
.setUnderlying()
if != nil {
.obj = .obj
}
.interfaceType(, , )
return
case *ast.MapType:
:= new(Map)
.setUnderlying()
.key = .varType(.Key)
.elem = .varType(.Value)
.later(func() {
if !Comparable(.key) {
var string
if isTypeParam(.key) {
= " (missing comparable constraint)"
}
.errorf(.Key, _IncomparableMapKey, "incomparable map key type %s%s", .key, )
}
})
return
case *ast.ChanType:
:= new(Chan)
.setUnderlying()
:= SendRecv
switch .Dir {
case ast.SEND | ast.RECV:
case ast.SEND:
= SendOnly
case ast.RECV:
= RecvOnly
default:
.invalidAST(, "unknown channel direction %d", .Dir)
}
.dir =
.elem = .varType(.Value)
return
default:
.errorf(, _NotAType, "%s is not a type", )
}
:= Typ[Invalid]
.setUnderlying()
return
}
func ( *Checker) ( *typeparams.IndexExpr, *Named) ( Type) {
:= .X.Pos()
if trace {
.trace(, "-- instantiating %s with %s", .X, .Indices)
.indent++
defer func() {
.indent--
.trace(, "=> %s", )
}()
}
var string
:= .genericType(.X, &)
if != "" {
.invalidOp(.Orig, _NotAGenericType, "%s (%s)", .Orig, )
}
if == Typ[Invalid] {
return
}
, := .(*Named)
if == nil {
panic(fmt.Sprintf("%v: cannot instantiate %v", .Pos(), ))
}
:= .typeList(.Indices)
if == nil {
.setUnderlying(Typ[Invalid])
return Typ[Invalid]
}
const = false
:= .bestContext(nil)
:= .instanceHash(, )
, := .lookup(, , ).(*Named)
if == nil {
:= NewTypeName(.Pos(), .obj.pkg, .obj.name, nil)
= .newNamed(, , nil, nil, nil)
.targs = newTypeList()
= .update(, , , ).(*Named)
}
.setUnderlying()
.resolver = func( *Context, *Named) (*TypeParamList, Type, *methodList) {
:= .orig.TypeParams().list()
:= .targs.list()
if && len() < len() {
:= .infer(.Orig, , , nil, nil)
if len() > len() {
.targs = newTypeList()
}
}
return expandNamed(, , )
}
.later(func() {
.resolve()
.resolver = nil
.recordInstance(.Orig, .TypeArgs().list(), )
if .validateTArgLen(, .tparams.Len(), .targs.Len()) {
if , := .verify(, .tparams.list(), .targs.list()); != nil {
:= .Pos()
if < len(.Indices) {
= .Indices[].Pos()
}
.softErrorf(atPos(), _InvalidTypeArg, .Error())
} else {
.mono.recordInstance(.pkg, , .tparams.list(), .targs.list(), .Indices)
}
}
.validType()
})
return
}
func ( *Checker) ( ast.Expr) int64 {
if , := .(*ast.Ident); != nil {
:= .lookup(.Name)
if == nil {
.errorf(, _InvalidArrayLen, "undeclared name %s for array length", .Name)
return -1
}
if , := .(*Const); ! {
.errorf(, _InvalidArrayLen, "invalid array length %s", .Name)
return -1
}
}
var operand
.expr(&, )
if .mode != constant_ {
if .mode != invalid {
.errorf(&, _InvalidArrayLen, "array length %s must be constant", &)
}
return -1
}
if isUntyped(.typ) || isInteger(.typ) {
if := constant.ToInt(.val); .Kind() == constant.Int {
if representableConst(, , Typ[Int], nil) {
if , := constant.Int64Val(); && >= 0 {
return
}
.errorf(&, _InvalidArrayLen, "invalid array length %s", &)
return -1
}
}
}
.errorf(&, _InvalidArrayLen, "array length %s must be integer", &)
return -1
}
func ( *Checker) ( []ast.Expr) []Type {
:= make([]Type, len())
for , := range {
:= .varType()
if == Typ[Invalid] {
= nil
}
if != nil {
[] =
}
}
return
}