Unnamed repository; edit this file 'description' to name the repository.
Merge rust-analyzer/text-size#23
23: Add a deref-removing impl for TextSized r=CAD97 a=CAD97
Notably, given `s: &SmolStr`, `TextSize::of(s)` does not work, where `TextUnit::of_str(s)` did, because the concrete type could be deref-coerced to. (It's probably a limitation of the language that deref coersion does not apply here, but it's one we have to live with.)
So we provide a blanket impl for any type that derefs (directly) to `str`.
Alternatively, we can provide a deeper blanket impl that derefs any number of references recursively [[playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=008b5e0c2edd332b34b3efa42ce2a40a)]:
```rust
impl<D> TextSized for &'_ D
where
D: Deref,
for<'a> &'a D::Target: TextSized,
{
#[inline]
fn text_size(self) -> TextSize {
self.deref().text_size()
}
}
```
This is "only" at the cost of a little extra impl complexity.
Co-authored-by: CAD97 <[email protected]>
| -rw-r--r-- | lib/text-size/src/traits.rs | 15 | ||||
| -rw-r--r-- | lib/text-size/tests/constructors.rs | 31 |
2 files changed, 45 insertions, 1 deletions
diff --git a/lib/text-size/src/traits.rs b/lib/text-size/src/traits.rs index 7064dbc658..6f3462bee5 100644 --- a/lib/text-size/src/traits.rs +++ b/lib/text-size/src/traits.rs @@ -1,4 +1,7 @@ -use {crate::TextSize, std::convert::TryInto}; +use { + crate::TextSize, + std::{convert::TryInto, ops::Deref}, +}; /// Text-like structures that have a text size. pub trait TextSized: Copy { @@ -15,6 +18,16 @@ impl TextSized for &'_ str { } } +impl<D> TextSized for &'_ D +where + D: Deref<Target = str>, +{ + #[inline] + fn text_size(self) -> TextSize { + self.deref().text_size() + } +} + impl TextSized for char { #[inline] fn text_size(self) -> TextSize { diff --git a/lib/text-size/tests/constructors.rs b/lib/text-size/tests/constructors.rs new file mode 100644 index 0000000000..eba587b539 --- /dev/null +++ b/lib/text-size/tests/constructors.rs @@ -0,0 +1,31 @@ +use { + std::{borrow::Cow, ops::Deref}, + text_size::*, +}; + +struct StringLike<'a>(&'a str); + +impl Deref for StringLike<'_> { + type Target = str; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[test] +fn main() { + let s = ""; + let _ = TextSize::of(&s); + + let s = String::new(); + let _ = TextSize::of(&s); + + let s = Cow::Borrowed(""); + let _ = TextSize::of(&s); + + let s = Cow::Owned(String::new()); + let _ = TextSize::of(&s); + + let s = StringLike(""); + let _ = TextSize::of(&s); +} |