From f832e5e4c845bb8c540fc6cc665aa46f3af34f4b Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 12 Mar 2024 12:28:34 +0100 Subject: [PATCH] Add NeverMarker (#4674) Fixes #4186 --- provider/baked/calendar/data/macros.rs | 1 + provider/baked/casemap/data/macros.rs | 1 + provider/baked/collator/data/macros.rs | 1 + provider/baked/datetime/data/macros.rs | 1 + provider/baked/decimal/data/macros.rs | 1 + provider/baked/experimental/data/macros.rs | 1 + provider/baked/list/data/macros.rs | 1 + provider/baked/locid_transform/data/macros.rs | 1 + provider/baked/normalizer/data/macros.rs | 1 + provider/baked/plurals/data/macros.rs | 1 + provider/baked/properties/data/macros.rs | 1 + provider/baked/segmenter/data/macros.rs | 1 + provider/baked/timezone/data/macros.rs | 1 + provider/core/src/lib.rs | 1 + provider/core/src/marker.rs | 108 +++++++++++++++++- provider/datagen/src/baked_exporter.rs | 1 + provider/datagen/src/provider.rs | 1 + provider/datagen/tests/data/baked/macros.rs | 1 + 18 files changed, 124 insertions(+), 1 deletion(-) diff --git a/provider/baked/calendar/data/macros.rs b/provider/baked/calendar/data/macros.rs index 9d8a1b1a852..f698f60f3ca 100644 --- a/provider/baked/calendar/data/macros.rs +++ b/provider/baked/calendar/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/casemap/data/macros.rs b/provider/baked/casemap/data/macros.rs index f33dfa6512d..f9d847111e8 100644 --- a/provider/baked/casemap/data/macros.rs +++ b/provider/baked/casemap/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/collator/data/macros.rs b/provider/baked/collator/data/macros.rs index 424789a70ad..616a9eae789 100644 --- a/provider/baked/collator/data/macros.rs +++ b/provider/baked/collator/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/datetime/data/macros.rs b/provider/baked/datetime/data/macros.rs index b0f110d4a87..1faa44a6e91 100644 --- a/provider/baked/datetime/data/macros.rs +++ b/provider/baked/datetime/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/decimal/data/macros.rs b/provider/baked/decimal/data/macros.rs index a3b0bfe65c8..143c3e053ff 100644 --- a/provider/baked/decimal/data/macros.rs +++ b/provider/baked/decimal/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/experimental/data/macros.rs b/provider/baked/experimental/data/macros.rs index 58f8e9f936f..b7eeb470e4b 100644 --- a/provider/baked/experimental/data/macros.rs +++ b/provider/baked/experimental/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/list/data/macros.rs b/provider/baked/list/data/macros.rs index 60be6304a96..44175151a7f 100644 --- a/provider/baked/list/data/macros.rs +++ b/provider/baked/list/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/locid_transform/data/macros.rs b/provider/baked/locid_transform/data/macros.rs index f46dcf2cd90..9cd9206de23 100644 --- a/provider/baked/locid_transform/data/macros.rs +++ b/provider/baked/locid_transform/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/normalizer/data/macros.rs b/provider/baked/normalizer/data/macros.rs index 1ce657966be..46fbda83c15 100644 --- a/provider/baked/normalizer/data/macros.rs +++ b/provider/baked/normalizer/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/plurals/data/macros.rs b/provider/baked/plurals/data/macros.rs index b811c1dff6f..3e6f3709764 100644 --- a/provider/baked/plurals/data/macros.rs +++ b/provider/baked/plurals/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/properties/data/macros.rs b/provider/baked/properties/data/macros.rs index 2873c4a8bcf..a070f25d125 100644 --- a/provider/baked/properties/data/macros.rs +++ b/provider/baked/properties/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/segmenter/data/macros.rs b/provider/baked/segmenter/data/macros.rs index 91acb08c2a4..53c61688798 100644 --- a/provider/baked/segmenter/data/macros.rs +++ b/provider/baked/segmenter/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/baked/timezone/data/macros.rs b/provider/baked/timezone/data/macros.rs index 3435c10e97e..b086025a2af 100644 --- a/provider/baked/timezone/data/macros.rs +++ b/provider/baked/timezone/data/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/core/src/lib.rs b/provider/core/src/lib.rs index a82fe1a68fe..493ea7130c4 100644 --- a/provider/core/src/lib.rs +++ b/provider/core/src/lib.rs @@ -186,6 +186,7 @@ pub use crate::buf::BufferMarker; pub use crate::buf::BufferProvider; pub use crate::marker::DataMarker; pub use crate::marker::KeyedDataMarker; +pub use crate::marker::NeverMarker; #[cfg(feature = "serde")] pub use crate::serde::AsDeserializingBufferProvider; diff --git a/provider/core/src/marker.rs b/provider/core/src/marker.rs index 1096cf83309..83aa2c524ec 100644 --- a/provider/core/src/marker.rs +++ b/provider/core/src/marker.rs @@ -4,7 +4,9 @@ //! Marker types and traits for DataProvider. -use crate::key::DataKey; +use core::marker::PhantomData; + +use crate::{data_key, key::DataKey}; use yoke::Yokeable; /// Trait marker for data structs. All types delivered by the data provider must be associated with @@ -83,3 +85,107 @@ pub trait KeyedDataMarker: DataMarker { /// The single [`DataKey`] associated with this marker. const KEY: DataKey; } + +/// A [`DataMarker`] that never returns data. +/// +/// All types that have non-blanket impls of `DataProvider` are expected to explicitly +/// implement `DataProvider>`, returning [`DataErrorKind::MissingDataKey`]. +/// See [`impl_data_provider_never_marker!`]. +/// +/// [`DataErrorKind::MissingDataKey`]: crate::DataErrorKind::MissingDataKey +/// [`impl_data_provider_never_marker!`]: crate::impl_data_provider_never_marker +/// +/// # Examples +/// +/// ``` +/// use icu_locid::locale; +/// use icu_provider::hello_world::*; +/// use icu_provider::prelude::*; +/// use icu_provider::NeverMarker; +/// +/// let buffer_provider = HelloWorldProvider.into_json_provider(); +/// +/// let result = DataProvider::>>::load( +/// &buffer_provider.as_deserializing(), +/// DataRequest { +/// locale: &locale!("en").into(), +/// metadata: Default::default(), +/// }, +/// ); +/// +/// assert!(matches!( +/// result, +/// Err(DataError { +/// kind: DataErrorKind::MissingDataKey, +/// .. +/// }) +/// )); +/// ``` +#[derive(Debug, Copy, Clone)] +pub struct NeverMarker(PhantomData); + +impl DataMarker for NeverMarker +where + for<'a> Y: Yokeable<'a>, +{ + type Yokeable = Y; +} + +impl KeyedDataMarker for NeverMarker +where + for<'a> Y: Yokeable<'a>, +{ + const KEY: DataKey = data_key!("_never@1"); +} + +/// Implements `DataProvider>` on a struct. +/// +/// For more information, see [`NeverMarker`]. +/// +/// # Examples +/// +/// ``` +/// use icu_locid::locale; +/// use icu_provider::hello_world::*; +/// use icu_provider::prelude::*; +/// use icu_provider::NeverMarker; +/// +/// struct MyProvider; +/// +/// icu_provider::impl_data_provider_never_marker!(MyProvider); +/// +/// let result = DataProvider::>>::load( +/// &MyProvider, +/// DataRequest { +/// locale: &locale!("und").into(), +/// metadata: Default::default(), +/// }, +/// ); +/// +/// assert!(matches!( +/// result, +/// Err(DataError { +/// kind: DataErrorKind::MissingDataKey, +/// .. +/// }) +/// )); +/// ``` +#[macro_export] +macro_rules! impl_data_provider_never_marker { + ($ty:path) => { + impl $crate::DataProvider<$crate::NeverMarker> for $ty + where + for<'a> Y: $crate::yoke::Yokeable<'a>, + { + fn load( + &self, + req: $crate::DataRequest, + ) -> Result<$crate::DataResponse<$crate::NeverMarker>, $crate::DataError> { + Err($crate::DataErrorKind::MissingDataKey.with_req( + <$crate::NeverMarker as $crate::KeyedDataMarker>::KEY, + req, + )) + } + } + }; +} diff --git a/provider/datagen/src/baked_exporter.rs b/provider/datagen/src/baked_exporter.rs index 1719cbe7bbe..36ed635ad9b 100644 --- a/provider/datagen/src/baked_exporter.rs +++ b/provider/datagen/src/baked_exporter.rs @@ -657,6 +657,7 @@ impl BakedExporter { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)] diff --git a/provider/datagen/src/provider.rs b/provider/datagen/src/provider.rs index 3643e435aa4..899ae0a27a4 100644 --- a/provider/datagen/src/provider.rs +++ b/provider/datagen/src/provider.rs @@ -33,6 +33,7 @@ pub struct DatagenProvider { } crate::registry::make_exportable_provider!(DatagenProvider); +icu_provider::impl_data_provider_never_marker!(DatagenProvider); impl DatagenProvider { /// The latest CLDR JSON tag that has been verified to work with this version of `icu_datagen`. diff --git a/provider/datagen/tests/data/baked/macros.rs b/provider/datagen/tests/data/baked/macros.rs index 67299e961f1..a7aa73c9bf8 100644 --- a/provider/datagen/tests/data/baked/macros.rs +++ b/provider/datagen/tests/data/baked/macros.rs @@ -20,6 +20,7 @@ macro_rules! __make_provider { #[allow(dead_code)] pub const MUST_USE_MAKE_PROVIDER_MACRO: () = (); } + icu_provider::impl_data_provider_never_marker!($name); }; } #[doc(inline)]