test: 值/形状/私有键/内存内联测试迁入兄弟测试文件

This commit is contained in:
2026-09-15 18:04:15 +00:00
parent 263bdb5d27
commit 66ad14159d
8 changed files with 372 additions and 376 deletions
+1 -26
View File
@@ -156,29 +156,4 @@ impl Default for Epoch {
}
#[cfg(test)]
mod tests {
use super::*;
use crate::object::JsObject;
use crate::shape::EMPTY_SHAPE_ID;
use crate::value::JsValue;
#[test]
fn is_epoch_ptr_returns_true_for_epoch_object() {
let epoch = Epoch::new();
let obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
let ptr = epoch.alloc(obj);
assert!(epoch.is_epoch_ptr(ptr.cast::<u8>()));
}
#[test]
fn is_epoch_ptr_returns_false_for_heap_and_stack_pointers() {
let epoch = Epoch::new();
let persistent = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let stack_value = 7i32;
assert!(!epoch.is_epoch_ptr(persistent.as_ptr().cast::<u8>()));
assert!(!epoch.is_epoch_ptr((&stack_value as *const i32).cast::<u8>()));
assert!(!epoch.is_epoch_ptr(std::ptr::null()));
}
}
mod tests;
+24
View File
@@ -0,0 +1,24 @@
use super::*;
use crate::object::JsObject;
use crate::shape::EMPTY_SHAPE_ID;
use crate::value::JsValue;
#[test]
fn is_epoch_ptr_returns_true_for_epoch_object() {
let epoch = Epoch::new();
let obj = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
let ptr = epoch.alloc(obj);
assert!(epoch.is_epoch_ptr(ptr.cast::<u8>()));
}
#[test]
fn is_epoch_ptr_returns_false_for_heap_and_stack_pointers() {
let epoch = Epoch::new();
let persistent = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
let stack_value = 7i32;
assert!(!epoch.is_epoch_ptr(persistent.as_ptr().cast::<u8>()));
assert!(!epoch.is_epoch_ptr((&stack_value as *const i32).cast::<u8>()));
assert!(!epoch.is_epoch_ptr(std::ptr::null()));
}
+1 -78
View File
@@ -115,81 +115,4 @@ pub const fn well_known_symbol_id_from_key(key: u32) -> Option<u32> {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn private_name_ids_use_high_band() {
let id = make_private_name_id(7);
assert!(is_private_name_key(id));
assert_ne!(id, u32::MAX);
assert!(!is_private_name_key(7));
}
#[test]
fn symbol_keys_roundtrip() {
let key = make_symbol_key(0);
assert!(is_symbol_key(key));
assert!(is_private_name_key(key));
assert_eq!(symbol_index_from_key(key), 0);
assert!(well_known_symbol_id_from_key(key).is_none());
}
#[test]
fn symbol_keys_distinct_per_index() {
let a = make_symbol_key(1);
let b = make_symbol_key(2);
assert_ne!(a, b);
assert!(is_symbol_key(a));
assert!(is_symbol_key(b));
}
#[test]
fn symbol_keys_avoid_private_band() {
let id = make_private_name_id(12);
let key = make_symbol_key(12);
assert!(!is_symbol_key(id));
assert!(is_symbol_key(key));
assert_ne!(id, key);
}
#[test]
fn well_known_keys_reserve_low_slots() {
for id in 0..WELL_KNOWN_SYMBOL_COUNT {
let key = make_well_known_symbol_key(id);
assert!(is_symbol_key(key));
assert_eq!(well_known_symbol_id_from_key(key), Some(id));
}
let user_key = make_well_known_symbol_key(WELL_KNOWN_SYMBOL_COUNT);
assert!(well_known_symbol_id_from_key(user_key).is_none());
}
#[test]
fn symbol_index_mask_prevents_wrap() {
let key = make_symbol_key(SYMBOL_INDEX_MASK);
assert_eq!(symbol_index_from_key(key), SYMBOL_INDEX_MASK);
assert!(is_symbol_key(key));
}
#[test]
fn int_keys_stay_in_own_band() {
assert_eq!(make_int_key(0), INT_KEY_BASE);
assert_eq!(int_key_value(INT_KEY_BASE), 0);
assert_eq!(int_key_value(make_int_key(123)), 123);
assert!(is_int_key(make_int_key(0)));
assert!(!is_int_key(0));
assert!(!is_int_key(PRIVATE_NAME_BASE));
assert!(!is_private_name_key(make_int_key(0)));
assert!(!is_symbol_key(make_int_key(0)));
assert_ne!(make_int_key(5), make_private_name_id(5));
assert_ne!(make_int_key(5), make_symbol_key(5));
}
#[test]
fn int_key_roundtrip_max() {
let key = make_int_key(INT_KEY_COUNT - 1);
assert!(is_int_key(key));
assert!(key < PRIVATE_NAME_BASE);
assert_eq!(int_key_value(key), INT_KEY_COUNT - 1);
}
}
mod tests;
@@ -0,0 +1,76 @@
use super::*;
#[test]
fn private_name_ids_use_high_band() {
let id = make_private_name_id(7);
assert!(is_private_name_key(id));
assert_ne!(id, u32::MAX);
assert!(!is_private_name_key(7));
}
#[test]
fn symbol_keys_roundtrip() {
let key = make_symbol_key(0);
assert!(is_symbol_key(key));
assert!(is_private_name_key(key));
assert_eq!(symbol_index_from_key(key), 0);
assert!(well_known_symbol_id_from_key(key).is_none());
}
#[test]
fn symbol_keys_distinct_per_index() {
let a = make_symbol_key(1);
let b = make_symbol_key(2);
assert_ne!(a, b);
assert!(is_symbol_key(a));
assert!(is_symbol_key(b));
}
#[test]
fn symbol_keys_avoid_private_band() {
let id = make_private_name_id(12);
let key = make_symbol_key(12);
assert!(!is_symbol_key(id));
assert!(is_symbol_key(key));
assert_ne!(id, key);
}
#[test]
fn well_known_keys_reserve_low_slots() {
for id in 0..WELL_KNOWN_SYMBOL_COUNT {
let key = make_well_known_symbol_key(id);
assert!(is_symbol_key(key));
assert_eq!(well_known_symbol_id_from_key(key), Some(id));
}
let user_key = make_well_known_symbol_key(WELL_KNOWN_SYMBOL_COUNT);
assert!(well_known_symbol_id_from_key(user_key).is_none());
}
#[test]
fn symbol_index_mask_prevents_wrap() {
let key = make_symbol_key(SYMBOL_INDEX_MASK);
assert_eq!(symbol_index_from_key(key), SYMBOL_INDEX_MASK);
assert!(is_symbol_key(key));
}
#[test]
fn int_keys_stay_in_own_band() {
assert_eq!(make_int_key(0), INT_KEY_BASE);
assert_eq!(int_key_value(INT_KEY_BASE), 0);
assert_eq!(int_key_value(make_int_key(123)), 123);
assert!(is_int_key(make_int_key(0)));
assert!(!is_int_key(0));
assert!(!is_int_key(PRIVATE_NAME_BASE));
assert!(!is_private_name_key(make_int_key(0)));
assert!(!is_symbol_key(make_int_key(0)));
assert_ne!(make_int_key(5), make_private_name_id(5));
assert_ne!(make_int_key(5), make_symbol_key(5));
}
#[test]
fn int_key_roundtrip_max() {
let key = make_int_key(INT_KEY_COUNT - 1);
assert!(is_int_key(key));
assert!(key < PRIVATE_NAME_BASE);
assert_eq!(int_key_value(key), INT_KEY_COUNT - 1);
}
+1 -84
View File
@@ -185,87 +185,4 @@ pub fn shape_prop_count(shape_id: ShapeId) -> u32 {
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_shape_exists() {
let s = get_shape(EMPTY_SHAPE_ID);
assert!(s.is_some());
let s = s.unwrap();
assert_eq!(s.id, EMPTY_SHAPE_ID);
assert!(s.parent.is_none());
}
#[test]
fn make_shape_creates_new_id() {
let key: StringIndex = 1_000_000;
let s1 = make_shape(EMPTY_SHAPE_ID, key);
assert!(s1 > EMPTY_SHAPE_ID);
let shape = get_shape(s1).unwrap();
assert_eq!(shape.property_name, key);
assert_eq!(shape.parent, Some(EMPTY_SHAPE_ID));
}
#[test]
fn hash_cons_returns_same_id() {
let key: StringIndex = 1_000_001;
let a = make_shape(EMPTY_SHAPE_ID, key);
let b = make_shape(EMPTY_SHAPE_ID, key);
assert_eq!(a, b);
}
#[test]
fn different_props_different_ids() {
let a = make_shape(EMPTY_SHAPE_ID, 1_000_002);
let b = make_shape(EMPTY_SHAPE_ID, 1_000_003);
assert_ne!(a, b);
}
#[test]
fn chain_of_three() {
let s1 = make_shape(EMPTY_SHAPE_ID, 1_000_010);
let s2 = make_shape(s1, 1_000_020);
let s3 = make_shape(s2, 1_000_030);
assert_eq!(shape_prop_count(s3), 3);
assert_eq!(lookup_position(s3, 1_000_030), Some(2));
assert_eq!(lookup_position(s3, 1_000_020), Some(1));
assert_eq!(lookup_position(s3, 1_000_010), Some(0));
assert_eq!(lookup_position(s3, 99), None);
}
#[test]
fn two_branches_share_ancestor() {
let base = make_shape(EMPTY_SHAPE_ID, 1_000_040);
let branch_a = make_shape(base, 1_000_050);
let branch_b = make_shape(base, 1_000_060);
assert_ne!(branch_a, branch_b);
let a_shape = get_shape(branch_a).unwrap();
let b_shape = get_shape(branch_b).unwrap();
assert_eq!(a_shape.parent, Some(base));
assert_eq!(b_shape.parent, Some(base));
}
#[test]
fn edge_same_structure_different_names() {
let s1 = make_shape(EMPTY_SHAPE_ID, 1_000_070);
let s2 = make_shape(s1, 1_000_080);
let s3 = make_shape(EMPTY_SHAPE_ID, 1_000_090);
let s4 = make_shape(s3, 1_000_100);
assert_ne!(s1, s3);
assert_ne!(s2, s4);
assert_eq!(lookup_position(s2, 1_000_070), Some(0));
assert_eq!(lookup_position(s4, 1_000_090), Some(0));
}
#[test]
fn has_property_works() {
let s1 = make_shape(EMPTY_SHAPE_ID, 1_000_110);
let s2 = make_shape(s1, 1_000_120);
assert!(has_property(s2, 1_000_110));
assert!(has_property(s2, 1_000_120));
assert!(!has_property(s2, 99));
}
}
mod tests;
+82
View File
@@ -0,0 +1,82 @@
use super::*;
#[test]
fn empty_shape_exists() {
let s = get_shape(EMPTY_SHAPE_ID);
assert!(s.is_some());
let s = s.unwrap();
assert_eq!(s.id, EMPTY_SHAPE_ID);
assert!(s.parent.is_none());
}
#[test]
fn make_shape_creates_new_id() {
let key: StringIndex = 1_000_000;
let s1 = make_shape(EMPTY_SHAPE_ID, key);
assert!(s1 > EMPTY_SHAPE_ID);
let shape = get_shape(s1).unwrap();
assert_eq!(shape.property_name, key);
assert_eq!(shape.parent, Some(EMPTY_SHAPE_ID));
}
#[test]
fn hash_cons_returns_same_id() {
let key: StringIndex = 1_000_001;
let a = make_shape(EMPTY_SHAPE_ID, key);
let b = make_shape(EMPTY_SHAPE_ID, key);
assert_eq!(a, b);
}
#[test]
fn different_props_different_ids() {
let a = make_shape(EMPTY_SHAPE_ID, 1_000_002);
let b = make_shape(EMPTY_SHAPE_ID, 1_000_003);
assert_ne!(a, b);
}
#[test]
fn chain_of_three() {
let s1 = make_shape(EMPTY_SHAPE_ID, 1_000_010);
let s2 = make_shape(s1, 1_000_020);
let s3 = make_shape(s2, 1_000_030);
assert_eq!(shape_prop_count(s3), 3);
assert_eq!(lookup_position(s3, 1_000_030), Some(2));
assert_eq!(lookup_position(s3, 1_000_020), Some(1));
assert_eq!(lookup_position(s3, 1_000_010), Some(0));
assert_eq!(lookup_position(s3, 99), None);
}
#[test]
fn two_branches_share_ancestor() {
let base = make_shape(EMPTY_SHAPE_ID, 1_000_040);
let branch_a = make_shape(base, 1_000_050);
let branch_b = make_shape(base, 1_000_060);
assert_ne!(branch_a, branch_b);
let a_shape = get_shape(branch_a).unwrap();
let b_shape = get_shape(branch_b).unwrap();
assert_eq!(a_shape.parent, Some(base));
assert_eq!(b_shape.parent, Some(base));
}
#[test]
fn edge_same_structure_different_names() {
let s1 = make_shape(EMPTY_SHAPE_ID, 1_000_070);
let s2 = make_shape(s1, 1_000_080);
let s3 = make_shape(EMPTY_SHAPE_ID, 1_000_090);
let s4 = make_shape(s3, 1_000_100);
assert_ne!(s1, s3);
assert_ne!(s2, s4);
assert_eq!(lookup_position(s2, 1_000_070), Some(0));
assert_eq!(lookup_position(s4, 1_000_090), Some(0));
}
#[test]
fn has_property_works() {
let s1 = make_shape(EMPTY_SHAPE_ID, 1_000_110);
let s2 = make_shape(s1, 1_000_120);
assert!(has_property(s2, 1_000_110));
assert!(has_property(s2, 1_000_120));
assert!(!has_property(s2, 99));
}
+1 -188
View File
@@ -476,191 +476,4 @@ impl fmt::Debug for JsValue {
}
#[cfg(test)]
mod tests {
use super::{JsType, JsValue};
use num_bigint::BigInt;
use proptest::prelude::*;
use proptest::test_runner::TestRunner;
#[test]
fn int_roundtrip_prop() {
let mut runner = TestRunner::default();
runner
.run(&(i32::MIN..=i32::MAX), |v| {
let val = JsValue::int(v);
assert!(val.is_int());
assert_eq!(val.as_int(), v);
Ok(())
})
.unwrap();
}
#[test]
fn float_roundtrip_prop() {
let mut runner = TestRunner::default();
runner
.run(&any::<f64>(), |v| {
let val = JsValue::float(v);
assert!(val.is_double());
if !v.is_nan() {
assert_eq!(val.as_double(), v);
}
Ok(())
})
.unwrap();
}
#[test]
fn bool_roundtrip_prop() {
let mut runner = TestRunner::default();
runner
.run(&any::<bool>(), |v| {
let val = JsValue::bool(v);
assert!(val.is_bool());
assert_eq!(val.as_bool(), v);
Ok(())
})
.unwrap();
}
#[test]
fn random_u64_type_safety() {
let mut runner = TestRunner::default();
runner
.run(&any::<u64>(), |bits| {
let val = JsValue::from_bits(bits);
let matched = [
val.is_double(),
val.is_int(),
val.is_bool(),
val.is_null(),
val.is_undefined(),
val.is_object(),
val.is_string(),
val.is_symbol(),
val.is_bigint(),
];
let count = matched.iter().filter(|&&x| x).count();
assert_eq!(count, 1, "bits={bits:#018x} matched {count} types");
Ok(())
})
.unwrap();
}
#[test]
fn js_type_matches_tag_checks() {
let mut runner = TestRunner::default();
runner
.run(&any::<u64>(), |bits| {
let val = JsValue::from_bits(bits);
let t = val.js_type();
// 随机位模式上 js_type 与 9 个 is_* 检查 1:1 对拍。
let expected = if val.is_double() {
JsType::Double
} else if val.is_int() {
JsType::Int
} else if val.is_bool() {
JsType::Bool
} else if val.is_null() {
JsType::Null
} else if val.is_undefined() {
JsType::Undefined
} else if val.is_object() {
JsType::Object
} else if val.is_string() {
JsType::String
} else if val.is_symbol() {
JsType::Symbol
} else {
JsType::BigInt
};
assert_eq!(t, expected, "bits={bits:#018x} js_type={t:?}");
assert_eq!(t.is_number(), val.is_int() || val.is_double(), "bits={bits:#018x}");
Ok(())
})
.unwrap();
}
#[test]
fn null_identity() {
assert_eq!(JsValue::null(), JsValue::null());
}
#[test]
fn undefined_identity() {
assert_eq!(JsValue::undefined(), JsValue::undefined());
}
#[test]
fn nullish_matches_only_null_and_undefined() {
assert!(JsValue::null().is_nullish());
assert!(JsValue::undefined().is_nullish());
assert!(!JsValue::int(0).is_nullish());
assert!(!JsValue::bool(false).is_nullish());
assert!(!JsValue::float(f64::NAN).is_nullish());
}
#[test]
fn canonicalization_idempotent() {
let mut runner = TestRunner::default();
runner
.run(&any::<f64>(), |v| {
let a = JsValue::float(v);
let b = JsValue::float(a.as_double());
assert_eq!(a, b);
Ok(())
})
.unwrap();
}
#[test]
fn string_ptr_roundtrip() {
use crate::object::JsString;
let s = Box::new(JsString::new("test".to_string()));
let ptr: *const JsString = &*s;
let val = JsValue::string(ptr);
assert!(val.is_string());
assert_eq!(val.as_string_ptr(), ptr);
assert_eq!(unsafe { (*val.as_string_ptr()).as_str() }, "test");
}
#[test]
fn string_pointer_equality() {
use crate::object::JsString;
let a = Box::new(JsString::new("x".to_string()));
let b = Box::new(JsString::new("x".to_string()));
let va = JsValue::string(&*a);
let vb = JsValue::string(&*b);
// 内容相同但分配不同 → NOT ==(指针同一性)。
// 语义内容相等在 coercion 层处理,不在 PartialEq。
assert_ne!(va, vb);
assert_eq!(va, JsValue::string(&*a));
assert_eq!(unsafe { (*va.as_string_ptr()).as_str() }, unsafe { (*vb.as_string_ptr()).as_str() });
}
#[test]
fn bigint_pointer_roundtrip() {
let boxed = Box::new(BigInt::from(123));
let ptr: *const BigInt = &*boxed;
let val = JsValue::bigint(ptr);
assert!(val.is_bigint());
assert_eq!(val.as_bigint_ptr(), ptr);
assert_eq!(unsafe { &*val.as_bigint_ptr() }, &BigInt::from(123));
assert!(!val.is_double());
assert!(!val.is_int());
}
#[test]
fn bigint_value_equality_by_value() {
let a = JsValue::bigint(Box::into_raw(Box::new(BigInt::from(7))));
let b = JsValue::bigint(Box::into_raw(Box::new(BigInt::from(7))));
let c = JsValue::bigint(Box::into_raw(Box::new(BigInt::from(8))));
assert_eq!(a, b);
assert_ne!(a, c);
unsafe {
drop(Box::from_raw(a.as_bigint_ptr() as *mut BigInt));
drop(Box::from_raw(b.as_bigint_ptr() as *mut BigInt));
drop(Box::from_raw(c.as_bigint_ptr() as *mut BigInt));
}
}
}
mod tests;
+186
View File
@@ -0,0 +1,186 @@
use super::{JsType, JsValue};
use num_bigint::BigInt;
use proptest::prelude::*;
use proptest::test_runner::TestRunner;
#[test]
fn int_roundtrip_prop() {
let mut runner = TestRunner::default();
runner
.run(&(i32::MIN..=i32::MAX), |v| {
let val = JsValue::int(v);
assert!(val.is_int());
assert_eq!(val.as_int(), v);
Ok(())
})
.unwrap();
}
#[test]
fn float_roundtrip_prop() {
let mut runner = TestRunner::default();
runner
.run(&any::<f64>(), |v| {
let val = JsValue::float(v);
assert!(val.is_double());
if !v.is_nan() {
assert_eq!(val.as_double(), v);
}
Ok(())
})
.unwrap();
}
#[test]
fn bool_roundtrip_prop() {
let mut runner = TestRunner::default();
runner
.run(&any::<bool>(), |v| {
let val = JsValue::bool(v);
assert!(val.is_bool());
assert_eq!(val.as_bool(), v);
Ok(())
})
.unwrap();
}
#[test]
fn random_u64_type_safety() {
let mut runner = TestRunner::default();
runner
.run(&any::<u64>(), |bits| {
let val = JsValue::from_bits(bits);
let matched = [
val.is_double(),
val.is_int(),
val.is_bool(),
val.is_null(),
val.is_undefined(),
val.is_object(),
val.is_string(),
val.is_symbol(),
val.is_bigint(),
];
let count = matched.iter().filter(|&&x| x).count();
assert_eq!(count, 1, "bits={bits:#018x} matched {count} types");
Ok(())
})
.unwrap();
}
#[test]
fn js_type_matches_tag_checks() {
let mut runner = TestRunner::default();
runner
.run(&any::<u64>(), |bits| {
let val = JsValue::from_bits(bits);
let t = val.js_type();
// 随机位模式上 js_type 与 9 个 is_* 检查 1:1 对拍。
let expected = if val.is_double() {
JsType::Double
} else if val.is_int() {
JsType::Int
} else if val.is_bool() {
JsType::Bool
} else if val.is_null() {
JsType::Null
} else if val.is_undefined() {
JsType::Undefined
} else if val.is_object() {
JsType::Object
} else if val.is_string() {
JsType::String
} else if val.is_symbol() {
JsType::Symbol
} else {
JsType::BigInt
};
assert_eq!(t, expected, "bits={bits:#018x} js_type={t:?}");
assert_eq!(t.is_number(), val.is_int() || val.is_double(), "bits={bits:#018x}");
Ok(())
})
.unwrap();
}
#[test]
fn null_identity() {
assert_eq!(JsValue::null(), JsValue::null());
}
#[test]
fn undefined_identity() {
assert_eq!(JsValue::undefined(), JsValue::undefined());
}
#[test]
fn nullish_matches_only_null_and_undefined() {
assert!(JsValue::null().is_nullish());
assert!(JsValue::undefined().is_nullish());
assert!(!JsValue::int(0).is_nullish());
assert!(!JsValue::bool(false).is_nullish());
assert!(!JsValue::float(f64::NAN).is_nullish());
}
#[test]
fn canonicalization_idempotent() {
let mut runner = TestRunner::default();
runner
.run(&any::<f64>(), |v| {
let a = JsValue::float(v);
let b = JsValue::float(a.as_double());
assert_eq!(a, b);
Ok(())
})
.unwrap();
}
#[test]
fn string_ptr_roundtrip() {
use crate::object::JsString;
let s = Box::new(JsString::new("test".to_string()));
let ptr: *const JsString = &*s;
let val = JsValue::string(ptr);
assert!(val.is_string());
assert_eq!(val.as_string_ptr(), ptr);
assert_eq!(unsafe { (*val.as_string_ptr()).as_str() }, "test");
}
#[test]
fn string_pointer_equality() {
use crate::object::JsString;
let a = Box::new(JsString::new("x".to_string()));
let b = Box::new(JsString::new("x".to_string()));
let va = JsValue::string(&*a);
let vb = JsValue::string(&*b);
// 内容相同但分配不同 → NOT ==(指针同一性)。
// 语义内容相等在 coercion 层处理,不在 PartialEq。
assert_ne!(va, vb);
assert_eq!(va, JsValue::string(&*a));
assert_eq!(unsafe { (*va.as_string_ptr()).as_str() }, unsafe { (*vb.as_string_ptr()).as_str() });
}
#[test]
fn bigint_pointer_roundtrip() {
let boxed = Box::new(BigInt::from(123));
let ptr: *const BigInt = &*boxed;
let val = JsValue::bigint(ptr);
assert!(val.is_bigint());
assert_eq!(val.as_bigint_ptr(), ptr);
assert_eq!(unsafe { &*val.as_bigint_ptr() }, &BigInt::from(123));
assert!(!val.is_double());
assert!(!val.is_int());
}
#[test]
fn bigint_value_equality_by_value() {
let a = JsValue::bigint(Box::into_raw(Box::new(BigInt::from(7))));
let b = JsValue::bigint(Box::into_raw(Box::new(BigInt::from(7))));
let c = JsValue::bigint(Box::into_raw(Box::new(BigInt::from(8))));
assert_eq!(a, b);
assert_ne!(a, c);
unsafe {
drop(Box::from_raw(a.as_bigint_ptr() as *mut BigInt));
drop(Box::from_raw(b.as_bigint_ptr() as *mut BigInt));
drop(Box::from_raw(c.as_bigint_ptr() as *mut BigInt));
}
}