ronantakizawa/codereview-bench huggingface dataset:
Repository: paritytech/substrate
File: frame/election-provider-support/solution-type/src/lib.rs (Rust)

Code before:
fn parse_parenthesized_number<N: std::str::FromStr>(input_expr: syn::ExprParen) -> syn::Result<N>
where
	<N as std::str::FromStr>::Err: std::fmt::Display,
{
	let expr = input_expr.expr;
	let expr_lit = match *expr {
		syn::Expr::Lit(count_lit) => count_lit.lit,
		_ => return Err(syn_err("Count must be literal.")),
	};
	let int_lit = match expr_lit {
		syn::Lit::Int(int_lit) => int_lit,
		_ => return Err(syn_err("Count must be int literal.")),
	};
	int_lit.base10_parse::<N>()
}

fn imports() -> Result<TokenStream2> {
	match crate_name("frame-election-provider-support") {
		Ok(FoundCrate::Itself) => Ok(quote! {
			use crate as _feps;
			use _feps::private as _fepsp;
		}),
		Ok(FoundCrate::Name(frame_election_provider_support)) => {
			let ident = syn::Ident::new(&frame_election_provider_support, Span::call_site());
			Ok(quote!(
					extern crate #ident as _feps;
					use _feps::private as _fepsp;
			))
		},
		Err(e) => Err(syn::Error::new(Span::call_site(), e)),
	}
}

#[cfg(test)]
mod tests {
	#[test]
	fn ui_fail() {
		// Only run the ui tests when `RUN_UI_TESTS` is set.
		if std::env::var("RUN_UI_TESTS").is_err() {
			return
		}

		let cases = trybuild::TestCases::new();
		cases.compile_fail("tests/ui/fail/*.rs");
	}
}


Review comment (suggestion):
```suggestion
					use #ident as _feps;
```

I think everyone is using 2018 by now.

Code after:
fn parse_parenthesized_number<N: std::str::FromStr>(input_expr: syn::ExprParen) -> syn::Result<N>
where
	<N as std::str::FromStr>::Err: std::fmt::Display,
{
	let expr = input_expr.expr;
	let expr_lit = match *expr {
		syn::Expr::Lit(count_lit) => count_lit.lit,
		_ => return Err(syn_err("Count must be literal.")),
	};
	let int_lit = match expr_lit {
		syn::Lit::Int(int_lit) => int_lit,
		_ => return Err(syn_err("Count must be int literal.")),
	};
	int_lit.base10_parse::<N>()
}

fn imports() -> Result<TokenStream2> {
	match crate_name("frame-election-provider-support") {
		Ok(FoundCrate::Itself) => Ok(quote! {
			use crate as _feps;
			use _feps::private as _fepsp;
		}),
		Ok(FoundCrate::Name(frame_election_provider_support)) => {
			let ident = syn::Ident::new(&frame_election_provider_support, Span::call_site());
			Ok(quote!(
					use #ident as _feps;
					use _feps::private as _fepsp;
			))
		},
		Err(e) => Err(syn::Error::new(Span::call_site(), e)),
	}
}

#[cfg(test)]
mod tests {
	#[test]
	fn ui_fail() {
		// Only run the ui tests when `RUN_UI_TESTS` is set.
		if std::env::var("RUN_UI_TESTS").is_err() {
			return
		}

		let cases = trybuild::TestCases::new();
		cases.compile_fail("tests/ui/fail/*.rs");
	}
}
Repository: paritytech/substrate
File: frame/support/src/traits/storage.rs (Rust)

Code before:
		combined_keys.into_iter().collect::<Vec<_>>()
	}
}

macro_rules! impl_incrementable {
	($($type:ty),+) => {
		$(
			impl Incrementable for $type {
				fn increment(&self) -> Option<Self> {
					let mut val = self.clone();
					val.saturating_inc();
					Some(val)
				}

				fn initial_value() -> Option<Self> {
					Some(0)
				}
			}
		)+
	};
}

/// A trait representing an incrementable type.
///
/// The `increment` and `initial_value` functions are fallible.
/// They should either both return a Some with a valid value, or None.
pub trait Incrementable
where
	Self: Sized,
{
	/// Increments the value.
	///
	/// Returns `Some` with the incremented value if it is possible, or `None` if it is not.
	fn increment(&self) -> Option<Self>;

	/// Returns the initial value.
	///
	/// Returns `Some` with the initial value if it is available, or `None` if it is not.
	fn initial_value() -> Option<Self>;
}

impl_incrementable!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);


Review comment (suggestion):
```suggestion
/// They should either both return `Some` with a valid value, or `None`.
```

Code after:
		combined_keys.into_iter().collect::<Vec<_>>()
	}
}

macro_rules! impl_incrementable {
	($($type:ty),+) => {
		$(
			impl Incrementable for $type {
				fn increment(&self) -> Option<Self> {
					let mut val = self.clone();
					val.saturating_inc();
					Some(val)
				}

				fn initial_value() -> Option<Self> {
					Some(0)
				}
			}
		)+
	};
}

/// A trait representing an incrementable type.
///
/// The `increment` and `initial_value` functions are fallible.
/// They should either both return `Some` with a valid value, or `None`.
pub trait Incrementable
where
	Self: Sized,
{
	/// Increments the value.
	///
	/// Returns `Some` with the incremented value if it is possible, or `None` if it is not.
	fn increment(&self) -> Option<Self>;

	/// Returns the initial value.
	///
	/// Returns `Some` with the initial value if it is available, or `None` if it is not.
	fn initial_value() -> Option<Self>;
}

impl_incrementable!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128);
Repository: paritytech/substrate
File: primitives/state-machine/src/trie_backend_essence.rs (Rust)

Code before:

	fn was_complete(&self) -> bool {
		matches!(self.state, IterState::FinishedComplete)
	}
}

/// Patricia trie-based pairs storage essence.
pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher, C> {
	storage: S,
	root: H::Out,
	empty: H::Out,
	#[cfg(feature = "std")]
	pub(crate) cache: Arc<RwLock<Cache<H::Out>>>,
	pub(crate) trie_node_cache: Option<C>,
	#[cfg(feature = "std")]
	pub(crate) recorder: Option<Recorder<H>>,
}

impl<S: TrieBackendStorage<H>, H: Hasher, C> TrieBackendEssence<S, H, C> {
	/// Create new trie-based backend.
	pub fn new(storage: S, root: H::Out) -> Self {
		TrieBackendEssence {
			storage,
			root,
			empty: H::hash(&[0u8]),
			#[cfg(feature = "std")]
			cache: Arc::new(RwLock::new(Cache::new())),
			trie_node_cache: None,
			#[cfg(feature = "std")]
			recorder: None,
		}
	}

	/// Create new trie-based backend.
	pub fn new_with_cache(storage: S, root: H::Out, cache: Option<C>) -> Self {
		TrieBackendEssence {
			storage,
			root,
			empty: H::hash(&[0u8]),
			#[cfg(feature = "std")]
			cache: Arc::new(RwLock::new(Cache::new())),
			trie_node_cache: cache,
			#[cfg(feature = "std")]
			recorder: None,
		}
	}

	/// Create new trie-based backend.
	#[cfg(feature = "std")]
	pub fn new_with_cache_and_recorder(
		storage: S,

Review comment (performance):
You could simplify `TrieBackendEssence::new` by calling this method in there. (`Self::new_with_cache(storage, root, None)` instead of having the whole struct initialized in two places)

Code after:

	fn was_complete(&self) -> bool {
		matches!(self.state, IterState::FinishedComplete)
	}
}

/// Patricia trie-based pairs storage essence.
pub struct TrieBackendEssence<S: TrieBackendStorage<H>, H: Hasher, C> {
	storage: S,
	root: H::Out,
	empty: H::Out,
	#[cfg(feature = "std")]
	pub(crate) cache: Arc<RwLock<Cache<H::Out>>>,
	pub(crate) trie_node_cache: Option<C>,
	#[cfg(feature = "std")]
	pub(crate) recorder: Option<Recorder<H>>,
}

impl<S: TrieBackendStorage<H>, H: Hasher, C> TrieBackendEssence<S, H, C> {
	/// Create new trie-based backend.
	pub fn new(storage: S, root: H::Out) -> Self {
		Self::new_with_cache(storage, root, None)
	}

	/// Create new trie-based backend.
	pub fn new_with_cache(storage: S, root: H::Out, cache: Option<C>) -> Self {
		TrieBackendEssence {
			storage,
			root,
			empty: H::hash(&[0u8]),
			#[cfg(feature = "std")]
			cache: Arc::new(RwLock::new(Cache::new())),
			trie_node_cache: cache,
			#[cfg(feature = "std")]
			recorder: None,
		}
	}

	/// Create new trie-based backend.
	#[cfg(feature = "std")]
	pub fn new_with_cache_and_recorder(
		storage: S,
		root: H::Out,
		cache: Option<C>,
		recorder: Option<Recorder<H>>,
	) -> Self {
		TrieBackendEssence {
			storage,
			root,
			empty: H::hash(&[0u8]),
			cache: Arc::new(RwLock::new(Cache::new())),
Repository: paritytech/substrate
File: primitives/state-machine/src/trie_backend_essence.rs (Rust)

Code before:
			let mut cache = local_cache.as_trie_db_mut_cache();

			let (new_root, r) = callback(recorder, Some(&mut cache));

			if let Some(new_root) = new_root {
				local_cache.merge(cache, new_root);
			}

			r
		} else {
			callback(recorder, None).1
		};

		result
	}

	#[cfg(not(feature = "std"))]
	fn with_recorder_and_cache_for_storage_root<R>(
		&self,
		_storage_root: Option<H::Out>,
		callback: impl FnOnce(
			Option<&mut dyn TrieRecorder<H::Out>>,
			Option<&mut dyn TrieCache<NodeCodec<H>>>,
		) -> (Option<H::Out>, R),
	) -> R {
		let result = if let Some(local_cache) = self.trie_node_cache.as_ref() {
			let mut cache = local_cache.as_trie_db_mut_cache();

			let (new_root, r) = callback(None, Some(&mut cache));

			if let Some(new_root) = new_root {
				local_cache.merge(cache, new_root);
			}

			r
		} else {
			callback(None, None).1
		};

		result
	}
}

impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync>
	TrieBackendEssence<S, H, C>
where
	H::Out: Codec + Ord,
{
	/// Calls the given closure with a [`TrieDb`] constructed for the given
	/// storage root and (optionally) child trie.
	#[inline]

Review comment (performance):
`result` not needed, `if` expr could be returned.
```suggestion
		if let Some(local_cache) = self.trie_node_cache.as_ref() {
```

Code after:
		callback: impl FnOnce(
			Option<&mut dyn TrieRecorder<H::Out>>,
			Option<&mut dyn TrieCache<NodeCodec<H>>>,
		) -> (Option<H::Out>, R),
	) -> R {
		if let Some(local_cache) = self.trie_node_cache.as_ref() {
			let mut cache = local_cache.as_trie_db_mut_cache();

			let (new_root, r) = callback(None, Some(&mut cache));

			if let Some(new_root) = new_root {
				local_cache.merge(cache, new_root);
			}

			r
		} else {
			callback(None, None).1
		}
	}
}

impl<S: TrieBackendStorage<H>, H: Hasher, C: TrieCacheProvider<H> + Send + Sync>
	TrieBackendEssence<S, H, C>
where
	H::Out: Codec + Ord,
{
	/// Calls the given closure with a [`TrieDb`] constructed for the given
	/// storage root and (optionally) child trie.
	#[inline]
	fn with_trie_db<R>(
		&self,
		root: H::Out,
		child_info: Option<&ChildInfo>,
		callback: impl FnOnce(&sp_trie::TrieDB<Layout<H>>) -> R,
	) -> R {
		let backend = self as &dyn HashDBRef<H, Vec<u8>>;
		let db = child_info
			.as_ref()
			.map(|child_info| KeySpacedDB::new(backend, child_info.keyspace()));
		let db = db.as_ref().map(|db| db as &dyn HashDBRef<H, Vec<u8>>).unwrap_or(backend);

		self.with_recorder_and_cache(Some(root), |recorder, cache| {
			let trie = TrieDBBuilder::<H>::new(db, &root)
				.with_optional_recorder(recorder)
				.with_optional_cache(cache)
				.build();

			callback(&trie)
		})
	}
Repository: paritytech/substrate
File: primitives/metadata-ir/src/lib.rs (Rust)

Code before:
/// Transform the IR to the specified version.
///
/// Use [`supported_versions`] to find supported versions.
pub fn into_version(metadata: MetadataIR, version: u32) -> Option<RuntimeMetadataPrefixed> {
	// Note: Unstable metadata version is `u32::MAX` until stabilized.
	match version {
		// Latest stable version.
		V14 => Some(into_v14(metadata)),
		// Unstable metadata.
		V15 => Some(into_latest(metadata)),
		_ => None,
	}
}

/// Returns the supported metadata versions.
pub fn supported_versions() -> sp_std::vec::Vec<u32> {
	sp_std::vec![V14, V15]
}

/// Transform the IR to the latest stable metadata version.
pub fn into_latest(metadata: MetadataIR) -> RuntimeMetadataPrefixed {
	let latest: frame_metadata::v15::RuntimeMetadataV15 = metadata.into();
	latest.into()
}

/// Transform the IR to the latest stable metadata version.
pub fn into_v14(metadata: MetadataIR) -> RuntimeMetadataPrefixed {
	let latest: frame_metadata::v14::RuntimeMetadataV14 = metadata.into();
	latest.into()
}

#[cfg(test)]
mod test {
	use super::*;
	use frame_metadata::{v14::META_RESERVED, RuntimeMetadata};
	use scale_info::meta_type;

	fn ir_metadata() -> MetadataIR {
		MetadataIR {
			pallets: vec![],
			extrinsic: ExtrinsicMetadataIR {
				ty: meta_type::<()>(),
				version: 0,
				address_ty: meta_type::<()>(),
				call_ty: meta_type::<()>(),
				signature_ty: meta_type::<()>(),
				extra_ty: meta_type::<()>(),
				signed_extensions: vec![],
			},
			ty: meta_type::<()>(),
			apis: vec![],

Review comment (bug):
Nit: comment wrong

```suggestion
/// Transform the IR to metadata version 14.
```

Code after:
/// Transform the IR to the specified version.
///
/// Use [`supported_versions`] to find supported versions.
pub fn into_version(metadata: MetadataIR, version: u32) -> Option<RuntimeMetadataPrefixed> {
	// Note: Unstable metadata version is `u32::MAX` until stabilized.
	match version {
		// Latest stable version.
		V14 => Some(into_v14(metadata)),
		// Unstable metadata.
		V15 => Some(into_latest(metadata)),
		_ => None,
	}
}

/// Returns the supported metadata versions.
pub fn supported_versions() -> sp_std::vec::Vec<u32> {
	sp_std::vec![V14, V15]
}

/// Transform the IR to the latest stable metadata version.
pub fn into_latest(metadata: MetadataIR) -> RuntimeMetadataPrefixed {
	let latest: frame_metadata::v15::RuntimeMetadataV15 = metadata.into();
	latest.into()
}

/// Transform the IR to metadata version 14.
pub fn into_v14(metadata: MetadataIR) -> RuntimeMetadataPrefixed {
	let latest: frame_metadata::v14::RuntimeMetadataV14 = metadata.into();
	latest.into()
}

#[cfg(test)]
mod test {
	use super::*;
	use frame_metadata::{v14::META_RESERVED, RuntimeMetadata};
	use scale_info::meta_type;

	fn ir_metadata() -> MetadataIR {
		MetadataIR {
			pallets: vec![],
			extrinsic: ExtrinsicMetadataIR {
				ty: meta_type::<()>(),
				version: 0,
				address_ty: meta_type::<()>(),
				call_ty: meta_type::<()>(),
				signature_ty: meta_type::<()>(),
				extra_ty: meta_type::<()>(),
				signed_extensions: vec![],
			},
			ty: meta_type::<()>(),
			apis: vec![],
Repository: paritytech/substrate
File: frame/support/procedural/src/construct_runtime/expand/inherent.rs (Rust)

Code before:
						Err(Error::DecodingFailed(_, _)) | Err(Error::Application(_)) =>
							log::error!(
								target: LOG_TARGET,
								"Unexpected error from `put_error` operation",
							),
					}
				}

				for xt in block.extrinsics() {
					// Inherents are before any other extrinsics.
					// And signed extrinsics are not inherents.
					if #scrate::sp_runtime::traits::Extrinsic::is_signed(xt).unwrap_or(false) {
						break
					}

					let mut is_inherent = false;

					#(
						#pallet_attrs
						{
							let call = <#unchecked_extrinsic as ExtrinsicCall>::call(xt);
							if let Some(call) = IsSubType::<_>::is_sub_type(call) {
								if #pallet_names::is_inherent(call) {
									is_inherent = true;
									if let Err(e) = #pallet_names::check_inherent(call, self) {
										handle_put_error_result(result.put_error(
											#pallet_names::INHERENT_IDENTIFIER, &e
										));
										if e.is_fatal_error() {
											return result;
										}
									}
								}
							}
						}
					)*

					// Inherents are before any other extrinsics.
					// No module marked it as inherent thus it is not.
					if !is_inherent {
						break
					}
				}

				#(
					#pallet_attrs
					match #pallet_names::is_inherent_required(self) {
						Ok(Some(e)) => {
							let found = block.extrinsics().iter().any(|xt| {
								let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt)
									.unwrap_or(false);

Review comment (refactor):
I would suggest that we move the `if fata_error { return }` part also to a helper function as this is the part that is still important and ensures we bail after seeing one error. 

Code after:
						Err(_) =>
							log::error!(
								target: LOG_TARGET,
								"Unexpected error from `put_error` operation",
							),
					}
				}

				for xt in block.extrinsics() {
					// Inherents are before any other extrinsics.
					// And signed extrinsics are not inherents.
					if #scrate::sp_runtime::traits::Extrinsic::is_signed(xt).unwrap_or(false) {
						break
					}

					let mut is_inherent = false;

					#(
						#pallet_attrs
						{
							let call = <#unchecked_extrinsic as ExtrinsicCall>::call(xt);
							if let Some(call) = IsSubType::<_>::is_sub_type(call) {
								if #pallet_names::is_inherent(call) {
									is_inherent = true;
									if let Err(e) = #pallet_names::check_inherent(call, self) {
										handle_put_error_result(result.put_error(
											#pallet_names::INHERENT_IDENTIFIER, &e
										));
										if e.is_fatal_error() {
											return result;
										}
									}
								}
							}
						}
					)*

					// Inherents are before any other extrinsics.
					// No module marked it as inherent thus it is not.
					if !is_inherent {
						break
					}
				}

				#(
					#pallet_attrs
					match #pallet_names::is_inherent_required(self) {
						Ok(Some(e)) => {
							let found = block.extrinsics().iter().any(|xt| {
								let is_signed = #scrate::sp_runtime::traits::Extrinsic::is_signed(xt)
									.unwrap_or(false);
Repository: paritytech/substrate
File: frame/support/src/lib.rs (Rust)

Code before:
pub use paste;
#[doc(hidden)]
pub use scale_info;
pub use serde;
pub use sp_api::metadata_ir;
pub use sp_core::{OpaqueMetadata, Void};
#[doc(hidden)]
pub use sp_core_hashing_proc_macro;
#[doc(hidden)]
pub use sp_io::{self, storage::root as storage_root};
#[cfg(feature = "std")]
#[doc(hidden)]
pub use sp_runtime::{bounded_btree_map, bounded_vec};
#[doc(hidden)]
pub use sp_runtime::{RuntimeDebug, StateVersion};
#[cfg(feature = "std")]
#[doc(hidden)]
pub use sp_state_machine::BasicExternalities;
#[doc(hidden)]
pub use sp_std;
#[doc(hidden)]
pub use tt_call::*;

// Re-exports go here:
#[doc(hidden)]
pub mod private {
	#[cfg(feature = "std")]
	pub use sp_state_machine::ReadOnlyExternalities;
}

#[macro_use]
pub mod dispatch;
mod hash;
pub mod storage;
#[macro_use]
pub mod event;
pub mod inherent;
#[macro_use]
pub mod error;
pub mod crypto;
pub mod dispatch_context;
pub mod instances;
pub mod migrations;
pub mod traits;
pub mod weights;
#[doc(hidden)]
pub mod unsigned {
	#[doc(hidden)]
	pub use crate::sp_runtime::traits::ValidateUnsigned;
	#[doc(hidden)]
	pub use crate::sp_runtime::transaction_validity::{

Review comment (suggestion):
```suggestion
pub mod __private {
```

Maybe to make it even more "weird" to use this :P 

Code after:
pub use paste;
#[doc(hidden)]
pub use scale_info;
pub use serde;
pub use sp_api::metadata_ir;
pub use sp_core::{OpaqueMetadata, Void};
#[doc(hidden)]
pub use sp_core_hashing_proc_macro;
#[doc(hidden)]
pub use sp_io::{self, storage::root as storage_root};
#[cfg(feature = "std")]
#[doc(hidden)]
pub use sp_runtime::{bounded_btree_map, bounded_vec};
#[doc(hidden)]
pub use sp_runtime::{RuntimeDebug, StateVersion};
#[cfg(feature = "std")]
#[doc(hidden)]
pub use sp_state_machine::BasicExternalities;
#[doc(hidden)]
pub use sp_std;
#[doc(hidden)]
pub use tt_call::*;

#[macro_use]
pub mod dispatch;
mod hash;
pub mod storage;
#[macro_use]
pub mod event;
pub mod inherent;
#[macro_use]
pub mod error;
pub mod crypto;
pub mod dispatch_context;
pub mod instances;
pub mod migrations;
pub mod traits;
pub mod weights;
#[doc(hidden)]
pub mod unsigned {
	#[doc(hidden)]
	pub use crate::sp_runtime::traits::ValidateUnsigned;
	#[doc(hidden)]
	pub use crate::sp_runtime::transaction_validity::{
		TransactionSource, TransactionValidity, TransactionValidityError, UnknownTransaction,
	};
}

#[cfg(any(feature = "std", feature = "runtime-benchmarks", feature = "try-runtime", test))]
pub use self::storage::storage_noop_guard::StorageNoopGuard;
pub use self::{
Repository: paritytech/substrate
File: client/network/src/service/out_events.rs (Rust)

Code before:
		let metrics = self.metrics.clone();
		if let Some(metrics) = metrics.as_ref() {
			metrics.num_channels.with_label_values(&[self.name]).dec();
		}
	}
}

/// Receiving side of a channel.
pub struct Receiver {
	inner: async_channel::Receiver<Event>,
	name: &'static str,
	/// Initially contains `None`, and will be set to a value once the corresponding [`Sender`]
	/// is assigned to an instance of [`OutChannels`].
	metrics: Option<Metrics>,
}

impl Stream for Receiver {
	type Item = Event;

	fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Event>> {
		if let Some(ev) = ready!(Pin::new(&mut self.inner).poll_next(cx)) {
			let metrics = self.metrics.clone();
			match metrics.as_ref() {
				Some(metrics) => metrics.event_out(&ev, self.name),
				None => (), // no registry
			}
			Poll::Ready(Some(ev))
		} else {
			Poll::Ready(None)
		}
	}
}

impl fmt::Debug for Receiver {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.debug_tuple("Receiver").finish()
	}
}

impl Drop for Receiver {
	fn drop(&mut self) {
		if !self.inner.is_terminated() {
			// Empty the list to properly decrease the metrics.
			while let Some(Some(_)) = self.next().now_or_never() {}
		}
	}
}

/// Collection of senders.
pub struct OutChannels {
	event_streams: Vec<Sender>,

Review comment (suggestion):
```suggestion
			if let Some(metrics) = &self.metrics {
				metrics.event_out(&ev, self.name);
			}
```

Code after:
	/// Backtrace of a place where the channel was created.
	creation_backtrace: Backtrace,
	/// Clone of [`Receiver::metrics`]. Will be initialized when [`Sender`] is added to
	/// [`OutChannels`] with `OutChannels::push()`.
	metrics: Option<Metrics>,
}

impl fmt::Debug for Sender {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.debug_tuple("Sender").finish()
	}
}

impl Drop for Sender {
	fn drop(&mut self) {
		if let Some(metrics) = self.metrics.as_ref() {
			metrics.num_channels.with_label_values(&[self.name]).dec();
		}
	}
}

/// Receiving side of a channel.
pub struct Receiver {
	inner: async_channel::Receiver<Event>,
	name: &'static str,
	/// Initially contains `None`, and will be set to a value once the corresponding [`Sender`]
	/// is assigned to an instance of [`OutChannels`].
	metrics: Option<Metrics>,
}

impl Stream for Receiver {
	type Item = Event;

	fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Event>> {
		if let Some(ev) = ready!(Pin::new(&mut self.inner).poll_next(cx)) {
			if let Some(metrics) = &self.metrics {
				metrics.event_out(&ev, self.name);
			}
			Poll::Ready(Some(ev))
		} else {
			Poll::Ready(None)
		}
	}
}

impl fmt::Debug for Receiver {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.debug_tuple("Receiver").finish()
	}
}