Source file src/runtime/error.go

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

View as plain text