Add a TypeNameToDebug formatter to zebra_chain (#2466)
* Add a TypeNameToDebug formatter to zebra_chain This formatter makes it much easier to diagnose proptest errors. It will be used in a future PR. Implement Arbitrary and DerefMut for all the formatters. Also make the formatter type bounds consistent, to produce better compiler errors. * Clarify how TypeNameToDebug actually works Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com> Co-authored-by: Janito Vaqueiro Ferreira Filho <janito.vff@gmail.com>
This commit is contained in:
parent
23fe2c2e94
commit
64be7fddb7
|
|
@ -2,20 +2,23 @@
|
||||||
|
|
||||||
use std::{fmt, ops};
|
use std::{fmt, ops};
|
||||||
|
|
||||||
/// Wrapper to override `Debug`, redirecting it to the `Display` impl.
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
|
use proptest::prelude::*;
|
||||||
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
|
use proptest_derive::Arbitrary;
|
||||||
|
|
||||||
|
/// Wrapper to override `Debug`, redirecting it to only output the type's name.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct DisplayToDebug<T>(pub T);
|
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||||
|
pub struct TypeNameToDebug<T>(pub T);
|
||||||
|
|
||||||
impl<T> fmt::Debug for DisplayToDebug<T>
|
impl<T> fmt::Debug for TypeNameToDebug<T> {
|
||||||
where
|
|
||||||
T: fmt::Display,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
self.0.fmt(f)
|
f.write_str(std::any::type_name::<T>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> ops::Deref for DisplayToDebug<T> {
|
impl<T> ops::Deref for TypeNameToDebug<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|
@ -23,7 +26,44 @@ impl<T> ops::Deref for DisplayToDebug<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<T> for DisplayToDebug<T> {
|
impl<T> ops::DerefMut for TypeNameToDebug<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> From<T> for TypeNameToDebug<T> {
|
||||||
|
fn from(t: T) -> Self {
|
||||||
|
Self(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapper to override `Debug`, redirecting it to the `Display` impl.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
#[cfg_attr(any(test, feature = "proptest-impl"), derive(Arbitrary))]
|
||||||
|
pub struct DisplayToDebug<T: fmt::Display>(pub T);
|
||||||
|
|
||||||
|
impl<T: fmt::Display> fmt::Debug for DisplayToDebug<T> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
self.0.fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display> ops::Deref for DisplayToDebug<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display> ops::DerefMut for DisplayToDebug<T> {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: fmt::Display> From<T> for DisplayToDebug<T> {
|
||||||
fn from(t: T) -> Self {
|
fn from(t: T) -> Self {
|
||||||
Self(t)
|
Self(t)
|
||||||
}
|
}
|
||||||
|
|
@ -34,7 +74,10 @@ impl<T> From<T> for DisplayToDebug<T> {
|
||||||
/// For collections and exact size iterators, it only displays the
|
/// For collections and exact size iterators, it only displays the
|
||||||
/// collection/iterator type, the item type, and the length.
|
/// collection/iterator type, the item type, and the length.
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct SummaryDebug<CollectionOrIter>(pub CollectionOrIter);
|
pub struct SummaryDebug<CollectionOrIter>(pub CollectionOrIter)
|
||||||
|
where
|
||||||
|
CollectionOrIter: IntoIterator + Clone,
|
||||||
|
<CollectionOrIter as IntoIterator>::IntoIter: ExactSizeIterator;
|
||||||
|
|
||||||
impl<CollectionOrIter> fmt::Debug for SummaryDebug<CollectionOrIter>
|
impl<CollectionOrIter> fmt::Debug for SummaryDebug<CollectionOrIter>
|
||||||
where
|
where
|
||||||
|
|
@ -52,7 +95,11 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CollectionOrIter> ops::Deref for SummaryDebug<CollectionOrIter> {
|
impl<CollectionOrIter> ops::Deref for SummaryDebug<CollectionOrIter>
|
||||||
|
where
|
||||||
|
CollectionOrIter: IntoIterator + Clone,
|
||||||
|
<CollectionOrIter as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||||
|
{
|
||||||
type Target = CollectionOrIter;
|
type Target = CollectionOrIter;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
|
|
@ -60,7 +107,21 @@ impl<CollectionOrIter> ops::Deref for SummaryDebug<CollectionOrIter> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<CollectionOrIter> From<CollectionOrIter> for SummaryDebug<CollectionOrIter> {
|
impl<CollectionOrIter> ops::DerefMut for SummaryDebug<CollectionOrIter>
|
||||||
|
where
|
||||||
|
CollectionOrIter: IntoIterator + Clone,
|
||||||
|
<CollectionOrIter as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||||
|
{
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<CollectionOrIter> From<CollectionOrIter> for SummaryDebug<CollectionOrIter>
|
||||||
|
where
|
||||||
|
CollectionOrIter: IntoIterator + Clone,
|
||||||
|
<CollectionOrIter as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||||
|
{
|
||||||
fn from(collection: CollectionOrIter) -> Self {
|
fn from(collection: CollectionOrIter) -> Self {
|
||||||
Self(collection)
|
Self(collection)
|
||||||
}
|
}
|
||||||
|
|
@ -68,7 +129,8 @@ impl<CollectionOrIter> From<CollectionOrIter> for SummaryDebug<CollectionOrIter>
|
||||||
|
|
||||||
impl<CollectionOrIter> IntoIterator for SummaryDebug<CollectionOrIter>
|
impl<CollectionOrIter> IntoIterator for SummaryDebug<CollectionOrIter>
|
||||||
where
|
where
|
||||||
CollectionOrIter: IntoIterator,
|
CollectionOrIter: IntoIterator + Clone,
|
||||||
|
<CollectionOrIter as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||||
{
|
{
|
||||||
type Item = <CollectionOrIter as IntoIterator>::Item;
|
type Item = <CollectionOrIter as IntoIterator>::Item;
|
||||||
type IntoIter = <CollectionOrIter as IntoIterator>::IntoIter;
|
type IntoIter = <CollectionOrIter as IntoIterator>::IntoIter;
|
||||||
|
|
@ -77,3 +139,20 @@ where
|
||||||
self.0.into_iter()
|
self.0.into_iter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(test, feature = "proptest-impl"))]
|
||||||
|
impl<CollectionOrIter> Arbitrary for SummaryDebug<CollectionOrIter>
|
||||||
|
where
|
||||||
|
CollectionOrIter: Arbitrary + IntoIterator + Clone + 'static,
|
||||||
|
<CollectionOrIter as IntoIterator>::IntoIter: ExactSizeIterator,
|
||||||
|
{
|
||||||
|
type Parameters = <CollectionOrIter as Arbitrary>::Parameters;
|
||||||
|
|
||||||
|
fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
|
||||||
|
CollectionOrIter::arbitrary_with(args)
|
||||||
|
.prop_map_into()
|
||||||
|
.boxed()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Strategy = BoxedStrategy<Self>;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue