1 /* 2 * Copyright (C) 2025 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 use std::{ 18 any::type_name, 19 fmt::{self, Debug, Display, Formatter}, 20 }; 21 22 /// Provides access to a best-effort implementation of [Display]. 23 /// 24 /// [BestEffortDisplay] creates a wrapper that implements [Display] for the 25 /// provided type. 26 /// * If `T` implements [Display], the wrapper will forward to `T`'s [Display] 27 /// implementation. 28 /// * If `T` does not implement [Display], but does implement [Debug], the 29 /// wrapper will use to `T`'s [Debug] implementation. 30 /// * If `T` implements neither [Display] nor [Debug], the wrapper will 31 /// display `T`'s [type_name]. 32 /// 33 /// The wrapper should be created with the following expression. The 34 /// [DisplayKind], [DebugKind], and [TypenameKind] traits need to be in scope. 35 /// (` as _` is fine; the traits just need to be in scope for method resolution; 36 /// the actual trait names don't need to be accessible.) 37 /// 38 /// ``` 39 /// # fn example() -> impl std::fmt::Display { 40 /// # let x: usize = 5; 41 /// # use test::__internal_macro_utils::{ 42 /// # BestEffortDisplay, 43 /// # DisplayKind as _, 44 /// # DebugKind as _, 45 /// # TypenameKind as _, 46 /// # }; 47 /// (&&&BestEffortDisplay(&x)).display_kind().wrap(x) 48 /// # } 49 /// ``` 50 /// 51 /// # Examples 52 /// 53 /// ``` 54 /// use test::__internal_macro_utils::BestEffortDisplay; 55 /// 56 /// struct NeitherDisplayOrDebug; 57 /// #[derive(Debug)] 58 /// struct DebugOnlyType; 59 /// struct DisplayType; 60 /// 61 /// impl std::fmt::Display for DisplayType { 62 /// fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 63 /// write!(f, "Fancy Description") 64 /// } 65 /// } 66 /// 67 /// let a = DisplayType; 68 /// let b = DebugOnlyType; 69 /// let c = NeitherDisplayOrDebug; 70 /// 71 /// use test::__internal_macro_utils::{DisplayKind as _, DebugKind as _, TypenameKind as _}; 72 /// let a = (&&&BestEffortDisplay(&a)).display_kind().wrap(a); 73 /// let b = (&&&BestEffortDisplay(&b)).display_kind().wrap(b); 74 /// let c = (&&&BestEffortDisplay(&c)).display_kind().wrap(c); 75 /// 76 /// assert_eq!(a.to_string(), "Fancy Description"); 77 /// assert_eq!(b.to_string(), "DebugOnlyType"); 78 /// assert_eq!(c.to_string(), 79 /// format!("value of type {}", 80 /// std::any::type_name::<NeitherDisplayOrDebug>())); 81 /// ``` 82 /// 83 /// [BestEffortDisplay] is implemented with [autoref specialization], which has 84 /// some limitations, namely that we have to know that `T` implements [Display] 85 /// at `get`'s callsite. As a result, it's mostly only useful inside macros. 86 /// Because the specialization has [more than two levels], we're acutually using 87 /// auto*de*ref, which is why the usage requires calling `display_kind` on 88 /// `&&&Self` (one more `&` than the highest priority `*Kind` impl). 89 /// 90 /// Once stable Rust supports [min_specialization], this should be replaced to 91 /// use that instead. 92 /// 93 /// [autoref specialization]: https://github.com/dtolnay/case-studies/blob/master/autoref-specialization/README.md 94 /// [more than two levels]: https://lukaskalbertodt.github.io/2019/12/05/generalized-autoref-based-specialization.html#using-autoderef-for--two-specialization-levels 95 /// [min_specialization]: https://doc.rust-lang.org/nightly/unstable-book/language-features/min-specialization.html#min_specialization 96 pub struct BestEffortDisplay<T>(pub T); 97 98 // When calling `(&&&BestEffortDisplay(&x)).display_kind()`, autoderef 99 // prioritizes the `DisplayKind` impl if it applies, then the `DebugKind` impl 100 // if it applies, then `TypenameKind`, which always applies. 101 impl<T: Display> DisplayKind for &&BestEffortDisplay<&T> {} 102 impl<T: Debug> DebugKind for &BestEffortDisplay<&T> {} 103 impl<T> TypenameKind for BestEffortDisplay<&T> {} 104 105 /// Constructs [Display] wrappers for types that implement [Display]. 106 pub struct DisplayTag; 107 /// Constructs [Display] wrappers for types that implement [Debug]. 108 pub struct DebugTag; 109 /// Constructs [Display] wrappers for any type. 110 pub struct TypenameTag; 111 112 /// Implements [Display] by delegating to `T`'s [Display] implementation. 113 pub struct DisplayDisplayer<T>(T); 114 /// Implements [Display] by delegating to `T`'s [Debug] implementation. 115 pub struct DebugDisplayer<T>(T); 116 /// Implements [Display] by printing `T`'s [type_name]. 117 pub struct TypenameDisplayer<T>(T); 118 119 pub trait DisplayKind { 120 #[inline] display_kind(&self) -> DisplayTag121 fn display_kind(&self) -> DisplayTag { 122 DisplayTag 123 } 124 } 125 pub trait DebugKind { 126 #[inline] display_kind(&self) -> DebugTag127 fn display_kind(&self) -> DebugTag { 128 DebugTag 129 } 130 } 131 pub trait TypenameKind { 132 #[inline] display_kind(&self) -> TypenameTag133 fn display_kind(&self) -> TypenameTag { 134 TypenameTag 135 } 136 } 137 138 impl DisplayTag { wrap<T: Display>(self, t: T) -> DisplayDisplayer<T>139 pub fn wrap<T: Display>(self, t: T) -> DisplayDisplayer<T> { 140 DisplayDisplayer(t) 141 } 142 } 143 impl DebugTag { wrap<T: Debug>(self, t: T) -> DebugDisplayer<T>144 pub fn wrap<T: Debug>(self, t: T) -> DebugDisplayer<T> { 145 DebugDisplayer(t) 146 } 147 } 148 impl TypenameTag { wrap<T>(self, t: T) -> TypenameDisplayer<T>149 pub fn wrap<T>(self, t: T) -> TypenameDisplayer<T> { 150 TypenameDisplayer(t) 151 } 152 } 153 154 impl<T: Display> Display for DisplayDisplayer<T> { fmt(&self, f: &mut Formatter) -> fmt::Result155 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 156 write!(f, "{}", self.0) 157 } 158 } 159 impl<T: Debug> Display for DebugDisplayer<T> { fmt(&self, f: &mut Formatter) -> fmt::Result160 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 161 write!(f, "{:?}", self.0) 162 } 163 } 164 impl<T> Display for TypenameDisplayer<T> { fmt(&self, f: &mut Formatter) -> fmt::Result165 fn fmt(&self, f: &mut Formatter) -> fmt::Result { 166 write!(f, "value of type {}", type_name::<T>()) 167 } 168 } 169