...

Source file src/runtime/error.go

Documentation: runtime

		 1  // Copyright 2010 The Go Authors. All rights reserved.
		 2  // Use of this source code is governed by a BSD-style
		 3  // license that can be found in the LICENSE file.
		 4  
		 5  package runtime
		 6  
		 7  import "internal/bytealg"
		 8  
		 9  // The Error interface identifies a run time error.
		10  type Error interface {
		11  	error
		12  
		13  	// RuntimeError is a no-op function but
		14  	// serves to distinguish types that are run time
		15  	// errors from ordinary errors: a type is a
		16  	// run time error if it has a RuntimeError method.
		17  	RuntimeError()
		18  }
		19  
		20  // A TypeAssertionError explains a failed type assertion.
		21  type TypeAssertionError struct {
		22  	_interface		*_type
		23  	concrete			*_type
		24  	asserted			*_type
		25  	missingMethod string // one method needed by Interface, missing from Concrete
		26  }
		27  
		28  func (*TypeAssertionError) RuntimeError() {}
		29  
		30  func (e *TypeAssertionError) Error() string {
		31  	inter := "interface"
		32  	if e._interface != nil {
		33  		inter = e._interface.string()
		34  	}
		35  	as := e.asserted.string()
		36  	if e.concrete == nil {
		37  		return "interface conversion: " + inter + " is nil, not " + as
		38  	}
		39  	cs := e.concrete.string()
		40  	if e.missingMethod == "" {
		41  		msg := "interface conversion: " + inter + " is " + cs + ", not " + as
		42  		if cs == as {
		43  			// provide slightly clearer error message
		44  			if e.concrete.pkgpath() != e.asserted.pkgpath() {
		45  				msg += " (types from different packages)"
		46  			} else {
		47  				msg += " (types from different scopes)"
		48  			}
		49  		}
		50  		return msg
		51  	}
		52  	return "interface conversion: " + cs + " is not " + as +
		53  		": missing method " + e.missingMethod
		54  }
		55  
		56  //go:nosplit
		57  // itoa converts val to a decimal representation. The result is
		58  // written somewhere within buf and the location of the result is returned.
		59  // buf must be at least 20 bytes.
		60  func itoa(buf []byte, val uint64) []byte {
		61  	i := len(buf) - 1
		62  	for val >= 10 {
		63  		buf[i] = byte(val%10 + '0')
		64  		i--
		65  		val /= 10
		66  	}
		67  	buf[i] = byte(val + '0')
		68  	return buf[i:]
		69  }
		70  
		71  // An errorString represents a runtime error described by a single string.
		72  type errorString string
		73  
		74  func (e errorString) RuntimeError() {}
		75  
		76  func (e errorString) Error() string {
		77  	return "runtime error: " + string(e)
		78  }
		79  
		80  type errorAddressString struct {
		81  	msg	string	// error message
		82  	addr uintptr // memory address where the error occurred
		83  }
		84  
		85  func (e errorAddressString) RuntimeError() {}
		86  
		87  func (e errorAddressString) Error() string {
		88  	return "runtime error: " + e.msg
		89  }
		90  
		91  // Addr returns the memory address where a fault occurred.
		92  // The address provided is best-effort.
		93  // The veracity of the result may depend on the platform.
		94  // Errors providing this method will only be returned as
		95  // a result of using runtime/debug.SetPanicOnFault.
		96  func (e errorAddressString) Addr() uintptr {
		97  	return e.addr
		98  }
		99  
	 100  // plainError represents a runtime error described a string without
	 101  // the prefix "runtime error: " after invoking errorString.Error().
	 102  // See Issue #14965.
	 103  type plainError string
	 104  
	 105  func (e plainError) RuntimeError() {}
	 106  
	 107  func (e plainError) Error() string {
	 108  	return string(e)
	 109  }
	 110  
	 111  // A boundsError represents an indexing or slicing operation gone wrong.
	 112  type boundsError struct {
	 113  	x int64
	 114  	y int
	 115  	// Values in an index or slice expression can be signed or unsigned.
	 116  	// That means we'd need 65 bits to encode all possible indexes, from -2^63 to 2^64-1.
	 117  	// Instead, we keep track of whether x should be interpreted as signed or unsigned.
	 118  	// y is known to be nonnegative and to fit in an int.
	 119  	signed bool
	 120  	code	 boundsErrorCode
	 121  }
	 122  
	 123  type boundsErrorCode uint8
	 124  
	 125  const (
	 126  	boundsIndex boundsErrorCode = iota // s[x], 0 <= x < len(s) failed
	 127  
	 128  	boundsSliceAlen // s[?:x], 0 <= x <= len(s) failed
	 129  	boundsSliceAcap // s[?:x], 0 <= x <= cap(s) failed
	 130  	boundsSliceB		// s[x:y], 0 <= x <= y failed (but boundsSliceA didn't happen)
	 131  
	 132  	boundsSlice3Alen // s[?:?:x], 0 <= x <= len(s) failed
	 133  	boundsSlice3Acap // s[?:?:x], 0 <= x <= cap(s) failed
	 134  	boundsSlice3B		// s[?:x:y], 0 <= x <= y failed (but boundsSlice3A didn't happen)
	 135  	boundsSlice3C		// s[x:y:?], 0 <= x <= y failed (but boundsSlice3A/B didn't happen)
	 136  
	 137  	boundsConvert // (*[x]T)(s), 0 <= x <= len(s) failed
	 138  	// Note: in the above, len(s) and cap(s) are stored in y
	 139  )
	 140  
	 141  // boundsErrorFmts provide error text for various out-of-bounds panics.
	 142  // Note: if you change these strings, you should adjust the size of the buffer
	 143  // in boundsError.Error below as well.
	 144  var boundsErrorFmts = [...]string{
	 145  	boundsIndex:			"index out of range [%x] with length %y",
	 146  	boundsSliceAlen:	"slice bounds out of range [:%x] with length %y",
	 147  	boundsSliceAcap:	"slice bounds out of range [:%x] with capacity %y",
	 148  	boundsSliceB:		 "slice bounds out of range [%x:%y]",
	 149  	boundsSlice3Alen: "slice bounds out of range [::%x] with length %y",
	 150  	boundsSlice3Acap: "slice bounds out of range [::%x] with capacity %y",
	 151  	boundsSlice3B:		"slice bounds out of range [:%x:%y]",
	 152  	boundsSlice3C:		"slice bounds out of range [%x:%y:]",
	 153  	boundsConvert:		"cannot convert slice with length %y to pointer to array with length %x",
	 154  }
	 155  
	 156  // boundsNegErrorFmts are overriding formats if x is negative. In this case there's no need to report y.
	 157  var boundsNegErrorFmts = [...]string{
	 158  	boundsIndex:			"index out of range [%x]",
	 159  	boundsSliceAlen:	"slice bounds out of range [:%x]",
	 160  	boundsSliceAcap:	"slice bounds out of range [:%x]",
	 161  	boundsSliceB:		 "slice bounds out of range [%x:]",
	 162  	boundsSlice3Alen: "slice bounds out of range [::%x]",
	 163  	boundsSlice3Acap: "slice bounds out of range [::%x]",
	 164  	boundsSlice3B:		"slice bounds out of range [:%x:]",
	 165  	boundsSlice3C:		"slice bounds out of range [%x::]",
	 166  }
	 167  
	 168  func (e boundsError) RuntimeError() {}
	 169  
	 170  func appendIntStr(b []byte, v int64, signed bool) []byte {
	 171  	if signed && v < 0 {
	 172  		b = append(b, '-')
	 173  		v = -v
	 174  	}
	 175  	var buf [20]byte
	 176  	b = append(b, itoa(buf[:], uint64(v))...)
	 177  	return b
	 178  }
	 179  
	 180  func (e boundsError) Error() string {
	 181  	fmt := boundsErrorFmts[e.code]
	 182  	if e.signed && e.x < 0 {
	 183  		fmt = boundsNegErrorFmts[e.code]
	 184  	}
	 185  	// max message length is 99: "runtime error: slice bounds out of range [::%x] with capacity %y"
	 186  	// x can be at most 20 characters. y can be at most 19.
	 187  	b := make([]byte, 0, 100)
	 188  	b = append(b, "runtime error: "...)
	 189  	for i := 0; i < len(fmt); i++ {
	 190  		c := fmt[i]
	 191  		if c != '%' {
	 192  			b = append(b, c)
	 193  			continue
	 194  		}
	 195  		i++
	 196  		switch fmt[i] {
	 197  		case 'x':
	 198  			b = appendIntStr(b, e.x, e.signed)
	 199  		case 'y':
	 200  			b = appendIntStr(b, int64(e.y), true)
	 201  		}
	 202  	}
	 203  	return string(b)
	 204  }
	 205  
	 206  type stringer interface {
	 207  	String() string
	 208  }
	 209  
	 210  // printany prints an argument passed to panic.
	 211  // If panic is called with a value that has a String or Error method,
	 212  // it has already been converted into a string by preprintpanics.
	 213  func printany(i interface{}) {
	 214  	switch v := i.(type) {
	 215  	case nil:
	 216  		print("nil")
	 217  	case bool:
	 218  		print(v)
	 219  	case int:
	 220  		print(v)
	 221  	case int8:
	 222  		print(v)
	 223  	case int16:
	 224  		print(v)
	 225  	case int32:
	 226  		print(v)
	 227  	case int64:
	 228  		print(v)
	 229  	case uint:
	 230  		print(v)
	 231  	case uint8:
	 232  		print(v)
	 233  	case uint16:
	 234  		print(v)
	 235  	case uint32:
	 236  		print(v)
	 237  	case uint64:
	 238  		print(v)
	 239  	case uintptr:
	 240  		print(v)
	 241  	case float32:
	 242  		print(v)
	 243  	case float64:
	 244  		print(v)
	 245  	case complex64:
	 246  		print(v)
	 247  	case complex128:
	 248  		print(v)
	 249  	case string:
	 250  		print(v)
	 251  	default:
	 252  		printanycustomtype(i)
	 253  	}
	 254  }
	 255  
	 256  func printanycustomtype(i interface{}) {
	 257  	eface := efaceOf(&i)
	 258  	typestring := eface._type.string()
	 259  
	 260  	switch eface._type.kind {
	 261  	case kindString:
	 262  		print(typestring, `("`, *(*string)(eface.data), `")`)
	 263  	case kindBool:
	 264  		print(typestring, "(", *(*bool)(eface.data), ")")
	 265  	case kindInt:
	 266  		print(typestring, "(", *(*int)(eface.data), ")")
	 267  	case kindInt8:
	 268  		print(typestring, "(", *(*int8)(eface.data), ")")
	 269  	case kindInt16:
	 270  		print(typestring, "(", *(*int16)(eface.data), ")")
	 271  	case kindInt32:
	 272  		print(typestring, "(", *(*int32)(eface.data), ")")
	 273  	case kindInt64:
	 274  		print(typestring, "(", *(*int64)(eface.data), ")")
	 275  	case kindUint:
	 276  		print(typestring, "(", *(*uint)(eface.data), ")")
	 277  	case kindUint8:
	 278  		print(typestring, "(", *(*uint8)(eface.data), ")")
	 279  	case kindUint16:
	 280  		print(typestring, "(", *(*uint16)(eface.data), ")")
	 281  	case kindUint32:
	 282  		print(typestring, "(", *(*uint32)(eface.data), ")")
	 283  	case kindUint64:
	 284  		print(typestring, "(", *(*uint64)(eface.data), ")")
	 285  	case kindUintptr:
	 286  		print(typestring, "(", *(*uintptr)(eface.data), ")")
	 287  	case kindFloat32:
	 288  		print(typestring, "(", *(*float32)(eface.data), ")")
	 289  	case kindFloat64:
	 290  		print(typestring, "(", *(*float64)(eface.data), ")")
	 291  	case kindComplex64:
	 292  		print(typestring, *(*complex64)(eface.data))
	 293  	case kindComplex128:
	 294  		print(typestring, *(*complex128)(eface.data))
	 295  	default:
	 296  		print("(", typestring, ") ", eface.data)
	 297  	}
	 298  }
	 299  
	 300  // panicwrap generates a panic for a call to a wrapped value method
	 301  // with a nil pointer receiver.
	 302  //
	 303  // It is called from the generated wrapper code.
	 304  func panicwrap() {
	 305  	pc := getcallerpc()
	 306  	name := funcname(findfunc(pc))
	 307  	// name is something like "main.(*T).F".
	 308  	// We want to extract pkg ("main"), typ ("T"), and meth ("F").
	 309  	// Do it by finding the parens.
	 310  	i := bytealg.IndexByteString(name, '(')
	 311  	if i < 0 {
	 312  		throw("panicwrap: no ( in " + name)
	 313  	}
	 314  	pkg := name[:i-1]
	 315  	if i+2 >= len(name) || name[i-1:i+2] != ".(*" {
	 316  		throw("panicwrap: unexpected string after package name: " + name)
	 317  	}
	 318  	name = name[i+2:]
	 319  	i = bytealg.IndexByteString(name, ')')
	 320  	if i < 0 {
	 321  		throw("panicwrap: no ) in " + name)
	 322  	}
	 323  	if i+2 >= len(name) || name[i:i+2] != ")." {
	 324  		throw("panicwrap: unexpected string after type name: " + name)
	 325  	}
	 326  	typ := name[:i]
	 327  	meth := name[i+2:]
	 328  	panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer"))
	 329  }
	 330  

View as plain text