@@ -137,7 +137,22 @@ matrix_bounds_check_error :: proc "contextless" (file: string, line, column: i32
137137
138138
139139when ODIN_NO_RTTI {
140- type_assertion_check :: proc " contextless" (ok: bool , file: string , line, column: i32 ) {
140+ type_assertion_check_with_context :: proc " odin" (ok: bool , file: string , line, column: i32 ) {
141+ if ok {
142+ return
143+ }
144+ @ (cold, no_instrumentation)
145+ handle_error :: proc " odin" (file: string , line, column: i32 ) -> ! {
146+ p := context .assertion_failure_proc
147+ if p == nil {
148+ p = default_assertion_failure_proc
149+ }
150+ p (" type assertion" , " Invalid type assertion" , Source_Code_Location{file, line, column, " " })
151+ }
152+ handle_error (file, line, column)
153+ }
154+
155+ type_assertion_check_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 ) {
141156 if ok {
142157 return
143158 }
@@ -150,7 +165,7 @@ when ODIN_NO_RTTI {
150165 handle_error (file, line, column)
151166 }
152167
153- type_assertion_check2 :: proc " contextless " (ok: bool , file: string , line, column: i32 ) {
168+ type_assertion_check2_with_context :: proc " odin " (ok: bool , file: string , line, column: i32 ) {
154169 if ok {
155170 return
156171 }
@@ -162,8 +177,53 @@ when ODIN_NO_RTTI {
162177 }
163178 handle_error (file, line, column)
164179 }
180+
181+ type_assertion_check2_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 ) {
182+ if ok {
183+ return
184+ }
185+ @ (cold, no_instrumentation)
186+ handle_error :: proc " odin" (file: string , line, column: i32 ) -> ! {
187+ p := context .assertion_failure_proc
188+ if p == nil {
189+ p = default_assertion_failure_proc
190+ }
191+ p (" type assertion" , " Invalid type assertion" , Source_Code_Location{file, line, column, " " })
192+ }
193+ handle_error (file, line, column)
194+ }
165195} else {
166- type_assertion_check :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid ) {
196+ @ (private=" file" )
197+ TYPE_ASSERTION_BUFFER_SIZE :: 1024
198+
199+ type_assertion_check_with_context :: proc " odin" (ok: bool , file: string , line, column: i32 , from, to: typeid ) {
200+ if ok {
201+ return
202+ }
203+ @ (cold, no_instrumentation)
204+ handle_error :: proc " odin" (file: string , line, column: i32 , from, to: typeid ) -> ! {
205+ do_msg :: proc " contextless" (i: ^int , buf: []byte , file: string , line, column: i32 , from, to: typeid ) -> bool {
206+ try_copy_string (i, buf, " Invalid type assertion from " ) or_return
207+ try_copy_typeid (i, buf, from) or_return
208+ try_copy_string (i, buf, " to " ) or_return
209+ try_copy_typeid (i, buf, to) or_return
210+ return true
211+ }
212+
213+ buf: [TYPE_ASSERTION_BUFFER_SIZE]byte
214+ i := 0
215+ _ = do_msg (&i, buf[:], file, line, column, from, to)
216+
217+ p := context .assertion_failure_proc
218+ if p == nil {
219+ p = default_assertion_failure_proc
220+ }
221+ p (" type assertion" , string (buf[:i]), Source_Code_Location{file, line, column, " " })
222+ }
223+ handle_error (file, line, column, from, to)
224+ }
225+
226+ type_assertion_check_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid ) {
167227 if ok {
168228 return
169229 }
@@ -180,42 +240,85 @@ when ODIN_NO_RTTI {
180240 handle_error (file, line, column, from, to)
181241 }
182242
183- type_assertion_check2 :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) {
243+ @ (private=" file" )
244+ type_assertion_variant_type :: proc " contextless" (id: typeid , data: rawptr ) -> typeid {
245+ if id == nil || data == nil {
246+ return id
247+ }
248+ ti := type_info_base (type_info_of (id))
249+ #partial switch v in ti.variant {
250+ case Type_Info_Any:
251+ return (^any )(data).id
252+ case Type_Info_Union:
253+ if v.tag_type == nil {
254+ if (^rawptr )(data)^ == nil {
255+ return nil
256+ }
257+ return v.variants[0 ].id
258+
259+ }
260+
261+ tag_ptr := uintptr (data) + v.tag_offset
262+ idx := 0
263+ switch v.tag_type.size {
264+ case 1 : idx = int ( (^u8 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
265+ case 2 : idx = int ( (^u16 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
266+ case 4 : idx = int ( (^u32 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
267+ case 8 : idx = int ( (^u64 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
268+ case 16 : idx = int ((^u128 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
269+ }
270+ if idx < 0 {
271+ return nil
272+ } else if idx < len (v.variants) {
273+ return v.variants[idx].id
274+ }
275+ }
276+ return id
277+ }
278+
279+ type_assertion_check2_with_context :: proc " odin" (ok: bool , file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) {
184280 if ok {
185281 return
186282 }
187283
188- variant_type :: proc " contextless" (id: typeid , data: rawptr ) -> typeid {
189- if id == nil || data == nil {
190- return id
191- }
192- ti := type_info_base (type_info_of (id))
193- #partial switch v in ti.variant {
194- case Type_Info_Any:
195- return (^any )(data).id
196- case Type_Info_Union:
197- tag_ptr := uintptr (data) + v.tag_offset
198- idx := 0
199- switch v.tag_type.size {
200- case 1 : idx = int ((^u8 )(tag_ptr)^) - 1
201- case 2 : idx = int ((^u16 )(tag_ptr)^) - 1
202- case 4 : idx = int ((^u32 )(tag_ptr)^) - 1
203- case 8 : idx = int ((^u64 )(tag_ptr)^) - 1
204- case 16 : idx = int ((^u128 )(tag_ptr)^) - 1
205- }
206- if idx < 0 {
207- return nil
208- } else if idx < len (v.variants) {
209- return v.variants[idx].id
284+ @ (cold, no_instrumentation)
285+ handle_error :: proc " odin" (file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) -> ! {
286+ do_msg :: proc " contextless" (i: ^int , buf: []byte , file: string , line, column: i32 , from, to, actual: typeid ) -> bool {
287+ try_copy_string (i, buf, " Invalid type assertion from " ) or_return
288+ try_copy_typeid (i, buf, from) or_return
289+ try_copy_string (i, buf, " to " ) or_return
290+ try_copy_typeid (i, buf, to) or_return
291+ if actual != from {
292+ try_copy_string (i, buf, " , actual type: " ) or_return
293+ try_copy_typeid (i, buf, actual) or_return
210294 }
295+ return true
211296 }
212- return id
297+
298+ actual := type_assertion_variant_type (from, from_data)
299+
300+ buf: [TYPE_ASSERTION_BUFFER_SIZE]byte
301+ i := 0
302+ _ = do_msg (&i, buf[:], file, line, column, from, to, actual)
303+
304+ p := context .assertion_failure_proc
305+ if p == nil {
306+ p = default_assertion_failure_proc
307+ }
308+ p (" type assertion" , string (buf[:i]), Source_Code_Location{file, line, column, " " })
309+ }
310+ handle_error (file, line, column, from, to, from_data)
311+ }
312+
313+ type_assertion_check2_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) {
314+ if ok {
315+ return
213316 }
214317
215318 @ (cold, no_instrumentation)
216319 handle_error :: proc " contextless" (file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) -> ! {
217320
218- actual := variant_type (from, from_data)
321+ actual := type_assertion_variant_type (from, from_data)
219322
220323 print_caller_location (Source_Code_Location{file, line, column, " " })
221324 print_string (" Invalid type assertion from " )
0 commit comments