diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 497218cb8..49011f112 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -101,6 +101,16 @@ use super::{make_record, Program, ProgramState, Register}; use crate::resolve_ext_path; use crate::{bail_constraint_error, must_be_btree_cursor, MvStore, Pager, Result}; +/// Macro to destructure an Insn, only to be used when it +/// is *impossible* to be another variant. +macro_rules! assert_insn { + ($pat:pat = $insn:expr) => { + let $pat = $insn else { + unsafe { std::hint::unreachable_unchecked() } + }; + }; +} + macro_rules! return_if_io { ($expr:expr) => { match $expr? { @@ -145,9 +155,7 @@ pub fn op_init( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Init { target_pc } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Init { target_pc } = insn); assert!(target_pc.is_offset()); state.pc = target_pc.as_offset_int(); Ok(InsnFunctionStepResult::Step) @@ -160,9 +168,7 @@ pub fn op_add( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Add { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Add { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -179,9 +185,7 @@ pub fn op_subtract( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Subtract { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Subtract { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -198,9 +202,7 @@ pub fn op_multiply( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Multiply { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Multiply { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -217,9 +219,7 @@ pub fn op_divide( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Divide { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Divide { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -236,9 +236,7 @@ pub fn op_drop_index( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::DropIndex { index, db: _ } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::DropIndex { index, db: _ } = insn); program .connection .with_schema_mut(|schema| schema.remove_index(index)); @@ -253,9 +251,7 @@ pub fn op_remainder( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Remainder { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Remainder { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -272,9 +268,7 @@ pub fn op_bit_and( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::BitAnd { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::BitAnd { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -291,9 +285,7 @@ pub fn op_bit_or( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::BitOr { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::BitOr { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -310,9 +302,7 @@ pub fn op_bit_not( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::BitNot { reg, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::BitNot { reg, dest } = insn); state.registers[*dest] = Register::Value(state.registers[*reg].get_owned_value().exec_bit_not()); state.pc += 1; @@ -326,14 +316,13 @@ pub fn op_checkpoint( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Checkpoint { - database: _, - checkpoint_mode, - dest, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Checkpoint { + database: _, + checkpoint_mode, + dest, + } = insn + ); if !program.connection.auto_commit.get() { // TODO: sqlite returns "Runtime error: database table is locked (6)" when a table is in use // when a checkpoint is attempted. We don't have table locks, so return TableLocked for any @@ -394,9 +383,7 @@ pub fn op_null_row( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::NullRow { cursor_id } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::NullRow { cursor_id } = insn); { let mut cursor = must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "NullRow"); let cursor = cursor.as_btree_mut(); @@ -413,15 +400,14 @@ pub fn op_compare( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Compare { - start_reg_a, - start_reg_b, - count, - collation, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Compare { + start_reg_a, + start_reg_b, + count, + collation, + } = insn + ); let start_reg_a = *start_reg_a; let start_reg_b = *start_reg_b; let count = *count; @@ -459,14 +445,13 @@ pub fn op_jump( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Jump { - target_pc_lt, - target_pc_eq, - target_pc_gt, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Jump { + target_pc_lt, + target_pc_eq, + target_pc_gt, + } = insn + ); assert!(target_pc_lt.is_offset()); assert!(target_pc_eq.is_offset()); assert!(target_pc_gt.is_offset()); @@ -492,14 +477,13 @@ pub fn op_move( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Move { - source_reg, - dest_reg, - count, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Move { + source_reg, + dest_reg, + count, + } = insn + ); let source_reg = *source_reg; let dest_reg = *dest_reg; let count = *count; @@ -520,14 +504,13 @@ pub fn op_if_pos( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IfPos { - reg, - target_pc, - decrement_by, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IfPos { + reg, + target_pc, + decrement_by, + } = insn + ); assert!(target_pc.is_offset()); let reg = *reg; let target_pc = *target_pc; @@ -555,9 +538,7 @@ pub fn op_not_null( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::NotNull { reg, target_pc } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::NotNull { reg, target_pc } = insn); assert!(target_pc.is_offset()); let reg = *reg; let target_pc = *target_pc; @@ -867,14 +848,13 @@ pub fn op_if( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::If { - reg, - target_pc, - jump_if_null, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::If { + reg, + target_pc, + jump_if_null, + } = insn + ); assert!(target_pc.is_offset()); if state.registers[*reg] .get_owned_value() @@ -894,14 +874,13 @@ pub fn op_if_not( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IfNot { - reg, - target_pc, - jump_if_null, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IfNot { + reg, + target_pc, + jump_if_null, + } = insn + ); assert!(target_pc.is_offset()); if state.registers[*reg] .get_owned_value() @@ -921,14 +900,13 @@ pub fn op_open_read( _pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::OpenRead { - cursor_id, - root_page, - db, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::OpenRead { + cursor_id, + root_page, + db, + } = insn + ); let pager = program.get_pager_from_database_index(db); @@ -993,9 +971,7 @@ pub fn op_vopen( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VOpen { cursor_id } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::VOpen { cursor_id } = insn); let (_, cursor_type) = program.cursor_ref.get(*cursor_id).unwrap(); let CursorType::VirtualTable(virtual_table) = cursor_type else { panic!("VOpen on non-virtual table cursor"); @@ -1018,14 +994,13 @@ pub fn op_vcreate( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VCreate { - module_name, - table_name, - args_reg, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::VCreate { + module_name, + table_name, + args_reg, + } = insn + ); let module_name = state.registers[*module_name].get_owned_value().to_string(); let table_name = state.registers[*table_name].get_owned_value().to_string(); let args = if let Some(args_reg) = args_reg { @@ -1059,17 +1034,16 @@ pub fn op_vfilter( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VFilter { - cursor_id, - pc_if_empty, - arg_count, - args_reg, - idx_str, - idx_num, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::VFilter { + cursor_id, + pc_if_empty, + arg_count, + args_reg, + idx_str, + idx_num, + } = insn + ); let has_rows = { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_virtual_mut(); @@ -1099,14 +1073,13 @@ pub fn op_vcolumn( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VColumn { - cursor_id, - column, - dest, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::VColumn { + cursor_id, + column, + dest, + } = insn + ); let value = { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_virtual_mut(); @@ -1124,16 +1097,15 @@ pub fn op_vupdate( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VUpdate { - cursor_id, - arg_count, - start_reg, - conflict_action, - .. - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::VUpdate { + cursor_id, + arg_count, + start_reg, + conflict_action, + .. + } = insn + ); let (_, cursor_type) = program.cursor_ref.get(*cursor_id).unwrap(); let CursorType::VirtualTable(virtual_table) = cursor_type else { panic!("VUpdate on non-virtual table cursor"); @@ -1188,13 +1160,12 @@ pub fn op_vnext( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VNext { - cursor_id, - pc_if_next, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::VNext { + cursor_id, + pc_if_next, + } = insn + ); let has_more = { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_virtual_mut(); @@ -1215,9 +1186,7 @@ pub fn op_vdestroy( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::VDestroy { db, table_name } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::VDestroy { db, table_name } = insn); let conn = program.connection.clone(); { let Some(vtab) = conn.syms.borrow_mut().vtabs.remove(table_name) else { @@ -1239,14 +1208,13 @@ pub fn op_open_pseudo( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::OpenPseudo { - cursor_id, - content_reg: _, - num_fields: _, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::OpenPseudo { + cursor_id, + content_reg: _, + num_fields: _, + } = insn + ); { let mut cursors = state.cursors.borrow_mut(); let cursor = PseudoCursor::default(); @@ -1266,13 +1234,12 @@ pub fn op_rewind( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Rewind { - cursor_id, - pc_if_empty, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Rewind { + cursor_id, + pc_if_empty, + } = insn + ); assert!(pc_if_empty.is_offset()); let is_empty = { let mut cursor = must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "Rewind"); @@ -1295,13 +1262,12 @@ pub fn op_last( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Last { - cursor_id, - pc_if_empty, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Last { + cursor_id, + pc_if_empty, + } = insn + ); assert!(pc_if_empty.is_offset()); let is_empty = { let mut cursor = must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "Last"); @@ -1416,15 +1382,14 @@ pub fn op_column( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Column { - cursor_id, - column, - dest, - default, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Column { + cursor_id, + column, + dest, + default, + } = insn + ); if let Some((index_cursor_id, table_cursor_id)) = state.deferred_seeks[*cursor_id].take() { let deferred_seek = 'd: { let rowid = { @@ -1711,15 +1676,14 @@ pub fn op_type_check( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::TypeCheck { - start_reg, - count, - check_generated, - table_reference, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::TypeCheck { + start_reg, + count, + check_generated, + table_reference, + } = insn + ); assert!(table_reference.is_strict); state.registers[*start_reg..*start_reg + *count] .iter_mut() @@ -1773,15 +1737,14 @@ pub fn op_make_record( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::MakeRecord { - start_reg, - count, - dest_reg, - .. - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::MakeRecord { + start_reg, + count, + dest_reg, + .. + } = insn + ); let record = make_record(&state.registers, start_reg, count); state.registers[*dest_reg] = Register::Record(record); state.pc += 1; @@ -1795,9 +1758,7 @@ pub fn op_result_row( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::ResultRow { start_reg, count } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::ResultRow { start_reg, count } = insn); let row = Row { values: &state.registers[*start_reg] as *const Register, count: *count, @@ -1814,13 +1775,12 @@ pub fn op_next( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Next { - cursor_id, - pc_if_next, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Next { + cursor_id, + pc_if_next, + } = insn + ); assert!(pc_if_next.is_offset()); let is_empty = { let mut cursor = must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "Next"); @@ -1845,13 +1805,12 @@ pub fn op_prev( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Prev { - cursor_id, - pc_if_prev, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Prev { + cursor_id, + pc_if_prev, + } = insn + ); assert!(pc_if_prev.is_offset()); let is_empty = { let mut cursor = must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "Prev"); @@ -1915,13 +1874,12 @@ pub fn op_halt( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Halt { - err_code, - description, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Halt { + err_code, + description, + } = insn + ); if *err_code > 0 { // invalidate page cache in case of error pager.clear_page_cache(); @@ -1966,14 +1924,13 @@ pub fn op_halt_if_null( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::HaltIfNull { - target_reg, - err_code, - description, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::HaltIfNull { + target_reg, + err_code, + description, + } = insn + ); if state.registers[*target_reg].get_owned_value() == &Value::Null { halt(program, state, pager, mv_store, *err_code, description) } else { @@ -1989,14 +1946,13 @@ pub fn op_transaction( _pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Transaction { - db, - write, - schema_cookie, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Transaction { + db, + write, + schema_cookie, + } = insn + ); let conn = program.connection.clone(); if *write && conn._db.open_flags.contains(OpenFlags::ReadOnly) { return Err(LimboError::ReadOnly); @@ -2119,13 +2075,12 @@ pub fn op_auto_commit( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::AutoCommit { - auto_commit, - rollback, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::AutoCommit { + auto_commit, + rollback, + } = insn + ); let conn = program.connection.clone(); if state.commit_state == CommitState::Committing { return program @@ -2173,9 +2128,7 @@ pub fn op_goto( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Goto { target_pc } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Goto { target_pc } = insn); assert!(target_pc.is_offset()); state.pc = target_pc.as_offset_int(); Ok(InsnFunctionStepResult::Step) @@ -2188,13 +2141,12 @@ pub fn op_gosub( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Gosub { - target_pc, - return_reg, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Gosub { + target_pc, + return_reg, + } = insn + ); assert!(target_pc.is_offset()); state.registers[*return_reg] = Register::Value(Value::Integer((state.pc + 1) as i64)); state.pc = target_pc.as_offset_int(); @@ -2208,13 +2160,12 @@ pub fn op_return( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Return { - return_reg, - can_fallthrough, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Return { + return_reg, + can_fallthrough, + } = insn + ); if let Value::Integer(pc) = state.registers[*return_reg].get_owned_value() { let pc: u32 = (*pc) .try_into() @@ -2238,9 +2189,7 @@ pub fn op_integer( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Integer { value, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Integer { value, dest } = insn); state.registers[*dest] = Register::Value(Value::Integer(*value)); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -2253,9 +2202,7 @@ pub fn op_real( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Real { value, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Real { value, dest } = insn); state.registers[*dest] = Register::Value(Value::Float(*value)); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -2268,9 +2215,7 @@ pub fn op_real_affinity( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::RealAffinity { register } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::RealAffinity { register } = insn); if let Value::Integer(i) = &state.registers[*register].get_owned_value() { state.registers[*register] = Register::Value(Value::Float(*i as f64)); }; @@ -2285,9 +2230,7 @@ pub fn op_string8( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::String8 { value, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::String8 { value, dest } = insn); state.registers[*dest] = Register::Value(Value::build_text(value)); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -2300,9 +2243,7 @@ pub fn op_blob( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Blob { value, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Blob { value, dest } = insn); state.registers[*dest] = Register::Value(Value::Blob(value.clone())); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -2315,9 +2256,7 @@ pub fn op_row_data( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::RowData { cursor_id, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::RowData { cursor_id, dest } = insn); let record = { let mut cursor_ref = @@ -2346,9 +2285,7 @@ pub fn op_row_id( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::RowId { cursor_id, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::RowId { cursor_id, dest } = insn); if let Some((index_cursor_id, table_cursor_id)) = state.deferred_seeks[*cursor_id].take() { let deferred_seek = 'd: { let rowid = { @@ -2411,9 +2348,7 @@ pub fn op_idx_row_id( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxRowId { cursor_id, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::IdxRowId { cursor_id, dest } = insn); let mut cursors = state.cursors.borrow_mut(); let cursor = cursors.get_mut(*cursor_id).unwrap().as_mut().unwrap(); let cursor = cursor.as_btree_mut(); @@ -2433,14 +2368,13 @@ pub fn op_seek_rowid( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SeekRowid { - cursor_id, - src_reg, - target_pc, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SeekRowid { + cursor_id, + src_reg, + target_pc, + } = insn + ); assert!(target_pc.is_offset()); let pc = { let mut cursor = state.get_cursor(*cursor_id); @@ -2489,13 +2423,12 @@ pub fn op_deferred_seek( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::DeferredSeek { - index_cursor_id, - table_cursor_id, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::DeferredSeek { + index_cursor_id, + table_cursor_id, + } = insn + ); state.deferred_seeks[*table_cursor_id] = Some((*index_cursor_id, *table_cursor_id)); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -2915,15 +2848,14 @@ pub fn op_idx_ge( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxGE { - cursor_id, - start_reg, - num_regs, - target_pc, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IdxGE { + cursor_id, + start_reg, + num_regs, + target_pc, + } = insn + ); assert!(target_pc.is_offset()); let pc = { @@ -2966,12 +2898,11 @@ pub fn op_seek_end( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - if let Insn::SeekEnd { cursor_id } = *insn { + assert_insn!(Insn::SeekEnd { cursor_id } = *insn); + { let mut cursor = state.get_cursor(cursor_id); let cursor = cursor.as_btree_mut(); return_if_io!(cursor.seek_end()); - } else { - unreachable!("unexpected Insn {:?}", insn) } state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -2985,15 +2916,14 @@ pub fn op_idx_le( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxLE { - cursor_id, - start_reg, - num_regs, - target_pc, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IdxLE { + cursor_id, + start_reg, + num_regs, + target_pc, + } = insn + ); assert!(target_pc.is_offset()); let pc = { @@ -3036,15 +2966,14 @@ pub fn op_idx_gt( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxGT { - cursor_id, - start_reg, - num_regs, - target_pc, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IdxGT { + cursor_id, + start_reg, + num_regs, + target_pc, + } = insn + ); assert!(target_pc.is_offset()); let pc = { @@ -3087,15 +3016,14 @@ pub fn op_idx_lt( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxLT { - cursor_id, - start_reg, - num_regs, - target_pc, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IdxLT { + cursor_id, + start_reg, + num_regs, + target_pc, + } = insn + ); assert!(target_pc.is_offset()); let pc = { @@ -3138,9 +3066,7 @@ pub fn op_decr_jump_zero( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::DecrJumpZero { reg, target_pc } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::DecrJumpZero { reg, target_pc } = insn); assert!(target_pc.is_offset()); match state.registers[*reg].get_owned_value() { Value::Integer(n) => { @@ -3191,15 +3117,14 @@ pub fn op_agg_step( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::AggStep { - acc_reg, - col, - delimiter, - func, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::AggStep { + acc_reg, + col, + delimiter, + func, + } = insn + ); if let Register::Value(Value::Null) = state.registers[*acc_reg] { state.registers[*acc_reg] = match func { AggFunc::Avg => { @@ -3496,9 +3421,7 @@ pub fn op_agg_final( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::AggFinal { register, func } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::AggFinal { register, func } = insn); match state.registers[*register].borrow_mut() { Register::Aggregate(agg) => match func { AggFunc::Avg => { @@ -3636,15 +3559,14 @@ pub fn op_sorter_open( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SorterOpen { - cursor_id, - columns: _, - order, - collations, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SorterOpen { + cursor_id, + columns: _, + order, + collations, + } = insn + ); let cache_size = program.connection.get_cache_size(); // Set the buffer size threshold to be roughly the same as the limit configured for the page-cache. let page_size = pager @@ -3684,14 +3606,13 @@ pub fn op_sorter_data( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SorterData { - cursor_id, - dest_reg, - pseudo_cursor, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SorterData { + cursor_id, + dest_reg, + pseudo_cursor, + } = insn + ); let record = { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_sorter_mut(); @@ -3720,13 +3641,12 @@ pub fn op_sorter_insert( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SorterInsert { - cursor_id, - record_reg, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SorterInsert { + cursor_id, + record_reg, + } = insn + ); { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_sorter_mut(); @@ -3747,13 +3667,12 @@ pub fn op_sorter_sort( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SorterSort { - cursor_id, - pc_if_empty, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SorterSort { + cursor_id, + pc_if_empty, + } = insn + ); let is_empty = { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_sorter_mut(); @@ -3780,13 +3699,12 @@ pub fn op_sorter_next( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SorterNext { - cursor_id, - pc_if_next, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SorterNext { + cursor_id, + pc_if_next, + } = insn + ); assert!(pc_if_next.is_offset()); let has_more = { let mut cursor = state.get_cursor(*cursor_id); @@ -3811,15 +3729,14 @@ pub fn op_function( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Function { - constant_mask, - func, - start_reg, - dest, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Function { + constant_mask, + func, + start_reg, + dest, + } = insn + ); let arg_count = func.arg_count; match &func.func { @@ -5029,14 +4946,13 @@ pub fn op_init_coroutine( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::InitCoroutine { - yield_reg, - jump_on_definition, - start_offset, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::InitCoroutine { + yield_reg, + jump_on_definition, + start_offset, + } = insn + ); assert!(jump_on_definition.is_offset()); let start_offset = start_offset.as_offset_int(); state.registers[*yield_reg] = Register::Value(Value::Integer(start_offset as i64)); @@ -5057,9 +4973,8 @@ pub fn op_end_coroutine( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::EndCoroutine { yield_reg } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::EndCoroutine { yield_reg } = insn); + if let Value::Integer(pc) = state.registers[*yield_reg].get_owned_value() { state.ended_coroutine.set(*yield_reg); let pc: u32 = (*pc) @@ -5079,13 +4994,12 @@ pub fn op_yield( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Yield { - yield_reg, - end_offset, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Yield { + yield_reg, + end_offset, + } = insn + ); if let Value::Integer(pc) = state.registers[*yield_reg].get_owned_value() { if state.ended_coroutine.get(*yield_reg) { state.pc = end_offset.as_offset_int(); @@ -5122,16 +5036,15 @@ pub fn op_insert( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Insert { - cursor: cursor_id, - key_reg, - record_reg, - flag, - table_name: _, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Insert { + cursor: cursor_id, + key_reg, + record_reg, + flag, + table_name: _, + } = insn + ); if state.op_insert_state == OpInsertState::UpdateLastRowid { let maybe_rowid = { @@ -5203,15 +5116,14 @@ pub fn op_int_64( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Int64 { - _p1, - out_reg, - _p3, - value, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Int64 { + _p1, + out_reg, + _p3, + value, + } = insn + ); state.registers[*out_reg] = Register::Value(Value::Integer(*value)); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -5224,9 +5136,7 @@ pub fn op_delete( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Delete { cursor_id } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Delete { cursor_id } = insn); { let mut cursor = state.get_cursor(*cursor_id); let cursor = cursor.as_btree_mut(); @@ -5251,15 +5161,14 @@ pub fn op_idx_delete( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxDelete { - cursor_id, - start_reg, - num_regs, - raise_error_if_no_matching_entry, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IdxDelete { + cursor_id, + start_reg, + num_regs, + raise_error_if_no_matching_entry, + } = insn + ); loop { tracing::debug!( @@ -5358,15 +5267,14 @@ pub fn op_idx_insert( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IdxInsert { - cursor_id, - record_reg, - flags, - .. - } = *insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IdxInsert { + cursor_id, + record_reg, + flags, + .. + } = *insn + ); let record_to_insert = match &state.registers[record_reg] { Register::Record(ref r) => r, @@ -5506,12 +5414,13 @@ pub fn op_new_rowid( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::NewRowid { - cursor, rowid_reg, .. - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::NewRowid { + cursor, + rowid_reg, + .. + } = insn + ); if let Some(mv_store) = mv_store { let rowid = { @@ -5639,9 +5548,7 @@ pub fn op_must_be_int( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::MustBeInt { reg } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::MustBeInt { reg } = insn); match &state.registers[*reg].get_owned_value() { Value::Integer(_) => {} Value::Float(f) => match cast_real_to_integer(*f) { @@ -5674,9 +5581,7 @@ pub fn op_soft_null( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SoftNull { reg } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::SoftNull { reg } = insn); state.registers[*reg] = Register::Value(Value::Null); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -5696,15 +5601,14 @@ pub fn op_no_conflict( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::NoConflict { - cursor_id, - target_pc, - record_reg, - num_regs, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::NoConflict { + cursor_id, + target_pc, + record_reg, + num_regs, + } = insn + ); loop { match &state.op_no_conflict_state { @@ -5792,14 +5696,13 @@ pub fn op_not_exists( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::NotExists { - cursor, - rowid_reg, - target_pc, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::NotExists { + cursor, + rowid_reg, + target_pc, + } = insn + ); let exists = if let Some(mv_store) = mv_store { let mut cursor = must_be_btree_cursor!(*cursor, program.cursor_ref, state, "NotExists"); let cursor = cursor.as_btree_mut(); @@ -5825,14 +5728,13 @@ pub fn op_offset_limit( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::OffsetLimit { - limit_reg, - combined_reg, - offset_reg, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::OffsetLimit { + limit_reg, + combined_reg, + offset_reg, + } = insn + ); let limit_val = match state.registers[*limit_reg].get_owned_value() { Value::Integer(val) => val, _ => { @@ -5870,14 +5772,13 @@ pub fn op_open_write( _pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::OpenWrite { - cursor_id, - root_page, - db, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::OpenWrite { + cursor_id, + root_page, + db, + } = insn + ); if program.connection.is_readonly(*db) { return Err(LimboError::ReadOnly); } @@ -5954,14 +5855,13 @@ pub fn op_copy( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Copy { - src_reg, - dst_reg, - extra_amount, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Copy { + src_reg, + dst_reg, + extra_amount, + } = insn + ); for i in 0..=*extra_amount { state.registers[*dst_reg + i] = state.registers[*src_reg + i].clone(); } @@ -5976,9 +5876,7 @@ pub fn op_create_btree( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::CreateBtree { db, root, flags } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::CreateBtree { db, root, flags } = insn); assert_eq!(*db, 0); @@ -6003,14 +5901,13 @@ pub fn op_destroy( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Destroy { - root, - former_root_reg, - is_temp, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Destroy { + root, + former_root_reg, + is_temp, + } = insn + ); if *is_temp == 1 { todo!("temp databases not implemented yet."); } @@ -6032,9 +5929,7 @@ pub fn op_drop_table( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::DropTable { db, table_name, .. } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::DropTable { db, table_name, .. } = insn); if *db > 0 { todo!("temp databases not implemented yet"); } @@ -6056,9 +5951,7 @@ pub fn op_close( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Close { cursor_id } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Close { cursor_id } = insn); let mut cursors = state.cursors.borrow_mut(); cursors.get_mut(*cursor_id).unwrap().take(); state.pc += 1; @@ -6072,9 +5965,7 @@ pub fn op_is_null( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IsNull { reg, target_pc } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::IsNull { reg, target_pc } = insn); if matches!(state.registers[*reg], Register::Value(Value::Null)) { state.pc = target_pc.as_offset_int(); } else { @@ -6090,9 +5981,7 @@ pub fn op_page_count( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::PageCount { db, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::PageCount { db, dest } = insn); if *db > 0 { // TODO: implement temp databases todo!("temp databases not implemented yet"); @@ -6114,13 +6003,12 @@ pub fn op_parse_schema( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::ParseSchema { - db: _, - where_clause, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::ParseSchema { + db: _, + where_clause, + } = insn + ); let conn = program.connection.clone(); // set auto commit to false in order for parse schema to not commit changes as transaction state is stored in connection, // and we use the same connection for nested query. @@ -6154,9 +6042,7 @@ pub fn op_read_cookie( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::ReadCookie { db, dest, cookie } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::ReadCookie { db, dest, cookie } = insn); if *db > 0 { // TODO: implement temp databases todo!("temp databases not implemented yet"); @@ -6186,15 +6072,14 @@ pub fn op_set_cookie( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::SetCookie { - db, - cookie, - value, - p5, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::SetCookie { + db, + cookie, + value, + p5, + } = insn + ); if *db > 0 { todo!("temp databases not implemented yet"); } @@ -6241,9 +6126,7 @@ pub fn op_shift_right( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::ShiftRight { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::ShiftRight { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -6260,9 +6143,7 @@ pub fn op_shift_left( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::ShiftLeft { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::ShiftLeft { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -6279,9 +6160,7 @@ pub fn op_add_imm( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::AddImm { register, value } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::AddImm { register, value } = insn); let current = &state.registers[*register]; let current_value = match current { @@ -6310,9 +6189,7 @@ pub fn op_variable( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Variable { index, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Variable { index, dest } = insn); state.registers[*dest] = Register::Value(state.get_parameter(*index)); state.pc += 1; Ok(InsnFunctionStepResult::Step) @@ -6325,9 +6202,7 @@ pub fn op_zero_or_null( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::ZeroOrNull { rg1, rg2, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::ZeroOrNull { rg1, rg2, dest } = insn); if *state.registers[*rg1].get_owned_value() == Value::Null || *state.registers[*rg2].get_owned_value() == Value::Null { @@ -6346,9 +6221,7 @@ pub fn op_not( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Not { reg, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Not { reg, dest } = insn); state.registers[*dest] = Register::Value(state.registers[*reg].get_owned_value().exec_boolean_not()); state.pc += 1; @@ -6362,9 +6235,7 @@ pub fn op_concat( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Concat { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Concat { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -6381,9 +6252,7 @@ pub fn op_and( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::And { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::And { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -6400,9 +6269,7 @@ pub fn op_or( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Or { lhs, rhs, dest } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Or { lhs, rhs, dest } = insn); state.registers[*dest] = Register::Value( state.registers[*lhs] .get_owned_value() @@ -6612,12 +6479,11 @@ pub fn op_once( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Once { - target_pc_when_reentered, - } = insn - else { - unreachable!("unexpected Insn: {:?}", insn) - }; + assert_insn!( + Insn::Once { + target_pc_when_reentered, + } = insn + ); assert!(target_pc_when_reentered.is_offset()); let offset = state.pc; if state.once.iter().any(|o| o == offset) { @@ -6698,14 +6564,13 @@ pub fn op_affinity( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Affinity { - start_reg, - count, - affinities, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Affinity { + start_reg, + count, + affinities, + } = insn + ); if affinities.len() != count.get() { return Err(LimboError::InternalError( @@ -6732,14 +6597,13 @@ pub fn op_count( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::Count { - cursor_id, - target_reg, - exact, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::Count { + cursor_id, + target_reg, + exact, + } = insn + ); let count = { let mut cursor = must_be_btree_cursor!(*cursor_id, program.cursor_ref, state, "Count"); @@ -6769,14 +6633,13 @@ pub fn op_integrity_check( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::IntegrityCk { - max_errors, - roots, - message_register, - } = insn - else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!( + Insn::IntegrityCk { + max_errors, + roots, + message_register, + } = insn + ); match &mut state.op_integrity_check_state { OpIntegrityCheckState::Start => { state.op_integrity_check_state = OpIntegrityCheckState::Checking { @@ -6822,9 +6685,7 @@ pub fn op_cast( _pager: &Rc, _mv_store: Option<&Arc>, ) -> Result { - let Insn::Cast { reg, affinity } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::Cast { reg, affinity } = insn); let value = state.registers[*reg].get_owned_value().clone(); let result = match affinity { @@ -6847,9 +6708,7 @@ pub fn op_rename_table( pager: &Rc, mv_store: Option<&Arc>, ) -> Result { - let Insn::RenameTable { from, to } = insn else { - unreachable!("unexpected Insn {:?}", insn) - }; + assert_insn!(Insn::RenameTable { from, to } = insn); let conn = program.connection.clone();