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_checkable_derive(&self, trait_name: &str) -> bool {
53 let short = trait_name.rsplit("::").next().unwrap_or(trait_name);
54 matches!(
55 short,
56 "Clone"
57 | "Copy"
58 | "Debug"
59 | "Default"
60 | "PartialEq"
61 | "Eq"
62 | "PartialOrd"
63 | "Ord"
64 | "Hash"
65 )
66 }
67
68 pub fn is_primitive(&self, type_name: &str) -> bool {
70 matches!(
71 type_name,
72 "i8" | "i16"
73 | "i32"
74 | "i64"
75 | "i128"
76 | "isize"
77 | "u8"
78 | "u16"
79 | "u32"
80 | "u64"
81 | "u128"
82 | "usize"
83 | "f32"
84 | "f64"
85 | "bool"
86 | "char"
87 | "()"
88 | "str"
89 )
90 }
91
92 pub fn is_std_container(&self, type_name: &str) -> bool {
94 let short = type_name.rsplit("::").next().unwrap_or(type_name);
95 matches!(
96 short,
97 "Vec"
98 | "String"
99 | "Option"
100 | "Result"
101 | "Box"
102 | "Rc"
103 | "Arc"
104 | "Cell"
105 | "RefCell"
106 | "HashMap"
107 | "HashSet"
108 | "BTreeMap"
109 | "BTreeSet"
110 | "VecDeque"
111 | "LinkedList"
112 | "BinaryHeap"
113 | "PathBuf"
114 | "OsString"
115 | "Cow"
116 )
117 }
118
119 pub fn traits_for(&self, type_name: &str) -> Vec<&'static str> {
121 let short = type_name.rsplit("::").next().unwrap_or(type_name);
122 self.impls
123 .iter()
124 .filter(|(t, _)| *t == short)
125 .map(|(_, tr)| *tr)
126 .collect()
127 }
128}
129
130impl Default for StdImplCache {
131 fn default() -> Self {
132 let mut impls = HashSet::new();
133
134 for prim in ["i8", "i16", "i32", "i64", "i128", "isize"] {
137 impls.insert((prim, "Clone"));
138 impls.insert((prim, "Copy"));
139 impls.insert((prim, "Debug"));
140 impls.insert((prim, "Default"));
141 impls.insert((prim, "PartialEq"));
142 impls.insert((prim, "Eq"));
143 impls.insert((prim, "PartialOrd"));
144 impls.insert((prim, "Ord"));
145 impls.insert((prim, "Hash"));
146 impls.insert((prim, "Send"));
147 impls.insert((prim, "Sync"));
148 }
149
150 for prim in ["u8", "u16", "u32", "u64", "u128", "usize"] {
152 impls.insert((prim, "Clone"));
153 impls.insert((prim, "Copy"));
154 impls.insert((prim, "Debug"));
155 impls.insert((prim, "Default"));
156 impls.insert((prim, "PartialEq"));
157 impls.insert((prim, "Eq"));
158 impls.insert((prim, "PartialOrd"));
159 impls.insert((prim, "Ord"));
160 impls.insert((prim, "Hash"));
161 impls.insert((prim, "Send"));
162 impls.insert((prim, "Sync"));
163 }
164
165 for prim in ["f32", "f64"] {
167 impls.insert((prim, "Clone"));
168 impls.insert((prim, "Copy"));
169 impls.insert((prim, "Debug"));
170 impls.insert((prim, "Default"));
171 impls.insert((prim, "PartialEq"));
172 impls.insert((prim, "PartialOrd"));
173 impls.insert((prim, "Send"));
174 impls.insert((prim, "Sync"));
175 }
176
177 impls.insert(("bool", "Clone"));
179 impls.insert(("bool", "Copy"));
180 impls.insert(("bool", "Debug"));
181 impls.insert(("bool", "Default"));
182 impls.insert(("bool", "PartialEq"));
183 impls.insert(("bool", "Eq"));
184 impls.insert(("bool", "PartialOrd"));
185 impls.insert(("bool", "Ord"));
186 impls.insert(("bool", "Hash"));
187 impls.insert(("bool", "Send"));
188 impls.insert(("bool", "Sync"));
189
190 impls.insert(("char", "Clone"));
192 impls.insert(("char", "Copy"));
193 impls.insert(("char", "Debug"));
194 impls.insert(("char", "PartialEq"));
195 impls.insert(("char", "Eq"));
196 impls.insert(("char", "PartialOrd"));
197 impls.insert(("char", "Ord"));
198 impls.insert(("char", "Hash"));
199 impls.insert(("char", "Send"));
200 impls.insert(("char", "Sync"));
201
202 impls.insert(("()", "Clone"));
204 impls.insert(("()", "Copy"));
205 impls.insert(("()", "Debug"));
206 impls.insert(("()", "Default"));
207 impls.insert(("()", "PartialEq"));
208 impls.insert(("()", "Eq"));
209 impls.insert(("()", "PartialOrd"));
210 impls.insert(("()", "Ord"));
211 impls.insert(("()", "Hash"));
212 impls.insert(("()", "Send"));
213 impls.insert(("()", "Sync"));
214
215 for tr in [
223 "Clone",
224 "Copy",
225 "Debug",
226 "Default",
227 "PartialEq",
228 "Eq",
229 "PartialOrd",
230 "Ord",
231 "Hash",
232 "Send",
233 "Sync",
234 ] {
235 impls.insert(("str", tr));
236 }
237
238 impls.insert(("String", "Clone"));
240 impls.insert(("String", "Debug"));
241 impls.insert(("String", "Default"));
242 impls.insert(("String", "PartialEq"));
243 impls.insert(("String", "Eq"));
244 impls.insert(("String", "PartialOrd"));
245 impls.insert(("String", "Ord"));
246 impls.insert(("String", "Hash"));
247 impls.insert(("String", "Send"));
248 impls.insert(("String", "Sync"));
249
250 impls.insert(("Vec", "Clone"));
252 impls.insert(("Vec", "Debug"));
253 impls.insert(("Vec", "Default"));
254 impls.insert(("Vec", "PartialEq"));
255 impls.insert(("Vec", "Eq"));
256 impls.insert(("Vec", "Hash"));
257 impls.insert(("Vec", "Send"));
258 impls.insert(("Vec", "Sync"));
259
260 impls.insert(("Option", "Clone"));
262 impls.insert(("Option", "Copy"));
263 impls.insert(("Option", "Debug"));
264 impls.insert(("Option", "Default"));
265 impls.insert(("Option", "PartialEq"));
266 impls.insert(("Option", "Eq"));
267 impls.insert(("Option", "PartialOrd"));
268 impls.insert(("Option", "Ord"));
269 impls.insert(("Option", "Hash"));
270 impls.insert(("Option", "Send"));
271 impls.insert(("Option", "Sync"));
272
273 impls.insert(("Result", "Clone"));
275 impls.insert(("Result", "Copy"));
276 impls.insert(("Result", "Debug"));
277 impls.insert(("Result", "PartialEq"));
278 impls.insert(("Result", "Eq"));
279 impls.insert(("Result", "PartialOrd"));
280 impls.insert(("Result", "Ord"));
281 impls.insert(("Result", "Hash"));
282 impls.insert(("Result", "Send"));
283 impls.insert(("Result", "Sync"));
284
285 impls.insert(("Box", "Clone"));
287 impls.insert(("Box", "Debug"));
288 impls.insert(("Box", "Default"));
289 impls.insert(("Box", "PartialEq"));
290 impls.insert(("Box", "Eq"));
291 impls.insert(("Box", "PartialOrd"));
292 impls.insert(("Box", "Ord"));
293 impls.insert(("Box", "Hash"));
294 impls.insert(("Box", "Send"));
295 impls.insert(("Box", "Sync"));
296
297 impls.insert(("Rc", "Clone"));
299 impls.insert(("Rc", "Debug"));
300 impls.insert(("Rc", "Default"));
301 impls.insert(("Rc", "PartialEq"));
302 impls.insert(("Rc", "Eq"));
303 impls.insert(("Rc", "PartialOrd"));
304 impls.insert(("Rc", "Ord"));
305 impls.insert(("Rc", "Hash"));
306
307 impls.insert(("Arc", "Clone"));
309 impls.insert(("Arc", "Debug"));
310 impls.insert(("Arc", "Default"));
311 impls.insert(("Arc", "PartialEq"));
312 impls.insert(("Arc", "Eq"));
313 impls.insert(("Arc", "PartialOrd"));
314 impls.insert(("Arc", "Ord"));
315 impls.insert(("Arc", "Hash"));
316 impls.insert(("Arc", "Send"));
317 impls.insert(("Arc", "Sync"));
318
319 impls.insert(("HashMap", "Clone"));
321 impls.insert(("HashMap", "Debug"));
322 impls.insert(("HashMap", "Default"));
323 impls.insert(("HashMap", "PartialEq"));
324 impls.insert(("HashMap", "Eq"));
325 impls.insert(("HashMap", "Send"));
326 impls.insert(("HashMap", "Sync"));
327
328 impls.insert(("HashSet", "Clone"));
330 impls.insert(("HashSet", "Debug"));
331 impls.insert(("HashSet", "Default"));
332 impls.insert(("HashSet", "PartialEq"));
333 impls.insert(("HashSet", "Eq"));
334 impls.insert(("HashSet", "Send"));
335 impls.insert(("HashSet", "Sync"));
336
337 impls.insert(("BTreeMap", "Clone"));
339 impls.insert(("BTreeMap", "Debug"));
340 impls.insert(("BTreeMap", "Default"));
341 impls.insert(("BTreeMap", "PartialEq"));
342 impls.insert(("BTreeMap", "Eq"));
343 impls.insert(("BTreeMap", "PartialOrd"));
344 impls.insert(("BTreeMap", "Ord"));
345 impls.insert(("BTreeMap", "Send"));
346 impls.insert(("BTreeMap", "Sync"));
347
348 impls.insert(("BTreeSet", "Clone"));
350 impls.insert(("BTreeSet", "Debug"));
351 impls.insert(("BTreeSet", "Default"));
352 impls.insert(("BTreeSet", "PartialEq"));
353 impls.insert(("BTreeSet", "Eq"));
354 impls.insert(("BTreeSet", "PartialOrd"));
355 impls.insert(("BTreeSet", "Ord"));
356 impls.insert(("BTreeSet", "Hash"));
357 impls.insert(("BTreeSet", "Send"));
358 impls.insert(("BTreeSet", "Sync"));
359
360 impls.insert(("PathBuf", "Clone"));
362 impls.insert(("PathBuf", "Debug"));
363 impls.insert(("PathBuf", "Default"));
364 impls.insert(("PathBuf", "PartialEq"));
365 impls.insert(("PathBuf", "Eq"));
366 impls.insert(("PathBuf", "PartialOrd"));
367 impls.insert(("PathBuf", "Ord"));
368 impls.insert(("PathBuf", "Hash"));
369 impls.insert(("PathBuf", "Send"));
370 impls.insert(("PathBuf", "Sync"));
371
372 impls.insert(("OsString", "Clone"));
374 impls.insert(("OsString", "Debug"));
375 impls.insert(("OsString", "Default"));
376 impls.insert(("OsString", "PartialEq"));
377 impls.insert(("OsString", "Eq"));
378 impls.insert(("OsString", "PartialOrd"));
379 impls.insert(("OsString", "Ord"));
380 impls.insert(("OsString", "Hash"));
381 impls.insert(("OsString", "Send"));
382 impls.insert(("OsString", "Sync"));
383
384 impls.insert(("Cell", "Clone"));
386 impls.insert(("Cell", "Copy"));
387 impls.insert(("Cell", "Debug"));
388 impls.insert(("Cell", "Default"));
389 impls.insert(("Cell", "PartialEq"));
390 impls.insert(("Cell", "Eq"));
391 impls.insert(("Cell", "PartialOrd"));
392 impls.insert(("Cell", "Ord"));
393 impls.insert(("Cell", "Send"));
394
395 impls.insert(("RefCell", "Clone"));
397 impls.insert(("RefCell", "Debug"));
398 impls.insert(("RefCell", "Default"));
399 impls.insert(("RefCell", "PartialEq"));
400 impls.insert(("RefCell", "Eq"));
401 impls.insert(("RefCell", "PartialOrd"));
402 impls.insert(("RefCell", "Ord"));
403 impls.insert(("RefCell", "Send"));
404
405 impls.insert(("Cow", "Clone"));
407 impls.insert(("Cow", "Debug"));
408 impls.insert(("Cow", "Default"));
409 impls.insert(("Cow", "PartialEq"));
410 impls.insert(("Cow", "Eq"));
411 impls.insert(("Cow", "PartialOrd"));
412 impls.insert(("Cow", "Ord"));
413 impls.insert(("Cow", "Hash"));
414 impls.insert(("Cow", "Send"));
415 impls.insert(("Cow", "Sync"));
416
417 impls.insert(("VecDeque", "Clone"));
419 impls.insert(("VecDeque", "Debug"));
420 impls.insert(("VecDeque", "Default"));
421 impls.insert(("VecDeque", "PartialEq"));
422 impls.insert(("VecDeque", "Eq"));
423 impls.insert(("VecDeque", "PartialOrd"));
424 impls.insert(("VecDeque", "Ord"));
425 impls.insert(("VecDeque", "Hash"));
426 impls.insert(("VecDeque", "Send"));
427 impls.insert(("VecDeque", "Sync"));
428
429 impls.insert(("PhantomData", "Clone"));
431 impls.insert(("PhantomData", "Copy"));
432 impls.insert(("PhantomData", "Debug"));
433 impls.insert(("PhantomData", "Default"));
434 impls.insert(("PhantomData", "PartialEq"));
435 impls.insert(("PhantomData", "Eq"));
436 impls.insert(("PhantomData", "PartialOrd"));
437 impls.insert(("PhantomData", "Ord"));
438 impls.insert(("PhantomData", "Hash"));
439 impls.insert(("PhantomData", "Send"));
440 impls.insert(("PhantomData", "Sync"));
441
442 Self { impls }
443 }
444}
445
446#[cfg(test)]
447mod tests {
448 use super::*;
449
450 #[test]
451 fn test_primitive_impls() {
452 let cache = StdImplCache::new();
453
454 assert!(cache.has_impl("i32", "Clone"));
456 assert!(cache.has_impl("i32", "Copy"));
457 assert!(cache.has_impl("i32", "Debug"));
458 assert!(cache.has_impl("i32", "Default"));
459 assert!(cache.has_impl("i32", "Eq"));
460 assert!(cache.has_impl("i32", "Hash"));
461
462 assert!(cache.has_impl("f64", "Clone"));
464 assert!(cache.has_impl("f64", "PartialEq"));
465 assert!(!cache.has_impl("f64", "Eq"));
466 assert!(!cache.has_impl("f64", "Hash"));
467 }
468
469 #[test]
470 fn test_std_type_impls() {
471 let cache = StdImplCache::new();
472
473 assert!(cache.has_impl("String", "Clone"));
474 assert!(cache.has_impl("String", "Default"));
475 assert!(cache.has_impl("Vec", "Clone"));
476 assert!(cache.has_impl("HashMap", "Default"));
477
478 assert!(cache.has_impl("Rc", "Clone"));
480 assert!(!cache.has_impl("Rc", "Send"));
481 }
482
483 #[test]
484 fn test_normalized_lookup() {
485 let cache = StdImplCache::new();
486
487 assert!(cache.has_impl("std::string::String", "Clone"));
489 assert!(cache.has_impl("std::vec::Vec", "Default"));
490 }
491
492 #[test]
493 fn test_is_primitive() {
494 let cache = StdImplCache::new();
495
496 assert!(cache.is_primitive("i32"));
497 assert!(cache.is_primitive("f64"));
498 assert!(cache.is_primitive("bool"));
499 assert!(!cache.is_primitive("String"));
500 assert!(!cache.is_primitive("Vec"));
501 }
502
503 #[test]
504 fn test_traits_for() {
505 let cache = StdImplCache::new();
506
507 let bool_traits = cache.traits_for("bool");
508 assert!(bool_traits.contains(&"Clone"));
509 assert!(bool_traits.contains(&"Copy"));
510 assert!(bool_traits.contains(&"Eq"));
511 }
512}