From 73da45b65c965777a00ba64aa03a247c0e5241ca Mon Sep 17 00:00:00 2001 From: Benjamin Lee Date: Wed, 26 Jun 2024 09:31:50 -0700 Subject: [PATCH] feat(SourceSpan): add impl From (#385) This can be used to avoid awkward `start..(end + 1)` constructions, which will trigger the `clippy::range_plus_one` lint. I added a single impl for `InclusiveRange` rather than a blanket `impl From for SourceSpan` for two reasons. The first is that the blanket impl would be a breaking change (because dependent crates may currently define a type `T: RangeBounds` and also have `impl From for SourceSpan`). The second is that this would allow one-sided ranges (`..x`, `x..`). In order to support bounded-below ranges, we would need to change `SourceSpan` so that `length` may depend on the the specific `SourceCode` instance. That seems like an unlikely use case. --- src/protocol.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/protocol.rs b/src/protocol.rs index 589cd0b5..d3ee9ca7 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -614,6 +614,28 @@ impl From> for SourceSpan { } } +impl From> for SourceSpan { + /// # Panics + /// + /// Panics if the total length of the inclusive range would overflow a + /// `usize`. This will only occur with the range `0..=usize::MAX`. + fn from(range: std::ops::RangeInclusive) -> Self { + let (start, end) = range.clone().into_inner(); + Self { + offset: start.into(), + length: if range.is_empty() { + 0 + } else { + // will not overflow because `is_empty() == false` guarantees + // that `start <= end` + (end - start) + .checked_add(1) + .expect("length of inclusive range should fit in a usize") + }, + } + } +} + impl From for SourceSpan { fn from(offset: SourceOffset) -> Self { Self { offset, length: 0 }