@@ -12,7 +12,7 @@ bounds_trap :: proc "contextless" () -> ! {
1212}
1313
1414@(no_instrumentation)
15- type_assertion_trap :: proc " contextless" () -> ! {
15+ type_assertion_trap_contextless :: proc " contextless" () -> ! {
1616 when ODIN_OS == .Windows {
1717 windows_trap_type_assertion ()
1818 } else when ODIN_OS == .Orca {
@@ -137,33 +137,94 @@ 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 }
144159 @ (cold, no_instrumentation)
145160 handle_error :: proc " contextless" (file: string , line, column: i32 ) -> ! {
146161 print_caller_location (Source_Code_Location{file, line, column, " " })
147162 print_string (" Invalid type assertion\n " )
148- type_assertion_trap ()
163+ type_assertion_trap_contextless ()
164+ }
165+ handle_error (file, line, column)
166+ }
167+
168+ type_assertion_check2_with_context :: proc " odin" (ok: bool , file: string , line, column: i32 ) {
169+ if ok {
170+ return
149171 }
172+ @ (cold, no_instrumentation)
173+ handle_error :: proc " odin" (file: string , line, column: i32 ) -> ! {
174+ p := context .assertion_failure_proc
175+ if p == nil {
176+ p = default_assertion_failure_proc
177+ }
178+ p (" type assertion" , " Invalid type assertion" , Source_Code_Location{file, line, column, " " })
179+ }
180+
150181 handle_error (file, line, column)
151182 }
152183
153- type_assertion_check2 :: proc " contextless" (ok: bool , file: string , line, column: i32 ) {
184+ type_assertion_check2_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 ) {
154185 if ok {
155186 return
156187 }
157188 @ (cold, no_instrumentation)
158189 handle_error :: proc " contextless" (file: string , line, column: i32 ) -> ! {
159190 print_caller_location (Source_Code_Location{file, line, column, " " })
160191 print_string (" Invalid type assertion\n " )
161- type_assertion_trap ()
192+ type_assertion_trap_contextless ()
162193 }
163194 handle_error (file, line, column)
164195 }
165196} else {
166- type_assertion_check :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid ) {
197+ @ (private=" file" )
198+ TYPE_ASSERTION_BUFFER_SIZE :: 1024
199+
200+ type_assertion_check_with_context :: proc " odin" (ok: bool , file: string , line, column: i32 , from, to: typeid ) {
201+ if ok {
202+ return
203+ }
204+ @ (cold, no_instrumentation)
205+ handle_error :: proc " odin" (file: string , line, column: i32 , from, to: typeid ) -> ! {
206+ do_msg :: proc " contextless" (i: ^int , buf: []byte , file: string , line, column: i32 , from, to: typeid ) -> bool {
207+ try_copy_string (i, buf, " Invalid type assertion from " ) or_return
208+ try_copy_typeid (i, buf, from) or_return
209+ try_copy_string (i, buf, " to " ) or_return
210+ try_copy_typeid (i, buf, to) or_return
211+ return true
212+ }
213+
214+ buf: [TYPE_ASSERTION_BUFFER_SIZE]byte
215+ i := 0
216+ _ = do_msg (&i, buf[:], file, line, column, from, to)
217+
218+ p := context .assertion_failure_proc
219+ if p == nil {
220+ p = default_assertion_failure_proc
221+ }
222+ p (" type assertion" , string (buf[:i]), Source_Code_Location{file, line, column, " " })
223+ }
224+ handle_error (file, line, column, from, to)
225+ }
226+
227+ type_assertion_check_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid ) {
167228 if ok {
168229 return
169230 }
@@ -175,47 +236,90 @@ when ODIN_NO_RTTI {
175236 print_string (" to " )
176237 print_typeid (to)
177238 print_byte (' \n ' )
178- type_assertion_trap ()
239+ type_assertion_trap_contextless ()
179240 }
180241 handle_error (file, line, column, from, to)
181242 }
182243
183- type_assertion_check2 :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) {
244+ @ (private=" file" )
245+ type_assertion_variant_type :: proc " contextless" (id: typeid , data: rawptr ) -> typeid {
246+ if id == nil || data == nil {
247+ return id
248+ }
249+ ti := type_info_base (type_info_of (id))
250+ #partial switch v in ti.variant {
251+ case Type_Info_Any:
252+ return (^any )(data).id
253+ case Type_Info_Union:
254+ if v.tag_type == nil {
255+ if (^rawptr )(data)^ == nil {
256+ return nil
257+ }
258+ return v.variants[0 ].id
259+
260+ }
261+
262+ tag_ptr := uintptr (data) + v.tag_offset
263+ idx := 0
264+ switch v.tag_type.size {
265+ case 1 : idx = int ( (^u8 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
266+ case 2 : idx = int ( (^u16 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
267+ case 4 : idx = int ( (^u32 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
268+ case 8 : idx = int ( (^u64 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
269+ case 16 : idx = int ((^u128 )(tag_ptr)^); if !v.no_nil { idx -= 1 }
270+ }
271+ if idx < 0 {
272+ return nil
273+ } else if idx < len (v.variants) {
274+ return v.variants[idx].id
275+ }
276+ }
277+ return id
278+ }
279+
280+ type_assertion_check2_with_context :: proc " odin" (ok: bool , file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) {
184281 if ok {
185282 return
186283 }
187284
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
285+ @ (cold, no_instrumentation)
286+ handle_error :: proc " odin" (file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) -> ! {
287+ do_msg :: proc " contextless" (i: ^int , buf: []byte , file: string , line, column: i32 , from, to, actual: typeid ) -> bool {
288+ try_copy_string (i, buf, " Invalid type assertion from " ) or_return
289+ try_copy_typeid (i, buf, from) or_return
290+ try_copy_string (i, buf, " to " ) or_return
291+ try_copy_typeid (i, buf, to) or_return
292+ if actual != from {
293+ try_copy_string (i, buf, " , actual type: " ) or_return
294+ try_copy_typeid (i, buf, actual) or_return
210295 }
296+ return true
211297 }
212- return id
298+
299+ actual := type_assertion_variant_type (from, from_data)
300+
301+ buf: [TYPE_ASSERTION_BUFFER_SIZE]byte
302+ i := 0
303+ _ = do_msg (&i, buf[:], file, line, column, from, to, actual)
304+
305+ p := context .assertion_failure_proc
306+ if p == nil {
307+ p = default_assertion_failure_proc
308+ }
309+ p (" type assertion" , string (buf[:i]), Source_Code_Location{file, line, column, " " })
310+ }
311+ handle_error (file, line, column, from, to, from_data)
312+ }
313+
314+ type_assertion_check2_contextless :: proc " contextless" (ok: bool , file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) {
315+ if ok {
316+ return
213317 }
214318
215319 @ (cold, no_instrumentation)
216320 handle_error :: proc " contextless" (file: string , line, column: i32 , from, to: typeid , from_data: rawptr ) -> ! {
217321
218- actual := variant_type (from, from_data)
322+ actual := type_assertion_variant_type (from, from_data)
219323
220324 print_caller_location (Source_Code_Location{file, line, column, " " })
221325 print_string (" Invalid type assertion from " )
@@ -227,7 +331,7 @@ when ODIN_NO_RTTI {
227331 print_typeid (actual)
228332 }
229333 print_byte (' \n ' )
230- type_assertion_trap ()
334+ type_assertion_trap_contextless ()
231335 }
232336 handle_error (file, line, column, from, to, from_data)
233337 }
0 commit comments