Home | History | Annotate | Download | only in 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 _ "unsafe" // for go:linkname
      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 	interfaceString string
     23 	concreteString  string
     24 	assertedString  string
     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 := e.interfaceString
     32 	if inter == "" {
     33 		inter = "interface"
     34 	}
     35 	if e.concreteString == "" {
     36 		return "interface conversion: " + inter + " is nil, not " + e.assertedString
     37 	}
     38 	if e.missingMethod == "" {
     39 		return "interface conversion: " + inter + " is " + e.concreteString +
     40 			", not " + e.assertedString
     41 	}
     42 	return "interface conversion: " + e.concreteString + " is not " + e.assertedString +
     43 		": missing method " + e.missingMethod
     44 }
     45 
     46 // An errorString represents a runtime error described by a single string.
     47 type errorString string
     48 
     49 func (e errorString) RuntimeError() {}
     50 
     51 func (e errorString) Error() string {
     52 	return "runtime error: " + string(e)
     53 }
     54 
     55 // plainError represents a runtime error described a string without
     56 // the prefix "runtime error: " after invoking errorString.Error().
     57 // See Issue #14965.
     58 type plainError string
     59 
     60 func (e plainError) RuntimeError() {}
     61 
     62 func (e plainError) Error() string {
     63 	return string(e)
     64 }
     65 
     66 type stringer interface {
     67 	String() string
     68 }
     69 
     70 func typestring(x interface{}) string {
     71 	e := efaceOf(&x)
     72 	return e._type.string()
     73 }
     74 
     75 // printany prints an argument passed to panic.
     76 func printany(i interface{}) {
     77 	switch v := i.(type) {
     78 	case nil:
     79 		print("nil")
     80 	case stringer:
     81 		print(v.String())
     82 	case error:
     83 		print(v.Error())
     84 	case bool:
     85 		print(v)
     86 	case int:
     87 		print(v)
     88 	case int8:
     89 		print(v)
     90 	case int16:
     91 		print(v)
     92 	case int32:
     93 		print(v)
     94 	case int64:
     95 		print(v)
     96 	case uint:
     97 		print(v)
     98 	case uint8:
     99 		print(v)
    100 	case uint16:
    101 		print(v)
    102 	case uint32:
    103 		print(v)
    104 	case uint64:
    105 		print(v)
    106 	case uintptr:
    107 		print(v)
    108 	case float32:
    109 		print(v)
    110 	case float64:
    111 		print(v)
    112 	case complex64:
    113 		print(v)
    114 	case complex128:
    115 		print(v)
    116 	case string:
    117 		print(v)
    118 	default:
    119 		print("(", typestring(i), ") ", i)
    120 	}
    121 }
    122 
    123 // strings.IndexByte is implemented in runtime/asm_$goarch.s
    124 // but amusingly we need go:linkname to get access to it here in the runtime.
    125 //go:linkname stringsIndexByte strings.IndexByte
    126 func stringsIndexByte(s string, c byte) int
    127 
    128 // panicwrap generates a panic for a call to a wrapped value method
    129 // with a nil pointer receiver.
    130 //
    131 // It is called from the generated wrapper code.
    132 func panicwrap() {
    133 	pc := getcallerpc()
    134 	name := funcname(findfunc(pc))
    135 	// name is something like "main.(*T).F".
    136 	// We want to extract pkg ("main"), typ ("T"), and meth ("F").
    137 	// Do it by finding the parens.
    138 	i := stringsIndexByte(name, '(')
    139 	if i < 0 {
    140 		throw("panicwrap: no ( in " + name)
    141 	}
    142 	pkg := name[:i-1]
    143 	if i+2 >= len(name) || name[i-1:i+2] != ".(*" {
    144 		throw("panicwrap: unexpected string after package name: " + name)
    145 	}
    146 	name = name[i+2:]
    147 	i = stringsIndexByte(name, ')')
    148 	if i < 0 {
    149 		throw("panicwrap: no ) in " + name)
    150 	}
    151 	if i+2 >= len(name) || name[i:i+2] != ")." {
    152 		throw("panicwrap: unexpected string after type name: " + name)
    153 	}
    154 	typ := name[:i]
    155 	meth := name[i+2:]
    156 	panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer"))
    157 }
    158