github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/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 // For calling from C. 76 // Prints an argument passed to panic. 77 func printany(i interface{}) { 78 switch v := i.(type) { 79 case nil: 80 print("nil") 81 case stringer: 82 print(v.String()) 83 case error: 84 print(v.Error()) 85 case bool: 86 print(v) 87 case int: 88 print(v) 89 case int8: 90 print(v) 91 case int16: 92 print(v) 93 case int32: 94 print(v) 95 case int64: 96 print(v) 97 case uint: 98 print(v) 99 case uint8: 100 print(v) 101 case uint16: 102 print(v) 103 case uint32: 104 print(v) 105 case uint64: 106 print(v) 107 case uintptr: 108 print(v) 109 case float32: 110 print(v) 111 case float64: 112 print(v) 113 case complex64: 114 print(v) 115 case complex128: 116 print(v) 117 case string: 118 print(v) 119 default: 120 print("(", typestring(i), ") ", i) 121 } 122 } 123 124 // strings.IndexByte is implemented in runtime/asm_$goarch.s 125 // but amusingly we need go:linkname to get access to it here in the runtime. 126 //go:linkname stringsIndexByte strings.IndexByte 127 func stringsIndexByte(s string, c byte) int 128 129 // called from generated code 130 func panicwrap() { 131 pc := make([]uintptr, 1) 132 n := Callers(2, pc) 133 if n == 0 { 134 throw("panicwrap: Callers failed") 135 } 136 frames := CallersFrames(pc) 137 frame, _ := frames.Next() 138 name := frame.Function 139 // name is something like "main.(*T).F". 140 // We want to extract pkg ("main"), typ ("T"), and meth ("F"). 141 // Do it by finding the parens. 142 i := stringsIndexByte(name, '(') 143 if i < 0 { 144 throw("panicwrap: no ( in " + frame.Function) 145 } 146 pkg := name[:i-1] 147 if i+2 >= len(name) || name[i-1:i+2] != ".(*" { 148 throw("panicwrap: unexpected string after package name: " + frame.Function) 149 } 150 name = name[i+2:] 151 i = stringsIndexByte(name, ')') 152 if i < 0 { 153 throw("panicwrap: no ) in " + frame.Function) 154 } 155 if i+2 >= len(name) || name[i:i+2] != ")." { 156 throw("panicwrap: unexpected string after type name: " + frame.Function) 157 } 158 typ := name[:i] 159 meth := name[i+2:] 160 panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")) 161 }