package types
import (
)
func ( *Checker) ( *operand, *typeparams.IndexExpr) ( bool) {
.exprOrType(, .X, true)
switch .mode {
case invalid:
.use(.Indices...)
return false
case typexpr:
.mode = invalid
.typ = .varType(.Orig)
if .typ != Typ[Invalid] {
.mode = typexpr
}
return false
case value:
if , := under(.typ).(*Signature); != nil && .TypeParams().Len() > 0 {
return true
}
}
.nonGeneric()
if .mode == invalid {
return false
}
:= false
:= int64(-1)
switch typ := under(.typ).(type) {
case *Basic:
if isString() {
= true
if .mode == constant_ {
= int64(len(constant.StringVal(.val)))
}
.mode = value
.typ = universeByte
}
case *Array:
= true
= .len
if .mode != variable {
.mode = value
}
.typ = .elem
case *Pointer:
if , := under(.base).(*Array); != nil {
= true
= .len
.mode = variable
.typ = .elem
}
case *Slice:
= true
.mode = variable
.typ = .elem
case *Map:
:= .singleIndex()
if == nil {
.mode = invalid
return false
}
var operand
.expr(&, )
.assignment(&, .key, "map index")
.mode = mapindex
.typ = .elem
.expr = .Orig
return false
case *Interface:
if !isTypeParam(.typ) {
break
}
var , Type
:= variable
if .typeSet().underIs(func( Type) bool {
:= int64(-1)
var , Type
switch t := .(type) {
case *Basic:
if isString() {
= universeByte
= value
}
case *Array:
= .len
= .elem
if .mode != variable {
= value
}
case *Pointer:
if , := under(.base).(*Array); != nil {
= .len
= .elem
}
case *Slice:
= .elem
case *Map:
= .key
= .elem
}
if == nil {
return false
}
if == nil {
=
, = ,
return true
}
if !Identical(, ) {
return false
}
if !Identical(, ) {
return false
}
if >= 0 && < {
=
}
return true
}) {
if != nil {
:= .singleIndex()
if == nil {
.mode = invalid
return false
}
var operand
.expr(&, )
.assignment(&, , "map index")
.mode = mapindex
.typ =
.expr =
return false
}
= true
.mode =
.typ =
}
}
if ! {
.invalidOp(, _NonIndexableOperand, "cannot index %s", )
.mode = invalid
return false
}
:= .singleIndex()
if == nil {
.mode = invalid
return false
}
if .typ == nil {
.typ = Typ[Invalid]
}
.index(, )
return false
}
func ( *Checker) ( *operand, *ast.SliceExpr) {
.expr(, .X)
if .mode == invalid {
.use(.Low, .High, .Max)
return
}
:= false
:= int64(-1)
switch u := coreString(.typ).(type) {
case nil:
.invalidOp(, _NonSliceableOperand, "cannot slice %s: %s has no core type", , .typ)
.mode = invalid
return
case *Basic:
if isString() {
if .Slice3 {
:= .Max
if == nil {
=
}
.invalidOp(, _InvalidSliceExpr, "3-index slice of string")
.mode = invalid
return
}
= true
if .mode == constant_ {
= int64(len(constant.StringVal(.val)))
}
if isUntyped(.typ) {
.typ = Typ[String]
}
}
case *Array:
= true
= .len
if .mode != variable {
.invalidOp(, _NonSliceableOperand, "cannot slice %s (value not addressable)", )
.mode = invalid
return
}
.typ = &Slice{elem: .elem}
case *Pointer:
if , := under(.base).(*Array); != nil {
= true
= .len
.typ = &Slice{elem: .elem}
}
case *Slice:
= true
}
if ! {
.invalidOp(, _NonSliceableOperand, "cannot slice %s", )
.mode = invalid
return
}
.mode = value
if .Slice3 && (.High == nil || .Max == nil) {
.invalidAST(inNode(, .Rbrack), "2nd and 3rd index required in 3-index slice")
.mode = invalid
return
}
var [3]int64
for , := range []ast.Expr{.Low, .High, .Max} {
:= int64(-1)
switch {
case != nil:
:= int64(-1)
if >= 0 {
= + 1
}
if , := .index(, ); >= 0 {
=
}
case == 0:
= 0
case >= 0:
=
}
[] =
}
:
for , := range [:len()-1] {
if > 0 {
for , := range [+1:] {
if >= 0 && < {
:= []ast.Expr{.Low, .High, .Max}[+1+]
.errorf(, _SwappedSliceIndices, "invalid slice indices: %d < %d", , )
break
}
}
}
}
}
func ( *Checker) ( *typeparams.IndexExpr) ast.Expr {
if len(.Indices) == 0 {
.invalidAST(.Orig, "index expression %v with 0 indices", )
return nil
}
if len(.Indices) > 1 {
.invalidOp(.Indices[1], _InvalidIndex, "more than one index")
}
return .Indices[0]
}
func ( *Checker) ( ast.Expr, int64) ( Type, int64) {
= Typ[Invalid]
= -1
var operand
.expr(&, )
if !.isValidIndex(&, _InvalidIndex, "index", false) {
return
}
if .mode != constant_ {
return .typ, -1
}
if .val.Kind() == constant.Unknown {
return
}
, := constant.Int64Val(.val)
assert()
if >= 0 && >= {
.invalidArg(&, _InvalidIndex, "index %s is out of bounds", &)
return
}
return .typ,
}
func ( *Checker) ( *operand, errorCode, string, bool) bool {
if .mode == invalid {
return false
}
.convertUntyped(, Typ[Int])
if .mode == invalid {
return false
}
if !allInteger(.typ) {
.invalidArg(, , "%s %s must be integer", , )
return false
}
if .mode == constant_ {
if ! && constant.Sign(.val) < 0 {
.invalidArg(, , "%s %s must not be negative", , )
return false
}
if !representableConst(.val, , Typ[Int], &.val) {
.invalidArg(, , "%s %s overflows int", , )
return false
}
}
return true
}
func ( *Checker) ( []ast.Expr, Type, int64) int64 {
:= make(map[int64]bool, len())
var , int64
for , := range {
:= false
:=
if , := .(*ast.KeyValueExpr); != nil {
if , := .index(.Key, ); != Typ[Invalid] {
if >= 0 {
=
= true
} else {
.errorf(, _InvalidLitIndex, "index %s must be integer constant", .Key)
}
}
= .Value
} else if >= 0 && >= {
.errorf(, _OversizeArrayLit, "index %d is out of bounds (>= %d)", , )
} else {
= true
}
if {
if [] {
.errorf(, _DuplicateLitKey, "duplicate index %d in array or slice literal", )
}
[] = true
}
++
if > {
=
}
var operand
.exprWithHint(&, , )
.assignment(&, , "array or slice literal")
}
return
}