Skip to content

Commit be566b9

Browse files
committed
Remove allow(clippy::result_unit_err)
Unit error types do not implement core::error::Error which leads to some ergonomic issues.
1 parent 2e71c18 commit be566b9

File tree

4 files changed

+65
-39
lines changed

4 files changed

+65
-39
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
4444

4545
### Changed
4646

47+
- Changed the error type of these methods from `()` to `CapacityError`.
48+
- `String::push_str`
49+
- `String::push`
50+
- `Vec::extend_from_slice`
51+
- `Vec::from_slice`
52+
- `Vec::resize_default`
53+
- `Vec::resize`
4754
- Changed `stable_deref_trait` to a platform-dependent dependency.
4855

4956
### Fixed

src/string/mod.rs

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use core::{
1313

1414
use crate::{
1515
storage::{OwnedStorage, Storage, ViewStorage},
16-
vec::VecInner,
16+
vec::{CapacityError, VecInner},
1717
Vec,
1818
};
1919

@@ -28,20 +28,28 @@ pub use drain::Drain;
2828
#[derive(Debug)]
2929
pub enum FromUtf16Error {
3030
/// The capacity of the `String` is too small for the given operation.
31-
Capacity,
31+
Capacity(CapacityError),
3232
/// Error decoding UTF-16.
3333
DecodeUtf16Error(DecodeUtf16Error),
3434
}
3535

3636
impl fmt::Display for FromUtf16Error {
3737
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3838
match self {
39-
Self::Capacity => "insufficient capacity".fmt(f),
39+
Self::Capacity(e) => write!(f, "{}", e),
4040
Self::DecodeUtf16Error(e) => write!(f, "invalid UTF-16: {}", e),
4141
}
4242
}
4343
}
4444

45+
impl core::error::Error for FromUtf16Error {}
46+
47+
impl From<CapacityError> for FromUtf16Error {
48+
fn from(e: CapacityError) -> Self {
49+
FromUtf16Error::Capacity(e)
50+
}
51+
}
52+
4553
/// Base struct for [`String`] and [`StringView`], generic over the [`Storage`].
4654
///
4755
/// In most cases you should use [`String`] or [`StringView`] directly. Only use this
@@ -168,7 +176,7 @@ impl<const N: usize> String<N> {
168176
for c in char::decode_utf16(v.iter().cloned()) {
169177
match c {
170178
Ok(c) => {
171-
s.push(c).map_err(|_| FromUtf16Error::Capacity)?;
179+
s.push(c)?;
172180
}
173181
Err(err) => {
174182
return Err(FromUtf16Error::DecodeUtf16Error(err));
@@ -257,7 +265,7 @@ impl<const N: usize> String<N> {
257265
/// assert!(b.len() == 2);
258266
///
259267
/// assert_eq!(&[b'a', b'b'], &b[..]);
260-
/// # Ok::<(), ()>(())
268+
/// # Ok::<(), heapless::vec::CapacityError>(())
261269
/// ```
262270
#[inline]
263271
pub fn into_bytes(self) -> Vec<u8, N> {
@@ -364,7 +372,7 @@ impl<S: Storage> StringInner<S> {
364372
///
365373
/// let _s = s.as_str();
366374
/// // s.push('c'); // <- cannot borrow `s` as mutable because it is also borrowed as immutable
367-
/// # Ok::<(), ()>(())
375+
/// # Ok::<(), heapless::vec::CapacityError>(())
368376
/// ```
369377
#[inline]
370378
pub fn as_str(&self) -> &str {
@@ -383,7 +391,7 @@ impl<S: Storage> StringInner<S> {
383391
/// let mut s: String<4> = String::try_from("ab")?;
384392
/// let s = s.as_mut_str();
385393
/// s.make_ascii_uppercase();
386-
/// # Ok::<(), ()>(())
394+
/// # Ok::<(), heapless::vec::CapacityError>(())
387395
/// ```
388396
#[inline]
389397
pub fn as_mut_str(&mut self) -> &mut str {
@@ -415,7 +423,7 @@ impl<S: Storage> StringInner<S> {
415423
/// vec.reverse();
416424
/// }
417425
/// assert_eq!(s, "olleh");
418-
/// # Ok::<(), ()>(())
426+
/// # Ok::<(), heapless::vec::CapacityError>(())
419427
/// ```
420428
pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner<u8, S> {
421429
&mut self.vec
@@ -437,11 +445,10 @@ impl<S: Storage> StringInner<S> {
437445
/// assert_eq!("foobar", s);
438446
///
439447
/// assert!(s.push_str("tender").is_err());
440-
/// # Ok::<(), ()>(())
448+
/// # Ok::<(), heapless::vec::CapacityError>(())
441449
/// ```
442450
#[inline]
443-
#[allow(clippy::result_unit_err)]
444-
pub fn push_str(&mut self, string: &str) -> Result<(), ()> {
451+
pub fn push_str(&mut self, string: &str) -> Result<(), CapacityError> {
445452
self.vec.extend_from_slice(string.as_bytes())
446453
}
447454

@@ -480,13 +487,12 @@ impl<S: Storage> StringInner<S> {
480487
/// assert!("abc123" == s.as_str());
481488
///
482489
/// assert_eq!("abc123", s);
483-
/// # Ok::<(), ()>(())
490+
/// # Ok::<(), heapless::vec::CapacityError>(())
484491
/// ```
485492
#[inline]
486-
#[allow(clippy::result_unit_err)]
487-
pub fn push(&mut self, c: char) -> Result<(), ()> {
493+
pub fn push(&mut self, c: char) -> Result<(), CapacityError> {
488494
match c.len_utf8() {
489-
1 => self.vec.push(c as u8).map_err(|_| {}),
495+
1 => self.vec.push(c as u8).map_err(|_| CapacityError {}),
490496
_ => self
491497
.vec
492498
.extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()),
@@ -517,7 +523,7 @@ impl<S: Storage> StringInner<S> {
517523
/// s.truncate(2);
518524
///
519525
/// assert_eq!("he", s);
520-
/// # Ok::<(), ()>(())
526+
/// # Ok::<(), heapless::vec::CapacityError>(())
521527
/// ```
522528
#[inline]
523529
pub fn truncate(&mut self, new_len: usize) {
@@ -545,7 +551,7 @@ impl<S: Storage> StringInner<S> {
545551
/// assert_eq!(s.pop(), Some('f'));
546552
///
547553
/// assert_eq!(s.pop(), None);
548-
/// Ok::<(), ()>(())
554+
/// # Ok::<(), heapless::vec::CapacityError>(())
549555
/// ```
550556
pub fn pop(&mut self) -> Option<char> {
551557
let ch = self.chars().next_back()?;
@@ -577,11 +583,12 @@ impl<S: Storage> StringInner<S> {
577583
/// ```
578584
/// use heapless::String;
579585
///
580-
/// let mut s: String<8> = String::try_from("foo").unwrap();
586+
/// let mut s: String<8> = String::try_from("foo")?;
581587
///
582588
/// assert_eq!(s.remove(0), 'f');
583589
/// assert_eq!(s.remove(1), 'o');
584590
/// assert_eq!(s.remove(0), 'o');
591+
/// # Ok::<(), heapless::vec::CapacityError>(())
585592
/// ```
586593
#[inline]
587594
pub fn remove(&mut self, index: usize) -> char {
@@ -619,7 +626,7 @@ impl<S: Storage> StringInner<S> {
619626
/// assert!(s.is_empty());
620627
/// assert_eq!(0, s.len());
621628
/// assert_eq!(8, s.capacity());
622-
/// Ok::<(), ()>(())
629+
/// # Ok::<(), heapless::vec::CapacityError>(())
623630
/// ```
624631
#[inline]
625632
pub fn clear(&mut self) {
@@ -634,7 +641,7 @@ impl<const N: usize> Default for String<N> {
634641
}
635642

636643
impl<'a, const N: usize> TryFrom<&'a str> for String<N> {
637-
type Error = ();
644+
type Error = CapacityError;
638645
fn try_from(s: &'a str) -> Result<Self, Self::Error> {
639646
let mut new = String::new();
640647
new.push_str(s)?;
@@ -643,7 +650,7 @@ impl<'a, const N: usize> TryFrom<&'a str> for String<N> {
643650
}
644651

645652
impl<const N: usize> str::FromStr for String<N> {
646-
type Err = ();
653+
type Err = CapacityError;
647654

648655
fn from_str(s: &str) -> Result<Self, Self::Err> {
649656
let mut new = String::new();
@@ -912,7 +919,7 @@ impl_try_from_num!(u64, 20);
912919

913920
#[cfg(test)]
914921
mod tests {
915-
use crate::{String, Vec};
922+
use crate::{vec::CapacityError, String, Vec};
916923

917924
#[test]
918925
fn static_new() {
@@ -980,7 +987,7 @@ mod tests {
980987
assert!(s.len() == 3);
981988
assert_eq!(s, "123");
982989

983-
let _: () = String::<2>::try_from("123").unwrap_err();
990+
let _: CapacityError = String::<2>::try_from("123").unwrap_err();
984991
}
985992

986993
#[test]
@@ -991,7 +998,7 @@ mod tests {
991998
assert!(s.len() == 3);
992999
assert_eq!(s, "123");
9931000

994-
let _: () = String::<2>::from_str("123").unwrap_err();
1001+
let _: CapacityError = String::<2>::from_str("123").unwrap_err();
9951002
}
9961003

9971004
#[test]

src/ufmt.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
1-
use crate::{storage::Storage, string::StringInner, vec::VecInner};
1+
use crate::{
2+
storage::Storage,
3+
string::StringInner,
4+
vec::{CapacityError, VecInner},
5+
};
26
use ufmt_write::uWrite;
37

48
impl<S: Storage> uWrite for StringInner<S> {
5-
type Error = ();
9+
type Error = CapacityError;
610
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
711
self.push_str(s)
812
}
913
}
1014

1115
impl<S: Storage> uWrite for VecInner<u8, S> {
12-
type Error = ();
16+
type Error = CapacityError;
1317
fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
1418
self.extend_from_slice(s.as_bytes())
1519
}

src/vec/mod.rs

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@ use crate::storage::{OwnedStorage, Storage, ViewStorage};
1616
mod drain;
1717
pub use drain::Drain;
1818

19+
/// The error type for fallible [`Vec`] and [`String`](crate::String) methods.
20+
#[derive(Debug)]
21+
pub struct CapacityError;
22+
23+
impl fmt::Display for CapacityError {
24+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25+
f.write_str("insufficient capacity")
26+
}
27+
}
28+
29+
impl core::error::Error for CapacityError {}
30+
1931
/// Base struct for [`Vec`] and [`VecView`], generic over the [`Storage`].
2032
///
2133
/// In most cases you should use [`Vec`] or [`VecView`] directly. Only use this
@@ -122,8 +134,7 @@ impl<T, const N: usize> Vec<T, N> {
122134
/// let mut v: Vec<u8, 16> = Vec::new();
123135
/// v.extend_from_slice(&[1, 2, 3]).unwrap();
124136
/// ```
125-
#[allow(clippy::result_unit_err)]
126-
pub fn from_slice(other: &[T]) -> Result<Self, ()>
137+
pub fn from_slice(other: &[T]) -> Result<Self, CapacityError>
127138
where
128139
T: Clone,
129140
{
@@ -453,22 +464,21 @@ impl<T, S: Storage> VecInner<T, S> {
453464
/// vec.extend_from_slice(&[2, 3, 4]).unwrap();
454465
/// assert_eq!(*vec, [1, 2, 3, 4]);
455466
/// ```
456-
#[allow(clippy::result_unit_err)]
457-
pub fn extend_from_slice(&mut self, other: &[T]) -> Result<(), ()>
467+
pub fn extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError>
458468
where
459469
T: Clone,
460470
{
461471
pub fn extend_from_slice_inner<T>(
462472
len: &mut usize,
463473
buf: &mut [MaybeUninit<T>],
464474
other: &[T],
465-
) -> Result<(), ()>
475+
) -> Result<(), CapacityError>
466476
where
467477
T: Clone,
468478
{
469479
if *len + other.len() > buf.len() {
470480
// won't fit in the `Vec`; don't modify anything and return an error
471-
Err(())
481+
Err(CapacityError {})
472482
} else {
473483
for elem in other {
474484
unsafe { *buf.get_unchecked_mut(*len) = MaybeUninit::new(elem.clone()) }
@@ -563,13 +573,12 @@ impl<T, S: Storage> VecInner<T, S> {
563573
/// new_len is less than len, the Vec is simply truncated.
564574
///
565575
/// See also [`resize_default`](Self::resize_default).
566-
#[allow(clippy::result_unit_err)]
567-
pub fn resize(&mut self, new_len: usize, value: T) -> Result<(), ()>
576+
pub fn resize(&mut self, new_len: usize, value: T) -> Result<(), CapacityError>
568577
where
569578
T: Clone,
570579
{
571580
if new_len > self.storage_capacity() {
572-
return Err(());
581+
return Err(CapacityError {});
573582
}
574583

575584
if new_len > self.len {
@@ -590,8 +599,7 @@ impl<T, S: Storage> VecInner<T, S> {
590599
/// If `new_len` is less than `len`, the `Vec` is simply truncated.
591600
///
592601
/// See also [`resize`](Self::resize).
593-
#[allow(clippy::result_unit_err)]
594-
pub fn resize_default(&mut self, new_len: usize) -> Result<(), ()>
602+
pub fn resize_default(&mut self, new_len: usize) -> Result<(), CapacityError>
595603
where
596604
T: Clone + Default,
597605
{
@@ -1148,7 +1156,7 @@ impl<T, S: Storage> Drop for VecInner<T, S> {
11481156
}
11491157

11501158
impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
1151-
type Error = ();
1159+
type Error = CapacityError;
11521160

11531161
fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
11541162
Vec::from_slice(slice)

0 commit comments

Comments
 (0)