// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package runtime

import 

// The Error interface identifies a run time error.
type Error interface {
	error

	// RuntimeError is a no-op function but
	// serves to distinguish types that are run time
	// errors from ordinary errors: a type is a
	// run time error if it has a RuntimeError method.
	RuntimeError()
}

// A TypeAssertionError explains a failed type assertion.
type TypeAssertionError struct {
	_interface    *_type
	concrete      *_type
	asserted      *_type
	missingMethod string // one method needed by Interface, missing from Concrete
}

func (*TypeAssertionError) () {}

func ( *TypeAssertionError) () string {
	 := "interface"
	if ._interface != nil {
		 = toRType(._interface).string()
	}
	 := toRType(.asserted).string()
	if .concrete == nil {
		return "interface conversion: " +  + " is nil, not " + 
	}
	 := toRType(.concrete).string()
	if .missingMethod == "" {
		 := "interface conversion: " +  + " is " +  + ", not " + 
		if  ==  {
			// provide slightly clearer error message
			if toRType(.concrete).pkgpath() != toRType(.asserted).pkgpath() {
				 += " (types from different packages)"
			} else {
				 += " (types from different scopes)"
			}
		}
		return 
	}
	return "interface conversion: " +  + " is not " +  +
		": missing method " + .missingMethod
}

// itoa converts val to a decimal representation. The result is
// written somewhere within buf and the location of the result is returned.
// buf must be at least 20 bytes.
//
//go:nosplit
func itoa( []byte,  uint64) []byte {
	 := len() - 1
	for  >= 10 {
		[] = byte(%10 + '0')
		--
		 /= 10
	}
	[] = byte( + '0')
	return [:]
}

// An errorString represents a runtime error described by a single string.
type errorString string

func ( errorString) () {}

func ( errorString) () string {
	return "runtime error: " + string()
}

type errorAddressString struct {
	msg  string  // error message
	addr uintptr // memory address where the error occurred
}

func ( errorAddressString) () {}

func ( errorAddressString) () string {
	return "runtime error: " + .msg
}

// Addr returns the memory address where a fault occurred.
// The address provided is best-effort.
// The veracity of the result may depend on the platform.
// Errors providing this method will only be returned as
// a result of using [runtime/debug.SetPanicOnFault].
func ( errorAddressString) () uintptr {
	return .addr
}

// plainError represents a runtime error described a string without
// the prefix "runtime error: " after invoking errorString.Error().
// See Issue #14965.
type plainError string

func ( plainError) () {}

func ( plainError) () string {
	return string()
}

// A boundsError represents an indexing or slicing operation gone wrong.
type boundsError struct {
	x int64
	y int
	// Values in an index or slice expression can be signed or unsigned.
	// That means we'd need 65 bits to encode all possible indexes, from -2^63 to 2^64-1.
	// Instead, we keep track of whether x should be interpreted as signed or unsigned.
	// y is known to be nonnegative and to fit in an int.
	signed bool
	code   boundsErrorCode
}

type boundsErrorCode uint8

const (
	boundsIndex boundsErrorCode = iota // s[x], 0 <= x < len(s) failed

	boundsSliceAlen // s[?:x], 0 <= x <= len(s) failed
	boundsSliceAcap // s[?:x], 0 <= x <= cap(s) failed
	boundsSliceB    // s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen)

	boundsSlice3Alen // s[?:?:x], 0 <= x <= len(s) failed
	boundsSlice3Acap // s[?:?:x], 0 <= x <= cap(s) failed
	boundsSlice3B    // s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen)
	boundsSlice3C    // s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen)

	boundsConvert // (*[x]T)(s), 0 <= x <= len(s) failed
	// Note: in the above, len(s) and cap(s) are stored in y
)

// boundsErrorFmts provide error text for various out-of-bounds panics.
// Note: if you change these strings, you should adjust the size of the buffer
// in boundsError.Error below as well.
var boundsErrorFmts = [...]string{
	boundsIndex:      "index out of range [%x] with length %y",
	boundsSliceAlen:  "slice bounds out of range [:%x] with length %y",
	boundsSliceAcap:  "slice bounds out of range [:%x] with capacity %y",
	boundsSliceB:     "slice bounds out of range [%x:%y]",
	boundsSlice3Alen: "slice bounds out of range [::%x] with length %y",
	boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
	boundsSlice3B:    "slice bounds out of range [:%x:%y]",
	boundsSlice3C:    "slice bounds out of range [%x:%y:]",
	boundsConvert:    "cannot convert slice with length %y to array or pointer to array with length %x",
}

// boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y.
var boundsNegErrorFmts = [...]string{
	boundsIndex:      "index out of range [%x]",
	boundsSliceAlen:  "slice bounds out of range [:%x]",
	boundsSliceAcap:  "slice bounds out of range [:%x]",
	boundsSliceB:     "slice bounds out of range [%x:]",
	boundsSlice3Alen: "slice bounds out of range [::%x]",
	boundsSlice3Acap: "slice bounds out of range [::%x]",
	boundsSlice3B:    "slice bounds out of range [:%x:]",
	boundsSlice3C:    "slice bounds out of range [%x::]",
}

func ( boundsError) () {}

func appendIntStr( []byte,  int64,  bool) []byte {
	if  &&  < 0 {
		 = append(, '-')
		 = -
	}
	var  [20]byte
	 = append(, itoa([:], uint64())...)
	return 
}

func ( boundsError) () string {
	 := boundsErrorFmts[.code]
	if .signed && .x < 0 {
		 = boundsNegErrorFmts[.code]
	}
	// max message length is 99: "runtime error: slice bounds out of range [::%x] with capacity %y"
	// x can be at most 20 characters. y can be at most 19.
	 := make([]byte, 0, 100)
	 = append(, "runtime error: "...)
	for  := 0;  < len(); ++ {
		 := []
		if  != '%' {
			 = append(, )
			continue
		}
		++
		switch [] {
		case 'x':
			 = appendIntStr(, .x, .signed)
		case 'y':
			 = appendIntStr(, int64(.y), true)
		}
	}
	return string()
}

type stringer interface {
	String() string
}

// printany prints an argument passed to panic.
// If panic is called with a value that has a String or Error method,
// it has already been converted into a string by preprintpanics.
func printany( any) {
	switch v := .(type) {
	case nil:
		print("nil")
	case bool:
		print()
	case int:
		print()
	case int8:
		print()
	case int16:
		print()
	case int32:
		print()
	case int64:
		print()
	case uint:
		print()
	case uint8:
		print()
	case uint16:
		print()
	case uint32:
		print()
	case uint64:
		print()
	case uintptr:
		print()
	case float32:
		print()
	case float64:
		print()
	case complex64:
		print()
	case complex128:
		print()
	case string:
		print()
	default:
		printanycustomtype()
	}
}

func printanycustomtype( any) {
	 := efaceOf(&)
	 := toRType(._type).string()

	switch ._type.Kind_ {
	case kindString:
		print(, `("`, *(*string)(.data), `")`)
	case kindBool:
		print(, "(", *(*bool)(.data), ")")
	case kindInt:
		print(, "(", *(*int)(.data), ")")
	case kindInt8:
		print(, "(", *(*int8)(.data), ")")
	case kindInt16:
		print(, "(", *(*int16)(.data), ")")
	case kindInt32:
		print(, "(", *(*int32)(.data), ")")
	case kindInt64:
		print(, "(", *(*int64)(.data), ")")
	case kindUint:
		print(, "(", *(*uint)(.data), ")")
	case kindUint8:
		print(, "(", *(*uint8)(.data), ")")
	case kindUint16:
		print(, "(", *(*uint16)(.data), ")")
	case kindUint32:
		print(, "(", *(*uint32)(.data), ")")
	case kindUint64:
		print(, "(", *(*uint64)(.data), ")")
	case kindUintptr:
		print(, "(", *(*uintptr)(.data), ")")
	case kindFloat32:
		print(, "(", *(*float32)(.data), ")")
	case kindFloat64:
		print(, "(", *(*float64)(.data), ")")
	case kindComplex64:
		print(, *(*complex64)(.data))
	case kindComplex128:
		print(, *(*complex128)(.data))
	default:
		print("(", , ") ", .data)
	}
}

// panicwrap generates a panic for a call to a wrapped value method
// with a nil pointer receiver.
//
// It is called from the generated wrapper code.
func panicwrap() {
	 := getcallerpc()
	 := funcNameForPrint(funcname(findfunc()))
	// name is something like "main.(*T).F".
	// We want to extract pkg ("main"), typ ("T"), and meth ("F").
	// Do it by finding the parens.
	 := bytealg.IndexByteString(, '(')
	if  < 0 {
		throw("panicwrap: no ( in " + )
	}
	 := [:-1]
	if +2 >= len() || [-1:+2] != ".(*" {
		throw("panicwrap: unexpected string after package name: " + )
	}
	 = [+2:]
	 = bytealg.IndexByteString(, ')')
	if  < 0 {
		throw("panicwrap: no ) in " + )
	}
	if +2 >= len() || [:+2] != ")." {
		throw("panicwrap: unexpected string after type name: " + )
	}
	 := [:]
	 := [+2:]
	panic(plainError("value method " +  + "." +  + "." +  + " called using nil *" +  + " pointer"))
}