1use std::collections::HashSet;
7
8#[derive(Debug, Clone)]
13pub struct StdImplCache {
14 impls: HashSet<(&'static str, &'static str)>,
16}
17
18impl StdImplCache {
19 pub fn new() -> Self {
21 Self::default()
22 }
23
24 #[inline]
26 pub fn has_impl(&self, type_name: &str, trait_name: &str) -> bool {
27 if self.impls.contains(&(type_name, trait_name)) {
29 return true;
30 }
31
32 let short_type = type_name.rsplit("::").next().unwrap_or(type_name);
34 let short_trait = trait_name.rsplit("::").next().unwrap_or(trait_name);
35
36 self.impls
37 .iter()
38 .any(|(t, tr)| *t == short_type && *tr == short_trait)
39 }
40
41 pub fn is_primitive(&self, type_name: &str) -> bool {
43 matches!(
44 type_name,
45 "i8" | "i16"
46 | "i32"
47 | "i64"
48 | "i128"
49 | "isize"
50 | "u8"
51 | "u16"
52 | "u32"
53 | "u64"
54 | "u128"
55 | "usize"
56 | "f32"
57 | "f64"
58 | "bool"
59 | "char"
60 | "()"
61 | "str"
62 )
63 }
64
65 pub fn is_std_container(&self, type_name: &str) -> bool {
67 let short = type_name.rsplit("::").next().unwrap_or(type_name);
68 matches!(
69 short,
70 "Vec"
71 | "String"
72 | "Option"
73 | "Result"
74 | "Box"
75 | "Rc"
76 | "Arc"
77 | "Cell"
78 | "RefCell"
79 | "HashMap"
80 | "HashSet"
81 | "BTreeMap"
82 | "BTreeSet"
83 | "VecDeque"
84 | "LinkedList"
85 | "BinaryHeap"
86 | "PathBuf"
87 | "OsString"
88 | "Cow"
89 )
90 }
91
92 pub fn traits_for(&self, type_name: &str) -> Vec<&'static str> {
94 let short = type_name.rsplit("::").next().unwrap_or(type_name);
95 self.impls
96 .iter()
97 .filter(|(t, _)| *t == short)
98 .map(|(_, tr)| *tr)
99 .collect()
100 }
101}
102
103impl Default for StdImplCache {
104 fn default() -> Self {
105 let mut impls = HashSet::new();
106
107 for prim in ["i8", "i16", "i32", "i64", "i128", "isize"] {
110 impls.insert((prim, "Clone"));
111 impls.insert((prim, "Copy"));
112 impls.insert((prim, "Debug"));
113 impls.insert((prim, "Default"));
114 impls.insert((prim, "PartialEq"));
115 impls.insert((prim, "Eq"));
116 impls.insert((prim, "PartialOrd"));
117 impls.insert((prim, "Ord"));
118 impls.insert((prim, "Hash"));
119 impls.insert((prim, "Send"));
120 impls.insert((prim, "Sync"));
121 }
122
123 for prim in ["u8", "u16", "u32", "u64", "u128", "usize"] {
125 impls.insert((prim, "Clone"));
126 impls.insert((prim, "Copy"));
127 impls.insert((prim, "Debug"));
128 impls.insert((prim, "Default"));
129 impls.insert((prim, "PartialEq"));
130 impls.insert((prim, "Eq"));
131 impls.insert((prim, "PartialOrd"));
132 impls.insert((prim, "Ord"));
133 impls.insert((prim, "Hash"));
134 impls.insert((prim, "Send"));
135 impls.insert((prim, "Sync"));
136 }
137
138 for prim in ["f32", "f64"] {
140 impls.insert((prim, "Clone"));
141 impls.insert((prim, "Copy"));
142 impls.insert((prim, "Debug"));
143 impls.insert((prim, "Default"));
144 impls.insert((prim, "PartialEq"));
145 impls.insert((prim, "PartialOrd"));
146 impls.insert((prim, "Send"));
147 impls.insert((prim, "Sync"));
148 }
149
150 impls.insert(("bool", "Clone"));
152 impls.insert(("bool", "Copy"));
153 impls.insert(("bool", "Debug"));
154 impls.insert(("bool", "Default"));
155 impls.insert(("bool", "PartialEq"));
156 impls.insert(("bool", "Eq"));
157 impls.insert(("bool", "PartialOrd"));
158 impls.insert(("bool", "Ord"));
159 impls.insert(("bool", "Hash"));
160 impls.insert(("bool", "Send"));
161 impls.insert(("bool", "Sync"));
162
163 impls.insert(("char", "Clone"));
165 impls.insert(("char", "Copy"));
166 impls.insert(("char", "Debug"));
167 impls.insert(("char", "PartialEq"));
168 impls.insert(("char", "Eq"));
169 impls.insert(("char", "PartialOrd"));
170 impls.insert(("char", "Ord"));
171 impls.insert(("char", "Hash"));
172 impls.insert(("char", "Send"));
173 impls.insert(("char", "Sync"));
174
175 impls.insert(("()", "Clone"));
177 impls.insert(("()", "Copy"));
178 impls.insert(("()", "Debug"));
179 impls.insert(("()", "Default"));
180 impls.insert(("()", "PartialEq"));
181 impls.insert(("()", "Eq"));
182 impls.insert(("()", "PartialOrd"));
183 impls.insert(("()", "Ord"));
184 impls.insert(("()", "Hash"));
185 impls.insert(("()", "Send"));
186 impls.insert(("()", "Sync"));
187
188 impls.insert(("String", "Clone"));
192 impls.insert(("String", "Debug"));
193 impls.insert(("String", "Default"));
194 impls.insert(("String", "PartialEq"));
195 impls.insert(("String", "Eq"));
196 impls.insert(("String", "PartialOrd"));
197 impls.insert(("String", "Ord"));
198 impls.insert(("String", "Hash"));
199 impls.insert(("String", "Send"));
200 impls.insert(("String", "Sync"));
201
202 impls.insert(("Vec", "Clone"));
204 impls.insert(("Vec", "Debug"));
205 impls.insert(("Vec", "Default"));
206 impls.insert(("Vec", "PartialEq"));
207 impls.insert(("Vec", "Eq"));
208 impls.insert(("Vec", "Hash"));
209 impls.insert(("Vec", "Send"));
210 impls.insert(("Vec", "Sync"));
211
212 impls.insert(("Option", "Clone"));
214 impls.insert(("Option", "Copy"));
215 impls.insert(("Option", "Debug"));
216 impls.insert(("Option", "Default"));
217 impls.insert(("Option", "PartialEq"));
218 impls.insert(("Option", "Eq"));
219 impls.insert(("Option", "PartialOrd"));
220 impls.insert(("Option", "Ord"));
221 impls.insert(("Option", "Hash"));
222 impls.insert(("Option", "Send"));
223 impls.insert(("Option", "Sync"));
224
225 impls.insert(("Result", "Clone"));
227 impls.insert(("Result", "Copy"));
228 impls.insert(("Result", "Debug"));
229 impls.insert(("Result", "PartialEq"));
230 impls.insert(("Result", "Eq"));
231 impls.insert(("Result", "PartialOrd"));
232 impls.insert(("Result", "Ord"));
233 impls.insert(("Result", "Hash"));
234 impls.insert(("Result", "Send"));
235 impls.insert(("Result", "Sync"));
236
237 impls.insert(("Box", "Clone"));
239 impls.insert(("Box", "Debug"));
240 impls.insert(("Box", "Default"));
241 impls.insert(("Box", "PartialEq"));
242 impls.insert(("Box", "Eq"));
243 impls.insert(("Box", "PartialOrd"));
244 impls.insert(("Box", "Ord"));
245 impls.insert(("Box", "Hash"));
246 impls.insert(("Box", "Send"));
247 impls.insert(("Box", "Sync"));
248
249 impls.insert(("Rc", "Clone"));
251 impls.insert(("Rc", "Debug"));
252 impls.insert(("Rc", "Default"));
253 impls.insert(("Rc", "PartialEq"));
254 impls.insert(("Rc", "Eq"));
255 impls.insert(("Rc", "PartialOrd"));
256 impls.insert(("Rc", "Ord"));
257 impls.insert(("Rc", "Hash"));
258
259 impls.insert(("Arc", "Clone"));
261 impls.insert(("Arc", "Debug"));
262 impls.insert(("Arc", "Default"));
263 impls.insert(("Arc", "PartialEq"));
264 impls.insert(("Arc", "Eq"));
265 impls.insert(("Arc", "PartialOrd"));
266 impls.insert(("Arc", "Ord"));
267 impls.insert(("Arc", "Hash"));
268 impls.insert(("Arc", "Send"));
269 impls.insert(("Arc", "Sync"));
270
271 impls.insert(("HashMap", "Clone"));
273 impls.insert(("HashMap", "Debug"));
274 impls.insert(("HashMap", "Default"));
275 impls.insert(("HashMap", "PartialEq"));
276 impls.insert(("HashMap", "Eq"));
277 impls.insert(("HashMap", "Send"));
278 impls.insert(("HashMap", "Sync"));
279
280 impls.insert(("HashSet", "Clone"));
282 impls.insert(("HashSet", "Debug"));
283 impls.insert(("HashSet", "Default"));
284 impls.insert(("HashSet", "PartialEq"));
285 impls.insert(("HashSet", "Eq"));
286 impls.insert(("HashSet", "Send"));
287 impls.insert(("HashSet", "Sync"));
288
289 impls.insert(("BTreeMap", "Clone"));
291 impls.insert(("BTreeMap", "Debug"));
292 impls.insert(("BTreeMap", "Default"));
293 impls.insert(("BTreeMap", "PartialEq"));
294 impls.insert(("BTreeMap", "Eq"));
295 impls.insert(("BTreeMap", "PartialOrd"));
296 impls.insert(("BTreeMap", "Ord"));
297 impls.insert(("BTreeMap", "Send"));
298 impls.insert(("BTreeMap", "Sync"));
299
300 impls.insert(("BTreeSet", "Clone"));
302 impls.insert(("BTreeSet", "Debug"));
303 impls.insert(("BTreeSet", "Default"));
304 impls.insert(("BTreeSet", "PartialEq"));
305 impls.insert(("BTreeSet", "Eq"));
306 impls.insert(("BTreeSet", "PartialOrd"));
307 impls.insert(("BTreeSet", "Ord"));
308 impls.insert(("BTreeSet", "Hash"));
309 impls.insert(("BTreeSet", "Send"));
310 impls.insert(("BTreeSet", "Sync"));
311
312 impls.insert(("PathBuf", "Clone"));
314 impls.insert(("PathBuf", "Debug"));
315 impls.insert(("PathBuf", "Default"));
316 impls.insert(("PathBuf", "PartialEq"));
317 impls.insert(("PathBuf", "Eq"));
318 impls.insert(("PathBuf", "PartialOrd"));
319 impls.insert(("PathBuf", "Ord"));
320 impls.insert(("PathBuf", "Hash"));
321 impls.insert(("PathBuf", "Send"));
322 impls.insert(("PathBuf", "Sync"));
323
324 impls.insert(("OsString", "Clone"));
326 impls.insert(("OsString", "Debug"));
327 impls.insert(("OsString", "Default"));
328 impls.insert(("OsString", "PartialEq"));
329 impls.insert(("OsString", "Eq"));
330 impls.insert(("OsString", "PartialOrd"));
331 impls.insert(("OsString", "Ord"));
332 impls.insert(("OsString", "Hash"));
333 impls.insert(("OsString", "Send"));
334 impls.insert(("OsString", "Sync"));
335
336 impls.insert(("Cell", "Clone"));
338 impls.insert(("Cell", "Copy"));
339 impls.insert(("Cell", "Debug"));
340 impls.insert(("Cell", "Default"));
341 impls.insert(("Cell", "PartialEq"));
342 impls.insert(("Cell", "Eq"));
343 impls.insert(("Cell", "PartialOrd"));
344 impls.insert(("Cell", "Ord"));
345 impls.insert(("Cell", "Send"));
346
347 impls.insert(("RefCell", "Clone"));
349 impls.insert(("RefCell", "Debug"));
350 impls.insert(("RefCell", "Default"));
351 impls.insert(("RefCell", "PartialEq"));
352 impls.insert(("RefCell", "Eq"));
353 impls.insert(("RefCell", "PartialOrd"));
354 impls.insert(("RefCell", "Ord"));
355 impls.insert(("RefCell", "Send"));
356
357 impls.insert(("Cow", "Clone"));
359 impls.insert(("Cow", "Debug"));
360 impls.insert(("Cow", "Default"));
361 impls.insert(("Cow", "PartialEq"));
362 impls.insert(("Cow", "Eq"));
363 impls.insert(("Cow", "PartialOrd"));
364 impls.insert(("Cow", "Ord"));
365 impls.insert(("Cow", "Hash"));
366 impls.insert(("Cow", "Send"));
367 impls.insert(("Cow", "Sync"));
368
369 impls.insert(("VecDeque", "Clone"));
371 impls.insert(("VecDeque", "Debug"));
372 impls.insert(("VecDeque", "Default"));
373 impls.insert(("VecDeque", "PartialEq"));
374 impls.insert(("VecDeque", "Eq"));
375 impls.insert(("VecDeque", "PartialOrd"));
376 impls.insert(("VecDeque", "Ord"));
377 impls.insert(("VecDeque", "Hash"));
378 impls.insert(("VecDeque", "Send"));
379 impls.insert(("VecDeque", "Sync"));
380
381 impls.insert(("PhantomData", "Clone"));
383 impls.insert(("PhantomData", "Copy"));
384 impls.insert(("PhantomData", "Debug"));
385 impls.insert(("PhantomData", "Default"));
386 impls.insert(("PhantomData", "PartialEq"));
387 impls.insert(("PhantomData", "Eq"));
388 impls.insert(("PhantomData", "PartialOrd"));
389 impls.insert(("PhantomData", "Ord"));
390 impls.insert(("PhantomData", "Hash"));
391 impls.insert(("PhantomData", "Send"));
392 impls.insert(("PhantomData", "Sync"));
393
394 Self { impls }
395 }
396}
397
398#[cfg(test)]
399mod tests {
400 use super::*;
401
402 #[test]
403 fn test_primitive_impls() {
404 let cache = StdImplCache::new();
405
406 assert!(cache.has_impl("i32", "Clone"));
408 assert!(cache.has_impl("i32", "Copy"));
409 assert!(cache.has_impl("i32", "Debug"));
410 assert!(cache.has_impl("i32", "Default"));
411 assert!(cache.has_impl("i32", "Eq"));
412 assert!(cache.has_impl("i32", "Hash"));
413
414 assert!(cache.has_impl("f64", "Clone"));
416 assert!(cache.has_impl("f64", "PartialEq"));
417 assert!(!cache.has_impl("f64", "Eq"));
418 assert!(!cache.has_impl("f64", "Hash"));
419 }
420
421 #[test]
422 fn test_std_type_impls() {
423 let cache = StdImplCache::new();
424
425 assert!(cache.has_impl("String", "Clone"));
426 assert!(cache.has_impl("String", "Default"));
427 assert!(cache.has_impl("Vec", "Clone"));
428 assert!(cache.has_impl("HashMap", "Default"));
429
430 assert!(cache.has_impl("Rc", "Clone"));
432 assert!(!cache.has_impl("Rc", "Send"));
433 }
434
435 #[test]
436 fn test_normalized_lookup() {
437 let cache = StdImplCache::new();
438
439 assert!(cache.has_impl("std::string::String", "Clone"));
441 assert!(cache.has_impl("std::vec::Vec", "Default"));
442 }
443
444 #[test]
445 fn test_is_primitive() {
446 let cache = StdImplCache::new();
447
448 assert!(cache.is_primitive("i32"));
449 assert!(cache.is_primitive("f64"));
450 assert!(cache.is_primitive("bool"));
451 assert!(!cache.is_primitive("String"));
452 assert!(!cache.is_primitive("Vec"));
453 }
454
455 #[test]
456 fn test_traits_for() {
457 let cache = StdImplCache::new();
458
459 let bool_traits = cache.traits_for("bool");
460 assert!(bool_traits.contains(&"Clone"));
461 assert!(bool_traits.contains(&"Copy"));
462 assert!(bool_traits.contains(&"Eq"));
463 }
464}