diff --git a/substrate/frame/referenda/src/lib.rs b/substrate/frame/referenda/src/lib.rs index fb8e9aa6a6..2d4d29b0bc 100644 --- a/substrate/frame/referenda/src/lib.rs +++ b/substrate/frame/referenda/src/lib.rs @@ -866,7 +866,7 @@ impl Pallet { let new_pos = queue.binary_search_by_key(&ayes, |x| x.1).unwrap_or_else(|x| x); branch = if maybe_old_pos.is_none() && new_pos > 0 { // Just insert. - queue.force_insert_keep_right(new_pos, (index, ayes)); + let _ = queue.force_insert_keep_right(new_pos, (index, ayes)); ServiceBranch::RequeuedInsertion } else if let Some(old_pos) = maybe_old_pos { // We were in the queue - slide into the correct position. diff --git a/substrate/frame/referenda/src/types.rs b/substrate/frame/referenda/src/types.rs index 1b028fdfe9..367fa2a4ba 100644 --- a/substrate/frame/referenda/src/types.rs +++ b/substrate/frame/referenda/src/types.rs @@ -86,7 +86,7 @@ impl> InsertSorted for BoundedVec { mut f: F, ) -> bool { let index = self.binary_search_by_key::(&f(&t), f).unwrap_or_else(|x| x); - self.force_insert_keep_right(index, t) + self.force_insert_keep_right(index, t).is_ok() } } diff --git a/substrate/frame/support/src/storage/bounded_vec.rs b/substrate/frame/support/src/storage/bounded_vec.rs index 86aa4d405c..206a7e5d4e 100644 --- a/substrate/frame/support/src/storage/bounded_vec.rs +++ b/substrate/frame/support/src/storage/bounded_vec.rs @@ -119,7 +119,17 @@ impl BoundedVec { self.0 } - /// Exactly the same semantics as [`Vec::remove`]. + /// Exactly the same semantics as [`slice::sort_by`]. + /// + /// This is safe since sorting cannot change the number of elements in the vector. + pub fn sort_by(&mut self, compare: F) + where + F: FnMut(&T, &T) -> sp_std::cmp::Ordering, + { + self.0.sort_by(compare) + } + + /// Exactly the same semantics as `Vec::remove`. /// /// # Panics /// @@ -128,7 +138,7 @@ impl BoundedVec { self.0.remove(index) } - /// Exactly the same semantics as [`Vec::swap_remove`]. + /// Exactly the same semantics as `slice::swap_remove`. /// /// # Panics /// @@ -137,12 +147,12 @@ impl BoundedVec { self.0.swap_remove(index) } - /// Exactly the same semantics as [`Vec::retain`]. + /// Exactly the same semantics as `Vec::retain`. pub fn retain bool>(&mut self, f: F) { self.0.retain(f) } - /// Exactly the same semantics as [`slice::get_mut`]. + /// Exactly the same semantics as `slice::get_mut`. pub fn get_mut>( &mut self, index: I, @@ -150,12 +160,16 @@ impl BoundedVec { self.0.get_mut(index) } - /// Exactly the same semantics as [`Vec::truncate`]. + /// Exactly the same semantics as `Vec::truncate`. + /// + /// This is safe because `truncate` can never increase the length of the internal vector. pub fn truncate(&mut self, s: usize) { self.0.truncate(s); } - /// Exactly the same semantics as [`Vec::pop`]. + /// Exactly the same semantics as `Vec::pop`. + /// + /// This is safe since popping can only shrink the inner vector. pub fn pop(&mut self) -> Option { self.0.pop() } @@ -191,54 +205,76 @@ impl> BoundedVec { S::get() as usize } - /// Forces the insertion of `s` into `self` retaining all items with index at least `index`. + /// Returns true of this collection is full. + pub fn is_full(&self) -> bool { + self.len() >= Self::bound() + } + + /// Forces the insertion of `element` into `self` retaining all items with index at least + /// `index`. /// /// If `index == 0` and `self.len() == Self::bound()`, then this is a no-op. /// /// If `Self::bound() < index` or `self.len() < index`, then this is also a no-op. /// - /// Returns `true` if the item was inserted. - pub fn force_insert_keep_right(&mut self, index: usize, element: T) -> bool { + /// Returns `Ok(maybe_removed)` if the item was inserted, where `maybe_removed` is + /// `Some(removed)` if an item was removed to make room for the new one. Returns `Err(())` if + /// `element` cannot be inserted. + pub fn force_insert_keep_right( + &mut self, + index: usize, + mut element: T, + ) -> Result, ()> { // Check against panics. if Self::bound() < index || self.len() < index { - return false - } - if self.len() < Self::bound() { + Err(()) + } else if self.len() < Self::bound() { // Cannot panic since self.len() >= index; self.0.insert(index, element); + Ok(None) } else { if index == 0 { - return false + return Err(()) } - self[0] = element; + sp_std::mem::swap(&mut self[0], &mut element); // `[0..index] cannot panic since self.len() >= index. // `rotate_left(1)` cannot panic because there is at least 1 element. self[0..index].rotate_left(1); + Ok(Some(element)) } - true } - /// Forces the insertion of `s` into `self` retaining all items with index at most `index`. + /// Forces the insertion of `element` into `self` retaining all items with index at most + /// `index`. /// /// If `index == Self::bound()` and `self.len() == Self::bound()`, then this is a no-op. /// /// If `Self::bound() < index` or `self.len() < index`, then this is also a no-op. /// - /// Returns `true` if the item was inserted. - pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> bool { + /// Returns `Ok(maybe_removed)` if the item was inserted, where `maybe_removed` is + /// `Some(removed)` if an item was removed to make room for the new one. Returns `Err(())` if + /// `element` cannot be inserted. + pub fn force_insert_keep_left(&mut self, index: usize, element: T) -> Result, ()> { // Check against panics. if Self::bound() < index || self.len() < index || Self::bound() == 0 { - return false + return Err(()) } // Noop condition. if Self::bound() == index && self.len() <= Self::bound() { - return false + return Err(()) } - // Cannot panic since `Self.bound() > 0` - self.0.truncate(Self::bound() - 1); + let maybe_removed = if self.is_full() { + // defensive-only: since we are at capacity, this is a noop. + self.0.truncate(Self::bound()); + // if we truncate anything, it will be the last one. + self.0.pop() + } else { + None + }; + // Cannot panic since `self.len() >= index`; self.0.insert(index, element); - true + Ok(maybe_removed) } /// Move the position of an item from one location to another in the slice. @@ -311,6 +347,20 @@ impl> BoundedVec { self.0.resize(size, value); } + /// Exactly the same semantics as [`Vec::extend`], but returns an error and does nothing if the + /// length of the outcome is larger than the bound. + pub fn try_extend( + &mut self, + with: impl IntoIterator + ExactSizeIterator, + ) -> Result<(), ()> { + if with.len().saturating_add(self.len()) <= Self::bound() { + self.0.extend(with); + Ok(()) + } else { + Err(()) + } + } + /// Consumes self and mutates self via the given `mutate` function. /// /// If the outcome of mutation is within bounds, `Some(Self)` is returned. Else, `None` is @@ -522,7 +572,7 @@ where #[cfg(test)] pub mod test { use super::*; - use crate::{traits::ConstU32, Twox128}; + use crate::{bounded_vec, traits::ConstU32, Twox128}; use sp_io::TestExternalities; crate::generate_storage_alias! { Prefix, Foo => Value>> } @@ -534,7 +584,7 @@ pub mod test { #[test] fn slide_works() { - let mut b: BoundedVec> = vec![0, 1, 2, 3, 4, 5].try_into().unwrap(); + let mut b: BoundedVec> = bounded_vec![0, 1, 2, 3, 4, 5]; assert!(b.slide(1, 5)); assert_eq!(*b, vec![0, 2, 3, 4, 1, 5]); assert!(b.slide(4, 0)); @@ -551,7 +601,7 @@ pub mod test { assert!(!b.slide(7, 0)); assert_eq!(*b, vec![0, 2, 3, 4, 5, 1]); - let mut c: BoundedVec> = vec![0, 1, 2].try_into().unwrap(); + let mut c: BoundedVec> = bounded_vec![0, 1, 2]; assert!(!c.slide(1, 5)); assert_eq!(*c, vec![0, 1, 2]); assert!(!c.slide(4, 0)); @@ -564,7 +614,7 @@ pub mod test { #[test] fn slide_noops_work() { - let mut b: BoundedVec> = vec![0, 1, 2, 3, 4, 5].try_into().unwrap(); + let mut b: BoundedVec> = bounded_vec![0, 1, 2, 3, 4, 5]; assert!(!b.slide(3, 3)); assert_eq!(*b, vec![0, 1, 2, 3, 4, 5]); assert!(!b.slide(3, 4)); @@ -573,58 +623,59 @@ pub mod test { #[test] fn force_insert_keep_left_works() { - let mut b: BoundedVec> = vec![].try_into().unwrap(); - assert!(!b.force_insert_keep_left(1, 10)); + let mut b: BoundedVec> = bounded_vec![]; + assert_eq!(b.force_insert_keep_left(1, 10), Err(())); assert!(b.is_empty()); - assert!(b.force_insert_keep_left(0, 30)); - assert!(b.force_insert_keep_left(0, 10)); - assert!(b.force_insert_keep_left(1, 20)); - assert!(b.force_insert_keep_left(3, 40)); + assert_eq!(b.force_insert_keep_left(0, 30), Ok(None)); + assert_eq!(b.force_insert_keep_left(0, 10), Ok(None)); + assert_eq!(b.force_insert_keep_left(1, 20), Ok(None)); + assert_eq!(b.force_insert_keep_left(3, 40), Ok(None)); assert_eq!(*b, vec![10, 20, 30, 40]); // at capacity. - assert!(!b.force_insert_keep_left(4, 41)); + assert_eq!(b.force_insert_keep_left(4, 41), Err(())); assert_eq!(*b, vec![10, 20, 30, 40]); - assert!(b.force_insert_keep_left(3, 31)); + assert_eq!(b.force_insert_keep_left(3, 31), Ok(Some(40))); assert_eq!(*b, vec![10, 20, 30, 31]); - assert!(b.force_insert_keep_left(1, 11)); + assert_eq!(b.force_insert_keep_left(1, 11), Ok(Some(31))); assert_eq!(*b, vec![10, 11, 20, 30]); - assert!(b.force_insert_keep_left(0, 1)); + assert_eq!(b.force_insert_keep_left(0, 1), Ok(Some(30))); assert_eq!(*b, vec![1, 10, 11, 20]); - let mut z: BoundedVec> = vec![].try_into().unwrap(); + let mut z: BoundedVec> = bounded_vec![]; assert!(z.is_empty()); - assert!(!z.force_insert_keep_left(0, 10)); + assert_eq!(z.force_insert_keep_left(0, 10), Err(())); assert!(z.is_empty()); } #[test] fn force_insert_keep_right_works() { - let mut b: BoundedVec> = vec![].try_into().unwrap(); - assert!(!b.force_insert_keep_right(1, 10)); + let mut b: BoundedVec> = bounded_vec![]; + assert_eq!(b.force_insert_keep_right(1, 10), Err(())); assert!(b.is_empty()); - assert!(b.force_insert_keep_right(0, 30)); - assert!(b.force_insert_keep_right(0, 10)); - assert!(b.force_insert_keep_right(1, 20)); - assert!(b.force_insert_keep_right(3, 40)); + assert_eq!(b.force_insert_keep_right(0, 30), Ok(None)); + assert_eq!(b.force_insert_keep_right(0, 10), Ok(None)); + assert_eq!(b.force_insert_keep_right(1, 20), Ok(None)); + assert_eq!(b.force_insert_keep_right(3, 40), Ok(None)); assert_eq!(*b, vec![10, 20, 30, 40]); + // at capacity. - assert!(!b.force_insert_keep_right(0, 0)); + assert_eq!(b.force_insert_keep_right(0, 0), Err(())); assert_eq!(*b, vec![10, 20, 30, 40]); - assert!(b.force_insert_keep_right(1, 11)); + assert_eq!(b.force_insert_keep_right(1, 11), Ok(Some(10))); assert_eq!(*b, vec![11, 20, 30, 40]); - assert!(b.force_insert_keep_right(3, 31)); + assert_eq!(b.force_insert_keep_right(3, 31), Ok(Some(11))); assert_eq!(*b, vec![20, 30, 31, 40]); - assert!(b.force_insert_keep_right(4, 41)); + assert_eq!(b.force_insert_keep_right(4, 41), Ok(Some(20))); assert_eq!(*b, vec![30, 31, 40, 41]); - assert!(!b.force_insert_keep_right(5, 69)); + assert_eq!(b.force_insert_keep_right(5, 69), Err(())); assert_eq!(*b, vec![30, 31, 40, 41]); - let mut z: BoundedVec> = vec![].try_into().unwrap(); + let mut z: BoundedVec> = bounded_vec![]; assert!(z.is_empty()); - assert!(!z.force_insert_keep_right(0, 10)); + assert_eq!(z.force_insert_keep_right(0, 10), Err(())); assert!(z.is_empty()); } @@ -636,13 +687,13 @@ pub mod test { #[test] fn decode_len_works() { TestExternalities::default().execute_with(|| { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; Foo::put(bounded); assert_eq!(Foo::decode_len().unwrap(), 3); }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; FooMap::insert(1, bounded); assert_eq!(FooMap::decode_len(1).unwrap(), 3); assert!(FooMap::decode_len(0).is_none()); @@ -650,7 +701,7 @@ pub mod test { }); TestExternalities::default().execute_with(|| { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; FooDoubleMap::insert(1, 1, bounded); assert_eq!(FooDoubleMap::decode_len(1, 1).unwrap(), 3); assert!(FooDoubleMap::decode_len(2, 1).is_none()); @@ -661,7 +712,7 @@ pub mod test { #[test] fn try_insert_works() { - let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = bounded_vec![1, 2, 3]; bounded.try_insert(1, 0).unwrap(); assert_eq!(*bounded, vec![1, 0, 2, 3]); @@ -685,13 +736,13 @@ pub mod test { #[test] #[should_panic(expected = "insertion index (is 9) should be <= len (is 3)")] fn try_inert_panics_if_oob() { - let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = bounded_vec![1, 2, 3]; bounded.try_insert(9, 0).unwrap(); } #[test] fn try_push_works() { - let mut bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let mut bounded: BoundedVec> = bounded_vec![1, 2, 3]; bounded.try_push(0).unwrap(); assert_eq!(*bounded, vec![1, 2, 3, 0]); @@ -700,7 +751,7 @@ pub mod test { #[test] fn deref_coercion_works() { - let bounded: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3]; // these methods come from deref-ed vec. assert_eq!(bounded.len(), 3); assert!(bounded.iter().next().is_some()); @@ -709,7 +760,7 @@ pub mod test { #[test] fn try_mutate_works() { - let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3, 4, 5, 6]; let bounded = bounded.try_mutate(|v| v.push(7)).unwrap(); assert_eq!(bounded.len(), 7); assert!(bounded.try_mutate(|v| v.push(8)).is_none()); @@ -717,13 +768,13 @@ pub mod test { #[test] fn slice_indexing_works() { - let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3, 4, 5, 6]; assert_eq!(&bounded[0..=2], &[1, 2, 3]); } #[test] fn vec_eq_works() { - let bounded: BoundedVec> = vec![1, 2, 3, 4, 5, 6].try_into().unwrap(); + let bounded: BoundedVec> = bounded_vec![1, 2, 3, 4, 5, 6]; assert_eq!(bounded, vec![1, 2, 3, 4, 5, 6]); } @@ -738,7 +789,7 @@ pub mod test { #[test] fn can_be_collected() { - let b1: BoundedVec> = vec![1, 2, 3, 4].try_into().unwrap(); + let b1: BoundedVec> = bounded_vec![1, 2, 3, 4]; let b2: BoundedVec> = b1.iter().map(|x| x + 1).try_collect().unwrap(); assert_eq!(b2, vec![2, 3, 4, 5]); @@ -777,8 +828,8 @@ pub mod test { #[test] fn eq_works() { // of same type - let b1: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); - let b2: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); + let b1: BoundedVec> = bounded_vec![1, 2, 3]; + let b2: BoundedVec> = bounded_vec![1, 2, 3]; assert_eq!(b1, b2); // of different type, but same value and bound. @@ -786,19 +837,41 @@ pub mod test { B1: u32 = 7; B2: u32 = 7; } - let b1: BoundedVec = vec![1, 2, 3].try_into().unwrap(); - let b2: BoundedVec = vec![1, 2, 3].try_into().unwrap(); + let b1: BoundedVec = bounded_vec![1, 2, 3]; + let b2: BoundedVec = bounded_vec![1, 2, 3]; assert_eq!(b1, b2); } #[test] fn ord_works() { use std::cmp::Ordering; - let b1: BoundedVec> = vec![1, 2, 3].try_into().unwrap(); - let b2: BoundedVec> = vec![1, 3, 2].try_into().unwrap(); + let b1: BoundedVec> = bounded_vec![1, 2, 3]; + let b2: BoundedVec> = bounded_vec![1, 3, 2]; // ordering for vec is lexicographic. assert_eq!(b1.cmp(&b2), Ordering::Less); assert_eq!(b1.cmp(&b2), b1.into_inner().cmp(&b2.into_inner())); } + + #[test] + fn try_extend_works() { + let mut b: BoundedVec> = bounded_vec![1, 2, 3]; + + assert!(b.try_extend(vec![4].into_iter()).is_ok()); + assert_eq!(*b, vec![1, 2, 3, 4]); + + assert!(b.try_extend(vec![5].into_iter()).is_ok()); + assert_eq!(*b, vec![1, 2, 3, 4, 5]); + + assert!(b.try_extend(vec![6].into_iter()).is_err()); + assert_eq!(*b, vec![1, 2, 3, 4, 5]); + + let mut b: BoundedVec> = bounded_vec![1, 2, 3]; + assert!(b.try_extend(vec![4, 5].into_iter()).is_ok()); + assert_eq!(*b, vec![1, 2, 3, 4, 5]); + + let mut b: BoundedVec> = bounded_vec![1, 2, 3]; + assert!(b.try_extend(vec![4, 5, 6].into_iter()).is_err()); + assert_eq!(*b, vec![1, 2, 3]); + } } diff --git a/substrate/frame/support/src/traits.rs b/substrate/frame/support/src/traits.rs index 5ee2952e44..88891c8327 100644 --- a/substrate/frame/support/src/traits.rs +++ b/substrate/frame/support/src/traits.rs @@ -58,6 +58,8 @@ pub use misc::{ PreimageRecipient, PrivilegeCmp, SameOrOther, Time, TryCollect, TryDrop, UnixTime, WrapperKeepOpaque, WrapperOpaque, }; +#[doc(hidden)] +pub use misc::{DEFENSIVE_OP_INTERNAL_ERROR, DEFENSIVE_OP_PUBLIC_ERROR}; mod stored_map; pub use stored_map::{StorageMapShim, StoredMap}; diff --git a/substrate/frame/support/src/traits/misc.rs b/substrate/frame/support/src/traits/misc.rs index eaada3ea2c..d2fd438d3a 100644 --- a/substrate/frame/support/src/traits/misc.rs +++ b/substrate/frame/support/src/traits/misc.rs @@ -24,8 +24,34 @@ use sp_arithmetic::traits::{CheckedAdd, CheckedMul, CheckedSub, Saturating}; use sp_runtime::{traits::Block as BlockT, DispatchError}; use sp_std::{cmp::Ordering, prelude::*}; -const DEFENSIVE_OP_PUBLIC_ERROR: &'static str = "a defensive failure has been triggered; please report the block number at https://github.com/paritytech/substrate/issues"; -const DEFENSIVE_OP_INTERNAL_ERROR: &'static str = "Defensive failure has been triggered!"; +#[doc(hidden)] +pub const DEFENSIVE_OP_PUBLIC_ERROR: &'static str = "a defensive failure has been triggered; please report the block number at https://github.com/paritytech/substrate/issues"; +#[doc(hidden)] +pub const DEFENSIVE_OP_INTERNAL_ERROR: &'static str = "Defensive failure has been triggered!"; + +/// Generic function to mark an execution path as ONLY defensive. +/// +/// Similar to mark a match arm or `if/else` branch as `unreachable!`. +#[macro_export] +macro_rules! defensive { + () => { + frame_support::log::error!( + target: "runtime", + "{}", + $crate::traits::misc::DEFENSIVE_OP_PUBLIC_ERROR + ); + debug_assert!(false, "{}", $crate::traits::misc::DEFENSIVE_OP_INTERNAL_ERROR); + }; + ($error:tt) => { + frame_support::log::error!( + target: "runtime", + "{}: {:?}", + $crate::traits::misc::DEFENSIVE_OP_PUBLIC_ERROR, + $error + ); + debug_assert!(false, "{}: {:?}", $crate::traits::misc::DEFENSIVE_OP_INTERNAL_ERROR, $error); + } +} /// Prelude module for all defensive traits to be imported at once. pub mod defensive_prelude { @@ -116,12 +142,7 @@ impl Defensive for Option { match self { Some(inner) => inner, None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); or }, } @@ -131,12 +152,7 @@ impl Defensive for Option { match self { Some(inner) => inner, None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); f() }, } @@ -149,12 +165,7 @@ impl Defensive for Option { match self { Some(inner) => inner, None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); Default::default() }, } @@ -164,12 +175,7 @@ impl Defensive for Option { match self { Some(inner) => Some(inner), None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR - ); + defensive!(); None }, } @@ -181,13 +187,7 @@ impl Defensive for Result { match self { Ok(inner) => inner, Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); or }, } @@ -197,13 +197,7 @@ impl Defensive for Result { match self { Ok(inner) => inner, Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); f() }, } @@ -216,13 +210,7 @@ impl Defensive for Result { match self { Ok(inner) => inner, Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); Default::default() }, } @@ -232,13 +220,7 @@ impl Defensive for Result { match self { Ok(inner) => Ok(inner), Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); Err(e) }, } @@ -248,13 +230,7 @@ impl Defensive for Result { impl DefensiveResult for Result { fn defensive_map_err F>(self, o: O) -> Result { self.map_err(|e| { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); o(e) }) } @@ -262,13 +238,7 @@ impl DefensiveResult for Result { fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { self.map_or_else( |e| { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); default(e) }, f, @@ -279,13 +249,7 @@ impl DefensiveResult for Result { match self { Ok(inner) => Some(inner), Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); None }, } @@ -295,13 +259,7 @@ impl DefensiveResult for Result { match self { Ok(inner) => Ok(f(inner)), Err(e) => { - debug_assert!(false, "{}: {:?}", DEFENSIVE_OP_INTERNAL_ERROR, e); - frame_support::log::error!( - target: "runtime", - "{}: {:?}", - DEFENSIVE_OP_PUBLIC_ERROR, - e - ); + defensive!(e); Err(e) }, } @@ -312,12 +270,7 @@ impl DefensiveOption for Option { fn defensive_map_or_else U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { self.map_or_else( || { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR, - ); + defensive!(); default() }, f, @@ -326,12 +279,7 @@ impl DefensiveOption for Option { fn defensive_ok_or_else E>(self, err: F) -> Result { self.ok_or_else(|| { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR, - ); + defensive!(); err() }) } @@ -340,12 +288,7 @@ impl DefensiveOption for Option { match self { Some(inner) => Some(f(inner)), None => { - debug_assert!(false, "{}", DEFENSIVE_OP_INTERNAL_ERROR); - frame_support::log::error!( - target: "runtime", - "{}", - DEFENSIVE_OP_PUBLIC_ERROR, - ); + defensive!(); None }, }