github.com/likebike/go--@v0.0.0-20190911215757-0bd925d16e96/go/src/runtime/error.go (about) 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 // If panic is called with a value that has a String or Error method, 77 // it has already been converted into a string by preprintpanics. 78 func printany(i interface{}) { 79 switch v := i.(type) { 80 case nil: 81 print("nil") 82 case bool: 83 print(v) 84 case int: 85 print(v) 86 case int8: 87 print(v) 88 case int16: 89 print(v) 90 case int32: 91 print(v) 92 case int64: 93 print(v) 94 case uint: 95 print(v) 96 case uint8: 97 print(v) 98 case uint16: 99 print(v) 100 case uint32: 101 print(v) 102 case uint64: 103 print(v) 104 case uintptr: 105 print(v) 106 case float32: 107 print(v) 108 case float64: 109 print(v) 110 case complex64: 111 print(v) 112 case complex128: 113 print(v) 114 case string: 115 print(v) 116 default: 117 print("(", typestring(i), ") ", i) 118 } 119 } 120 121 // strings.IndexByte is implemented in runtime/asm_$goarch.s 122 // but amusingly we need go:linkname to get access to it here in the runtime. 123 //go:linkname stringsIndexByte strings.IndexByte 124 func stringsIndexByte(s string, c byte) int 125 126 // panicwrap generates a panic for a call to a wrapped value method 127 // with a nil pointer receiver. 128 // 129 // It is called from the generated wrapper code. 130 func panicwrap() { 131 pc := getcallerpc() 132 name := funcname(findfunc(pc)) 133 // name is something like "main.(*T).F". 134 // We want to extract pkg ("main"), typ ("T"), and meth ("F"). 135 // Do it by finding the parens. 136 i := stringsIndexByte(name, '(') 137 if i < 0 { 138 throw("panicwrap: no ( in " + name) 139 } 140 pkg := name[:i-1] 141 if i+2 >= len(name) || name[i-1:i+2] != ".(*" { 142 throw("panicwrap: unexpected string after package name: " + name) 143 } 144 name = name[i+2:] 145 i = stringsIndexByte(name, ')') 146 if i < 0 { 147 throw("panicwrap: no ) in " + name) 148 } 149 if i+2 >= len(name) || name[i:i+2] != ")." { 150 throw("panicwrap: unexpected string after type name: " + name) 151 } 152 typ := name[:i] 153 meth := name[i+2:] 154 panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")) 155 }