diff --git a/src/backend/bucket/mod.rs b/src/backend/bucket/mod.rs index 5e5ad48..57bde81 100644 --- a/src/backend/bucket/mod.rs +++ b/src/backend/bucket/mod.rs @@ -4,7 +4,7 @@ mod fixed_str; mod interned_str; use self::{fixed_str::FixedString, interned_str::InternedStr}; -use super::Backend; +use super::{Backend, PhantomBackend}; use crate::{symbol::expect_valid_symbol, DefaultSymbol, Symbol}; use alloc::{string::String, vec::Vec}; use core::{iter::Enumerate, marker::PhantomData, slice}; @@ -43,11 +43,11 @@ use core::{iter::Enumerate, marker::PhantomData, slice}; /// | Contiguous | **yes** | /// | Iteration | **best** | #[derive(Debug)] -pub struct BucketBackend { +pub struct BucketBackend<'i, S: Symbol = DefaultSymbol> { spans: Vec, head: FixedString, full: Vec, - marker: PhantomData S>, + marker: PhantomBackend<'i, Self>, } /// # Safety @@ -55,16 +55,16 @@ pub struct BucketBackend { /// The bucket backend requires a manual [`Send`] impl because it is self /// referential. When cloning a bucket backend a deep clone is performed and /// all references to itself are updated for the clone. -unsafe impl Send for BucketBackend where S: Symbol {} +unsafe impl<'i, S> Send for BucketBackend<'i, S> where S: Symbol {} /// # Safety /// /// The bucket backend requires a manual [`Send`] impl because it is self /// referential. Those references won't escape its own scope and also /// the bucket backend has no interior mutability. -unsafe impl Sync for BucketBackend where S: Symbol {} +unsafe impl<'i, S> Sync for BucketBackend<'i, S> where S: Symbol {} -impl Default for BucketBackend { +impl<'i, S: Symbol> Default for BucketBackend<'i, S> { #[cfg_attr(feature = "inline-more", inline)] fn default() -> Self { Self { @@ -76,10 +76,14 @@ impl Default for BucketBackend { } } -impl Backend for BucketBackend +impl<'i, S> Backend<'i> for BucketBackend<'i, S> where S: Symbol, { + type Access<'local> = &'local str + where + Self: 'local, + 'i: 'local; type Symbol = S; type Iter<'a> = Iter<'a, S> @@ -136,7 +140,7 @@ where } } -impl BucketBackend +impl<'i, S> BucketBackend<'i, S> where S: Symbol, { @@ -167,7 +171,7 @@ where } } -impl Clone for BucketBackend { +impl<'i, S: Symbol> Clone for BucketBackend<'i, S> { fn clone(&self) -> Self { // For performance reasons we copy all cloned strings into a single cloned // head string leaving the cloned `full` empty. @@ -191,9 +195,9 @@ impl Clone for BucketBackend { } } -impl Eq for BucketBackend where S: Symbol {} +impl<'i, S> Eq for BucketBackend<'i, S> where S: Symbol {} -impl PartialEq for BucketBackend +impl<'i, S> PartialEq for BucketBackend<'i, S> where S: Symbol, { @@ -203,12 +207,12 @@ where } } -impl<'a, S> IntoIterator for &'a BucketBackend +impl<'i, 'l, S> IntoIterator for &'l BucketBackend<'i, S> where S: Symbol, { - type Item = (S, &'a str); - type IntoIter = Iter<'a, S>; + type Item = (S, &'l str); + type IntoIter = Iter<'l, S>; #[cfg_attr(feature = "inline-more", inline)] fn into_iter(self) -> Self::IntoIter { @@ -216,14 +220,14 @@ where } } -pub struct Iter<'a, S> { - iter: Enumerate>, +pub struct Iter<'l, S> { + iter: Enumerate>, symbol_marker: PhantomData S>, } -impl<'a, S> Iter<'a, S> { +impl<'i, 'l, S: Symbol> Iter<'l, S> { #[cfg_attr(feature = "inline-more", inline)] - pub fn new(backend: &'a BucketBackend) -> Self { + pub fn new(backend: &'l BucketBackend<'i, S>) -> Self { Self { iter: backend.spans.iter().enumerate(), symbol_marker: Default::default(), @@ -231,11 +235,11 @@ impl<'a, S> Iter<'a, S> { } } -impl<'a, S> Iterator for Iter<'a, S> +impl<'l, S> Iterator for Iter<'l, S> where S: Symbol, { - type Item = (S, &'a str); + type Item = (S, &'l str); #[inline] fn size_hint(&self) -> (usize, Option) { diff --git a/src/backend/buffer.rs b/src/backend/buffer.rs index c3b7c0b..40912e9 100644 --- a/src/backend/buffer.rs +++ b/src/backend/buffer.rs @@ -1,9 +1,9 @@ #![cfg(feature = "backends")] -use super::Backend; +use super::{Backend, PhantomBackend}; use crate::{symbol::expect_valid_symbol, DefaultSymbol, Symbol}; use alloc::vec::Vec; -use core::{marker::PhantomData, mem, str}; +use core::{mem, str}; /// An interner backend that appends all interned string information in a single buffer. /// @@ -34,13 +34,13 @@ use core::{marker::PhantomData, mem, str}; /// | Contiguous | **no** | /// | Iteration | **bad** | #[derive(Debug)] -pub struct BufferBackend { +pub struct BufferBackend<'i, S: Symbol = DefaultSymbol> { len_strings: usize, buffer: Vec, - marker: PhantomData S>, + marker: PhantomBackend<'i, Self>, } -impl PartialEq for BufferBackend +impl<'i, S> PartialEq for BufferBackend<'i, S> where S: Symbol, { @@ -49,9 +49,9 @@ where } } -impl Eq for BufferBackend where S: Symbol {} +impl<'i, S> Eq for BufferBackend<'i, S> where S: Symbol {} -impl Clone for BufferBackend { +impl<'i, S: Symbol> Clone for BufferBackend<'i, S> { fn clone(&self) -> Self { Self { len_strings: self.len_strings, @@ -61,7 +61,7 @@ impl Clone for BufferBackend { } } -impl Default for BufferBackend { +impl<'i, S: Symbol> Default for BufferBackend<'i, S> { #[cfg_attr(feature = "inline-more", inline)] fn default() -> Self { Self { @@ -72,7 +72,7 @@ impl Default for BufferBackend { } } -impl BufferBackend +impl<'i, S> BufferBackend<'i, S> where S: Symbol, { @@ -147,15 +147,19 @@ where } } -impl Backend for BufferBackend +impl<'i, S> Backend<'i> for BufferBackend<'i, S> where S: Symbol, { + type Access<'l> = &'l str + where + Self: 'l; type Symbol = S; - type Iter<'a> - = Iter<'a, S> + type Iter<'l> + = Iter<'i, 'l, S> where - Self: 'a; + 'i: 'l, + Self: 'l; #[cfg_attr(feature = "inline-more", inline)] fn with_capacity(capacity: usize) -> Self { @@ -307,12 +311,12 @@ fn decode_var_usize_cold(buffer: &[u8]) -> Option<(usize, usize)> { Some((result, i + 1)) } -impl<'a, S> IntoIterator for &'a BufferBackend +impl<'i, 'l, S> IntoIterator for &'l BufferBackend<'i, S> where S: Symbol, { - type Item = (S, &'a str); - type IntoIter = Iter<'a, S>; + type Item = (S, &'l str); + type IntoIter = Iter<'i, 'l, S>; #[cfg_attr(feature = "inline-more", inline)] fn into_iter(self) -> Self::IntoIter { @@ -320,15 +324,15 @@ where } } -pub struct Iter<'a, S> { - backend: &'a BufferBackend, +pub struct Iter<'i, 'l, S: Symbol> { + backend: &'l BufferBackend<'i, S>, remaining: usize, next: usize, } -impl<'a, S> Iter<'a, S> { +impl<'i, 'l, S: Symbol> Iter<'i, 'l, S> { #[cfg_attr(feature = "inline-more", inline)] - pub fn new(backend: &'a BufferBackend) -> Self { + pub fn new(backend: &'l BufferBackend<'i, S>) -> Self { Self { backend, remaining: backend.len_strings, @@ -337,11 +341,11 @@ impl<'a, S> Iter<'a, S> { } } -impl<'a, S> Iterator for Iter<'a, S> +impl<'i, 'l, S> Iterator for Iter<'i, 'l, S> where S: Symbol, { - type Item = (S, &'a str); + type Item = (S, &'l str); #[inline] fn size_hint(&self) -> (usize, Option) { @@ -365,7 +369,7 @@ where } } -impl ExactSizeIterator for Iter<'_, S> +impl<'i, S> ExactSizeIterator for Iter<'i, '_, S> where S: Symbol, { diff --git a/src/backend/mod.rs b/src/backend/mod.rs index 1609291..374c0c0 100644 --- a/src/backend/mod.rs +++ b/src/backend/mod.rs @@ -14,21 +14,43 @@ use crate::Symbol; /// The default backend recommended for general use. #[cfg(feature = "backends")] -pub type DefaultBackend = StringBackend; +pub type DefaultBackend<'i> = StringBackend<'i, crate::DefaultSymbol>; + +/// [`PhantomData`][std::marker::PhantomData] wrapper that describes how a [`Backend`] +/// implementor uses lifetime `'i` and [`B::Symbol`][Backend::Symbol]. +#[allow(type_alias_bounds)] // included for clarity +type PhantomBackend<'i, B: Backend<'i>> = std::marker::PhantomData< + // 'i is invariant, Symbol is covariant + Send + Sync + (core::cell::Cell<&'i ()>, fn() -> >::Symbol) +>; /// Types implementing this trait may act as backends for the string interner. /// /// The job of a backend is to actually store, manage and organize the interned /// strings. Different backends have different trade-offs. Users should pick /// their backend with hinsight of their personal use-case. -pub trait Backend: Default { +pub trait Backend<'i>: Default { /// The symbol used by the string interner backend. type Symbol: Symbol; + /// Describes the lifetime of returned string. + /// + /// If interned strings can move between insertion this type will be + /// `&'local str` - indicating that resolved `str` is only valid while + /// container isn't mutably accessed. + /// + /// If interned strings can't move then this type is `&'container str`, + /// indicating that resolved `str` are valid for as long as interner exists. + type Access<'l>: AsRef + where + Self: 'l, + 'i: 'l; + /// The iterator over the symbols and their strings. - type Iter<'a>: Iterator + type Iter<'l>: Iterator)> where - Self: 'a; + 'i: 'l, + Self: 'l; /// Creates a new backend for the given capacity. /// @@ -61,7 +83,7 @@ pub trait Backend: Default { fn shrink_to_fit(&mut self); /// Resolves the given symbol to its original string contents. - fn resolve(&self, symbol: Self::Symbol) -> Option<&str>; + fn resolve(&self, symbol: Self::Symbol) -> Option>; /// Resolves the given symbol to its original string contents. /// @@ -72,7 +94,7 @@ pub trait Backend: Default { /// by the [`intern`](`Backend::intern`) or /// [`intern_static`](`Backend::intern_static`) methods of the same /// interner backend. - unsafe fn resolve_unchecked(&self, symbol: Self::Symbol) -> &str; + unsafe fn resolve_unchecked(&self, symbol: Self::Symbol) -> Self::Access<'_>; /// Creates an iterator that yields all interned strings and their symbols. fn iter(&self) -> Self::Iter<'_>; diff --git a/src/backend/string.rs b/src/backend/string.rs index 307dd60..8ed5c86 100644 --- a/src/backend/string.rs +++ b/src/backend/string.rs @@ -1,9 +1,9 @@ #![cfg(feature = "backends")] -use super::Backend; +use super::{Backend, PhantomBackend}; use crate::{symbol::expect_valid_symbol, DefaultSymbol, Symbol}; use alloc::{string::String, vec::Vec}; -use core::{iter::Enumerate, marker::PhantomData, slice}; +use core::{iter::Enumerate, slice}; /// An interner backend that accumulates all interned string contents into one string. /// @@ -38,10 +38,10 @@ use core::{iter::Enumerate, marker::PhantomData, slice}; /// | Contiguous | **yes** | /// | Iteration | **good** | #[derive(Debug)] -pub struct StringBackend { +pub struct StringBackend<'i, S: Symbol = DefaultSymbol> { ends: Vec, buffer: String, - marker: PhantomData S>, + marker: PhantomBackend<'i, Self>, } /// Represents a `[from, to)` index into the `StringBackend` buffer. @@ -51,7 +51,7 @@ pub struct Span { to: usize, } -impl PartialEq for StringBackend +impl<'i, S> PartialEq for StringBackend<'i, S> where S: Symbol, { @@ -68,9 +68,9 @@ where } } -impl Eq for StringBackend where S: Symbol {} +impl<'i, S> Eq for StringBackend<'i, S> where S: Symbol {} -impl Clone for StringBackend { +impl<'i, S: Symbol> Clone for StringBackend<'i, S> { fn clone(&self) -> Self { Self { ends: self.ends.clone(), @@ -80,7 +80,7 @@ impl Clone for StringBackend { } } -impl Default for StringBackend { +impl<'i, S: Symbol> Default for StringBackend<'i, S> { #[cfg_attr(feature = "inline-more", inline)] fn default() -> Self { Self { @@ -91,7 +91,7 @@ impl Default for StringBackend { } } -impl StringBackend +impl<'i, S> StringBackend<'i, S> where S: Symbol, { @@ -144,15 +144,17 @@ where } } -impl Backend for StringBackend +impl<'i, S> Backend<'i> for StringBackend<'i, S> where S: Symbol, { + type Access<'l> = &'l str where Self: 'l; + type Symbol = S; - type Iter<'a> - = Iter<'a, S> + type Iter<'l> + = Iter<'i, 'l, S> where - Self: 'a; + Self: 'l; #[cfg_attr(feature = "inline-more", inline)] fn with_capacity(cap: usize) -> Self { @@ -194,12 +196,12 @@ where } } -impl<'a, S> IntoIterator for &'a StringBackend +impl<'i, 'l, S> IntoIterator for &'l StringBackend<'i, S> where - S: Symbol, + S: Symbol + 'l, { - type Item = (S, &'a str); - type IntoIter = Iter<'a, S>; + type Item = (S, &'l str); + type IntoIter = Iter<'i, 'l, S>; #[cfg_attr(feature = "inline-more", inline)] fn into_iter(self) -> Self::IntoIter { @@ -207,15 +209,15 @@ where } } -pub struct Iter<'a, S> { - backend: &'a StringBackend, +pub struct Iter<'i, 'l, S: Symbol> { + backend: &'l StringBackend<'i, S>, start: usize, - ends: Enumerate>, + ends: Enumerate>, } -impl<'a, S> Iter<'a, S> { +impl<'i, 'l, S: Symbol> Iter<'i, 'l, S> { #[cfg_attr(feature = "inline-more", inline)] - pub fn new(backend: &'a StringBackend) -> Self { + pub fn new(backend: &'l StringBackend<'i, S>) -> Self { Self { backend, start: 0, @@ -224,11 +226,11 @@ impl<'a, S> Iter<'a, S> { } } -impl<'a, S> Iterator for Iter<'a, S> +impl<'i, 'l, S> Iterator for Iter<'i, 'l, S> where S: Symbol, { - type Item = (S, &'a str); + type Item = (S, &'l str); #[inline] fn size_hint(&self) -> (usize, Option) { diff --git a/src/interner.rs b/src/interner.rs index 3841a47..a95cede 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -28,19 +28,19 @@ where /// - This maps from `string` type to `symbol` type. /// - [`StringInterner::resolve`]: To resolve your already interned strings. /// - This maps from `symbol` type to `string` type. -pub struct StringInterner +pub struct StringInterner<'i, B, H = DefaultHashBuilder> where - B: Backend, + B: Backend<'i>, { - dedup: HashMap<::Symbol, (), ()>, + dedup: HashMap<>::Symbol, (), ()>, hasher: H, backend: B, } -impl Debug for StringInterner +impl<'i, B, H> Debug for StringInterner<'i, B, H> where - B: Backend + Debug, - ::Symbol: Symbol + Debug, + B: Backend<'i> + Debug, + >::Symbol: Symbol + Debug, H: BuildHasher, { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -52,17 +52,17 @@ where } #[cfg(feature = "backends")] -impl Default for StringInterner { +impl<'i> Default for StringInterner<'i, crate::DefaultBackend<'i>> { #[cfg_attr(feature = "inline-more", inline)] fn default() -> Self { StringInterner::new() } } -impl Clone for StringInterner +impl<'i, B, H> Clone for StringInterner<'i, B, H> where - B: Backend + Clone, - ::Symbol: Symbol, + B: Backend<'i> + Clone, + >::Symbol: Symbol, H: BuildHasher + Clone, { fn clone(&self) -> Self { @@ -74,10 +74,10 @@ where } } -impl PartialEq for StringInterner +impl<'i, B, H> PartialEq for StringInterner<'i, B, H> where - B: Backend + PartialEq, - ::Symbol: Symbol, + B: Backend<'i> + PartialEq, + >::Symbol: Symbol, H: BuildHasher, { fn eq(&self, rhs: &Self) -> bool { @@ -85,18 +85,18 @@ where } } -impl Eq for StringInterner +impl<'i, B, H> Eq for StringInterner<'i, B, H> where - B: Backend + Eq, - ::Symbol: Symbol, + B: Backend<'i> + Eq, + >::Symbol: Symbol, H: BuildHasher, { } -impl StringInterner +impl<'i, B, H> StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher + Default, { /// Creates a new empty `StringInterner`. @@ -120,10 +120,10 @@ where } } -impl StringInterner +impl<'i, B, H> StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher, { /// Creates a new empty `StringInterner` with the given hasher. @@ -162,7 +162,7 @@ where /// /// Can be used to query if a string has already been interned without interning. #[inline] - pub fn get(&self, string: T) -> Option<::Symbol> + pub fn get(&self, string: T) -> Option<>::Symbol> where T: AsRef, { @@ -178,7 +178,7 @@ where .from_hash(hash, |symbol| { // SAFETY: This is safe because we only operate on symbols that // we receive from our backend making them valid. - string == unsafe { backend.resolve_unchecked(*symbol) } + string == unsafe { backend.resolve_unchecked(*symbol) }.as_ref() }) .map(|(&symbol, &())| symbol) } @@ -193,8 +193,8 @@ where fn get_or_intern_using( &mut self, string: T, - intern_fn: fn(&mut B, T) -> ::Symbol, - ) -> ::Symbol + intern_fn: fn(&mut B, T) -> >::Symbol, + ) -> >::Symbol where T: Copy + Hash + AsRef + for<'a> PartialEq<&'a str>, { @@ -207,7 +207,7 @@ where let entry = dedup.raw_entry_mut().from_hash(hash, |symbol| { // SAFETY: This is safe because we only operate on symbols that // we receive from our backend making them valid. - string == unsafe { backend.resolve_unchecked(*symbol) } + string == unsafe { backend.resolve_unchecked(*symbol) }.as_ref() }); use hashbrown::hash_map::RawEntryMut; let (&mut symbol, &mut ()) = match entry { @@ -218,7 +218,7 @@ where // SAFETY: This is safe because we only operate on symbols that // we receive from our backend making them valid. let string = unsafe { backend.resolve_unchecked(*symbol) }; - make_hash(hasher, string) + make_hash(hasher, string.as_ref()) }) } }; @@ -234,7 +234,7 @@ where /// If the interner already interns the maximum number of strings possible /// by the chosen symbol type. #[inline] - pub fn get_or_intern(&mut self, string: T) -> ::Symbol + pub fn get_or_intern(&mut self, string: T) -> >::Symbol where T: AsRef, { @@ -255,7 +255,7 @@ where /// If the interner already interns the maximum number of strings possible /// by the chosen symbol type. #[inline] - pub fn get_or_intern_static(&mut self, string: &'static str) -> ::Symbol { + pub fn get_or_intern_static(&mut self, string: &'static str) -> >::Symbol { self.get_or_intern_using(string, B::intern_static) } @@ -266,7 +266,7 @@ where /// Returns the string for the given `symbol`` if any. #[inline] - pub fn resolve(&self, symbol: ::Symbol) -> Option<&str> { + pub fn resolve(&self, symbol: >::Symbol) -> Option<>::Access<'_>> { self.backend.resolve(symbol) } @@ -277,21 +277,21 @@ where /// It is the caller's responsibility to provide this method with `symbol`s /// that are valid for the [`StringInterner`]. #[inline] - pub unsafe fn resolve_unchecked(&self, symbol: ::Symbol) -> &str { + pub unsafe fn resolve_unchecked(&self, symbol: >::Symbol) -> >::Access<'_> { unsafe { self.backend.resolve_unchecked(symbol) } } /// Returns an iterator that yields all interned strings and their symbols. #[inline] - pub fn iter(&self) -> ::Iter<'_> { + pub fn iter(&self) -> >::Iter<'_> { self.backend.iter() } } -impl FromIterator for StringInterner +impl<'i, B, H, T> FromIterator for StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher + Default, T: AsRef, { @@ -307,10 +307,10 @@ where } } -impl Extend for StringInterner +impl<'i, B, H, T> Extend for StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher, T: AsRef, { @@ -324,15 +324,15 @@ where } } -impl<'a, B, H> IntoIterator for &'a StringInterner +impl<'i, 'l, B, H> IntoIterator for &'l StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, - &'a B: IntoIterator::Symbol, &'a str)>, + B: Backend<'i>, + >::Symbol: Symbol, + &'l B: IntoIterator>::Symbol, &'l str)>, H: BuildHasher, { - type Item = (::Symbol, &'a str); - type IntoIter = <&'a B as IntoIterator>::IntoIter; + type Item = (>::Symbol, &'l str); + type IntoIter = <&'l B as IntoIterator>::IntoIter; #[cfg_attr(feature = "inline-more", inline)] fn into_iter(self) -> Self::IntoIter { diff --git a/src/lib.rs b/src/lib.rs index 8f313a6..df08e79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,8 +132,8 @@ pub mod symbol; /// A convenience [`StringInterner`] type based on the [`DefaultBackend`]. #[cfg(feature = "backends")] -pub type DefaultStringInterner = - self::interner::StringInterner; +pub type DefaultStringInterner<'i, B = DefaultBackend<'i>, H = DefaultHashBuilder> = + self::interner::StringInterner<'i, B, H>; #[cfg(feature = "backends")] #[doc(inline)] diff --git a/src/serde_impl.rs b/src/serde_impl.rs index 0bf79fb..01fcb62 100644 --- a/src/serde_impl.rs +++ b/src/serde_impl.rs @@ -6,11 +6,11 @@ use serde::{ ser::{Serialize, SerializeSeq, Serializer}, }; -impl Serialize for StringInterner +impl<'i, B, H> Serialize for StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, - for<'a> &'a B: IntoIterator::Symbol, &'a str)>, + B: Backend<'i>, + >::Symbol: Symbol, + for<'l> &'l B: IntoIterator>::Symbol, &'l str)>, H: BuildHasher, { fn serialize(&self, serializer: T) -> Result @@ -25,13 +25,13 @@ where } } -impl<'de, B, H> Deserialize<'de> for StringInterner +impl<'i: 'de, 'de, B, H> Deserialize<'de> for StringInterner<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher + Default, { - fn deserialize(deserializer: D) -> Result, D::Error> + fn deserialize(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { @@ -39,19 +39,19 @@ where } } -struct StringInternerVisitor +struct StringInternerVisitor<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher, { - mark: marker::PhantomData<(::Symbol, B, H)>, + mark: marker::PhantomData<(>::Symbol, B, H)>, } -impl Default for StringInternerVisitor +impl<'i, B, H> Default for StringInternerVisitor<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher, { fn default() -> Self { @@ -61,13 +61,13 @@ where } } -impl<'de, B, H> Visitor<'de> for StringInternerVisitor +impl<'i: 'de, 'de, B, H> Visitor<'de> for StringInternerVisitor<'i, B, H> where - B: Backend, - ::Symbol: Symbol, + B: Backend<'i>, + >::Symbol: Symbol, H: BuildHasher + Default, { - type Value = StringInterner; + type Value = StringInterner<'i, B, H>; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { formatter.write_str("Expected a contiguous sequence of strings.")