1use generalize::Generalizations;
43use indexmap::{IndexMap, IndexSet};
44use itertools::Itertools as _;
45use proc_macro::TokenStream;
46use proc_macro_error2::{OptionExt, abort, proc_macro_error};
47use proc_macro2::TokenStream as TokenStream2;
48use quote::{format_ident, quote};
49use syn::{
50 ItemImpl, ItemTrait, Token,
51 parse::{Parse, ParseStream},
52 parse_macro_input, parse_quote,
53 punctuated::Punctuated,
54 visit::{Visit, visit_trait_bound},
55 visit_mut::VisitMut,
56};
57
58use crate::{
59 disjoint::traitize_inherent_impl,
60 generalize::{Generalize, GenericParam, Params, Sizedness, as_generics},
61 main_trait::is_remote,
62 validate::validate_impl_syntax,
63};
64
65mod disjoint;
66mod generalize;
67mod helper_trait;
68mod main_trait;
69mod normalize;
70mod validate;
71
72type TraitBoundIdent = (Bounded, TraitBound);
75
76type AssocBindingPayload = syn::Type;
79
80type AssocBindings = IndexMap<
86 syn::Ident,
87 (
88 Option<AssocBindingPayload>,
89 Vec<Option<AssocBindingPayload>>,
90 ),
91>;
92
93type AssocBindingsBuilder =
95 IndexMap<syn::Ident, (AssocBindingPayload, Vec<Option<AssocBindingPayload>>)>;
96
97#[derive(Debug, Clone)]
99struct TraitBounds(IndexMap<TraitBoundIdent, (Vec<TraitBoundIdent>, AssocBindings)>);
100
101#[derive(Debug, Clone)]
103struct TraitBoundsBuilder(IndexMap<TraitBoundIdent, (Vec<TraitBoundIdent>, AssocBindingsBuilder)>);
104
105#[derive(Debug, Clone, PartialEq, Eq, Hash)]
117#[repr(transparent)]
118struct Bounded(syn::Type);
119
120#[derive(Debug, Clone, PartialEq, Eq, Hash)]
122#[repr(transparent)]
123struct TraitBound(syn::TraitBound);
124
125#[derive(Debug, Clone, PartialEq, Eq, Hash)]
129struct ImplGroupId {
130 trait_: Option<syn::Path>,
131 self_ty: syn::Type,
132}
133
134#[derive(Debug, Clone, Default)]
136struct ImplItemsDesc {
137 fns: IndexMap<syn::Ident, syn::Signature>,
139 assoc_types: IndexSet<syn::Ident>,
141 assoc_consts: IndexMap<syn::Ident, syn::Type>,
143}
144
145#[derive(Debug, Clone)]
147struct ItemImplDesc {
148 id: ImplGroupId,
150 params: Params,
152 trait_bounds: IndexMap<TraitBoundIdent, IndexMap<syn::Ident, AssocBindingPayload>>,
154 items: Option<ImplItemsDesc>,
156}
157
158#[derive(Debug, Clone)]
160struct ImplGroupBuilder {
161 id: ImplGroupId,
163 lifetimes: Vec<syn::LifetimeParam>,
165 params: Params,
167 trait_bounds: TraitBoundsBuilder,
169 items: Option<ImplItemsDesc>,
171 subgroups: Vec<(Self, Vec<usize>, TraitBoundsBuilder)>,
173}
174
175#[derive(Debug, Clone)]
177struct ImplGroup {
178 id: ImplGroupId,
180 params: Punctuated<syn::GenericParam, Token![,]>,
182 trait_bounds: TraitBounds,
184 items: Option<ImplItemsDesc>,
186
187 impls: Vec<(syn::ItemImpl, Vec<syn::GenericArgument>)>,
189
190 subgroups: Vec<(ImplGroup, Vec<AssocBindingPayload>)>,
201}
202
203#[derive(Debug, Clone)]
205struct ImplGroups {
206 trait_: Option<ItemTrait>,
208 impl_groups: Vec<ImplGroup>,
211}
212
213struct ItemImplDescVisitor {
214 curr_bounded_ty: Option<Bounded>,
216 curr_trait_bound: Option<TraitBound>,
218
219 impl_desc: ItemImplDesc,
221}
222
223impl ImplGroupId {
224 fn is_inherent(&self) -> bool {
225 self.trait_.is_none()
226 }
227}
228
229impl From<&syn::TypeParam> for Bounded {
230 fn from(source: &syn::TypeParam) -> Self {
231 let ident = &source.ident;
232 Self(parse_quote!(#ident))
233 }
234}
235
236impl From<syn::Type> for Bounded {
237 fn from(source: syn::Type) -> Self {
238 Self(source.clone())
239 }
240}
241
242impl From<syn::TraitBound> for TraitBound {
243 fn from(mut source: syn::TraitBound) -> Self {
244 source.lifetimes = Default::default();
245
246 source
247 .path
248 .segments
249 .last_mut()
250 .into_iter()
251 .for_each(|segment| {
252 if let syn::PathArguments::AngleBracketed(bracketed) = &mut segment.arguments {
253 bracketed.args = core::mem::take(&mut bracketed.args)
254 .into_iter()
255 .filter(|arg| {
256 matches!(
257 arg,
258 syn::GenericArgument::Lifetime(_)
259 | syn::GenericArgument::Type(_)
260 | syn::GenericArgument::Const(_)
261 )
262 })
263 .collect();
264
265 if bracketed.args.is_empty() {
266 segment.arguments = syn::PathArguments::None;
267 }
268 }
269 });
270
271 Self(source)
272 }
273}
274
275impl syn::parse::Parse for Bounded {
276 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
277 Ok(Self::from(input.parse::<syn::Type>()?))
278 }
279}
280
281impl syn::parse::Parse for TraitBound {
282 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
283 Ok(Self::from(input.parse::<syn::TraitBound>()?))
284 }
285}
286
287impl quote::ToTokens for Bounded {
288 fn to_tokens(&self, tokens: &mut TokenStream2) {
289 self.0.to_tokens(tokens);
290 }
291}
292
293impl quote::ToTokens for TraitBound {
294 fn to_tokens(&self, tokens: &mut TokenStream2) {
295 self.0.to_tokens(tokens);
296 }
297}
298
299impl quote::ToTokens for ImplGroupId {
300 fn to_tokens(&self, tokens: &mut TokenStream2) {
301 quote!(impl).to_tokens(tokens);
302
303 if let Some(trait_) = &self.trait_ {
304 trait_.to_tokens(tokens);
305 quote!(for).to_tokens(tokens);
306 }
307
308 self.self_ty.to_tokens(tokens);
309 }
310}
311
312struct Dsu {
314 parent: Vec<usize>,
315}
316
317impl Dsu {
318 fn new(n: usize) -> Self {
319 Self {
320 parent: (0..n).collect(),
321 }
322 }
323
324 fn find(&mut self, x: usize) -> usize {
325 if self.parent[x] != x {
326 let root = self.find(self.parent[x]);
327 self.parent[x] = root;
328 }
329
330 self.parent[x]
331 }
332
333 fn union(&mut self, a: usize, b: usize) {
334 let ra = self.find(a);
335 let rb = self.find(b);
336
337 if ra != rb {
338 self.parent[rb] = ra;
339 }
340 }
341
342 fn groups(mut self) -> Vec<Vec<usize>> {
343 let mut map: IndexMap<_, Vec<_>> = IndexMap::new();
344
345 for i in 0..self.parent.len() {
346 let root = self.find(i);
347 map.entry(root).or_default().push(i);
348 }
349
350 map.into_values().collect()
351 }
352}
353
354impl TraitBoundsBuilder {
355 fn retain_impl_by_pos(&mut self, keep: &[usize]) -> Self {
360 let keep: IndexSet<_> = keep.iter().copied().collect();
361
362 let mut removed = IndexMap::new();
363 for (trait_ident, (orig, bindings)) in self.0.iter_mut() {
364 let mut removed_bindings = IndexMap::new();
365
366 let (kept_rows, removed_rows) = core::mem::take(orig)
367 .into_iter()
368 .enumerate()
369 .partition::<Vec<_>, _>(|(pos, _)| keep.contains(pos));
370
371 bindings
372 .iter_mut()
373 .for_each(|(ident, (payload, payloads))| {
374 let (kept_payloads, removed_payloads) = core::mem::take(payloads)
375 .into_iter()
376 .enumerate()
377 .partition::<Vec<_>, _>(|(pos, _)| keep.contains(pos));
378
379 *payloads = kept_payloads
380 .into_iter()
381 .map(|(_, binding)| binding)
382 .collect();
383
384 let removed_payloads = removed_payloads
385 .into_iter()
386 .map(|(_, binding)| binding)
387 .collect::<Vec<_>>();
388
389 if !removed_payloads.is_empty() {
390 removed_bindings.insert(ident.clone(), (payload.clone(), removed_payloads));
391 }
392 });
393
394 if !removed_rows.is_empty() {
395 removed.insert(
396 trait_ident.clone(),
397 (
398 removed_rows.into_iter().map(|(_, row)| row).collect(),
399 removed_bindings,
400 ),
401 );
402 }
403
404 *orig = kept_rows.into_iter().map(|(_, row)| row).collect();
405 }
406
407 Self(removed)
408 }
409
410 fn build(self, impl_group_id: &ImplGroupId, params: &mut Params) -> TraitBounds {
416 struct ParamsPartitioner<'a>(IndexSet<&'a syn::Ident>, IndexSet<&'a syn::Ident>);
417 struct UnconstrainedParamFinder<'a>(IndexSet<&'a syn::Ident>, IndexSet<&'a syn::Ident>);
418
419 struct RequiredPayloadDetector<'a> {
420 unconstrained_params: &'a mut IndexSet<syn::Ident>,
421 required_params: IndexSet<&'a syn::Ident>,
422 all_params: &'a IndexSet<syn::Ident>,
423
424 is_required: bool,
425 }
426
427 impl<'a> Visit<'a> for ParamsPartitioner<'a> {
428 fn visit_path(&mut self, node: &'a syn::Path) {
429 let first_seg = node.segments.first().unwrap();
430
431 if self.0.swap_remove(&first_seg.ident) {
432 self.1.insert(&first_seg.ident);
433 } else {
434 syn::visit::visit_path(self, node);
435 }
436 }
437 }
438
439 impl<'a> Visit<'a> for UnconstrainedParamFinder<'a> {
440 fn visit_path(&mut self, node: &'a syn::Path) {
441 let first_seg = node.segments.first().unwrap();
442
443 if self.0.contains(&first_seg.ident) {
444 self.1.insert(&first_seg.ident);
445 } else {
446 syn::visit::visit_path(self, node);
447 }
448 }
449 }
450
451 impl<'a> Visit<'a> for RequiredPayloadDetector<'a> {
452 fn visit_path(&mut self, node: &'a syn::Path) {
453 let first_seg = node.segments.first().unwrap();
454
455 let ident = &first_seg.ident;
456 if self.unconstrained_params.swap_remove(ident) {
457 self.is_required = true;
458 } else if self.all_params.contains(ident) {
459 self.required_params.insert(ident);
460 } else {
461 syn::visit::visit_path(self, node);
462 }
463 }
464 }
465
466 let mut params_partitioner = ParamsPartitioner(
467 params.iter().map(|(ident, _)| ident).collect(),
468 IndexSet::new(),
469 );
470
471 params_partitioner.visit_type(&impl_group_id.self_ty);
472 if let Some(trait_) = &impl_group_id.trait_ {
473 params_partitioner.visit_path(trait_);
474 }
475
476 let (maybe_redundant_params, mut unconstrained_params) = if impl_group_id.is_inherent() {
477 let unconstrained_params = params_partitioner.0.into_iter().cloned().collect();
478
479 (IndexSet::new(), unconstrained_params)
480 } else {
481 let mut unconstrained_param_finder =
482 UnconstrainedParamFinder(params_partitioner.0, IndexSet::new());
483
484 for (bounded, trait_bound) in self.0.keys() {
485 unconstrained_param_finder.visit_type(&bounded.0);
486 unconstrained_param_finder.visit_trait_bound(&trait_bound.0);
487 }
488
489 let maybe_redundant_params = unconstrained_param_finder
490 .0
491 .into_iter()
492 .cloned()
493 .collect::<IndexSet<_>>();
494 let unconstrained_params = unconstrained_param_finder
495 .1
496 .into_iter()
497 .cloned()
498 .collect::<IndexSet<_>>();
499
500 (maybe_redundant_params, unconstrained_params)
501 };
502
503 let mut required_params = params_partitioner
504 .1
505 .into_iter()
506 .cloned()
507 .chain(unconstrained_params.clone())
508 .collect::<IndexSet<_>>();
509
510 let trait_bounds = self
511 .0
512 .into_iter()
513 .map(|(bound_id, (orig_idents, bindings))| {
514 let bindings = bindings
515 .into_iter()
516 .map(|(ident, (payload, payloads))| {
517 let mut required_payload_detector = RequiredPayloadDetector {
518 unconstrained_params: &mut unconstrained_params,
519 all_params: &maybe_redundant_params,
520 required_params: IndexSet::new(),
521
522 is_required: false,
523 };
524
525 required_payload_detector.visit_type(&payload);
526 let payload = if required_payload_detector.is_required {
527 required_params.extend(
528 required_payload_detector
529 .required_params
530 .into_iter()
531 .cloned(),
532 );
533
534 Some(payload)
535 } else {
536 None
537 };
538
539 (ident, (payload, payloads))
540 })
541 .collect();
542
543 (bound_id, (orig_idents, bindings))
544 })
545 .collect();
546
547 *params = core::mem::take(params)
548 .into_iter()
549 .filter(|(ident, _)| required_params.contains(ident))
550 .collect();
551
552 TraitBounds(trait_bounds)
553 }
554}
555
556impl TraitBounds {
557 fn generalized_idents(&self) -> impl Iterator<Item = (&TraitBoundIdent, &syn::Ident)> {
558 self.0
559 .iter()
560 .flat_map(|(trait_bound_ident, (_, bindings))| {
561 bindings
562 .iter()
563 .map(move |(ident, _)| (trait_bound_ident, ident))
564 })
565 }
566
567 fn payloads(&self) -> impl Iterator<Item = syn::Type> {
568 self.0.iter().flat_map(|(bounded, (_, bindings))| {
569 bindings.iter().map(move |(ident, (payload, _))| {
570 payload
571 .clone()
572 .unwrap_or_else(|| assoc_binding_default(bounded, ident))
573 })
574 })
575 }
576}
577
578impl ImplGroupBuilder {
579 fn new(impl_desc: &ItemImplDesc) -> Self {
580 let mut subs = Default::default();
581
582 let generalized_id = impl_desc
583 .id
584 .generalize(
585 &impl_desc.id,
586 &impl_desc.params,
587 &impl_desc.params,
588 &mut subs,
589 )
590 .unwrap();
591
592 for (assoc_ty1, assoc_ty2) in impl_desc
593 .trait_bounds
594 .values()
595 .zip_eq(impl_desc.trait_bounds.values())
596 .flat_map(|(group_bound, other_bound)| {
597 group_bound.values().zip_eq(other_bound.values())
598 })
599 {
600 let _ = assoc_ty1
601 .generalize(assoc_ty2, &impl_desc.params, &impl_desc.params, &mut subs)
602 .unwrap();
603 }
604
605 let group_bounds = impl_desc
606 .trait_bounds
607 .iter()
608 .zip_eq(&impl_desc.trait_bounds)
609 .map(
610 |((group_bound_id, group_bound), (other_bound_id, other_bound))| {
611 let group_bound_id = group_bound_id
612 .generalize(
613 other_bound_id,
614 &impl_desc.params,
615 &impl_desc.params,
616 &mut subs,
617 )
618 .unwrap();
619
620 let group_bound = group_bound
621 .iter()
622 .zip_eq(other_bound.iter())
623 .map(|((ident, group_payload), (_, other_payload))| {
624 let group_payload = group_payload
625 .generalize(
626 other_payload,
627 &impl_desc.params,
628 &impl_desc.params,
629 &mut subs,
630 )
631 .unwrap();
632
633 (
634 ident.clone(),
635 (group_payload, vec![Some(other_payload.clone())]),
636 )
637 })
638 .collect();
639
640 (group_bound_id, (vec![other_bound_id.clone()], group_bound))
641 },
642 )
643 .collect();
644
645 let impl_items = impl_desc.id.is_inherent().then(|| {
646 impl_desc
647 .items
648 .as_ref()
649 .unwrap()
650 .generalize(
651 impl_desc.items.as_ref().unwrap(),
652 &impl_desc.params,
653 &impl_desc.params,
654 &subs,
655 )
656 .unwrap()
657 });
658
659 let (lifetimes, params) = subs.build_params();
660
661 Self {
662 id: generalized_id,
663 lifetimes,
664 params,
665 trait_bounds: TraitBoundsBuilder(group_bounds),
666 items: impl_items,
667 subgroups: vec![],
668 }
669 }
670
671 fn find_valid_trait_bound_groups<'a>(
672 &'a self,
673 other: &'a ItemImplDesc,
674 id_substitutions: &Generalizations<'a>,
675 implicit_params_container: &'a mut Vec<syn::Type>,
676 ) -> Option<(TraitBoundsBuilder, Generalizations<'a>)> {
677 let mut generalized_bounds = Vec::new();
678
679 for (group_bound_id, (rows, group_bound)) in &self.trait_bounds.0 {
680 let nrows = rows.len();
681
682 for (other_bound_id, other_bound) in &other.trait_bounds {
683 let mut bound_subs = id_substitutions.clone();
684 let mut all_payload_subs = id_substitutions.clone();
685
686 let mut new_group_bound = group_bound.clone();
687 let Some(_) = group_bound_id.generalize(
688 other_bound_id,
689 &self.params,
690 &other.params,
691 &mut bound_subs,
692 ) else {
693 continue;
694 };
695
696 for (ident, payload) in other_bound
697 .iter()
698 .filter(|(ident, _)| !group_bound.contains_key(*ident))
699 {
700 let payloads = core::iter::repeat_n(None, nrows);
701 new_group_bound.insert(ident.clone(), (payload.clone(), payloads.collect()));
702 }
703 let new_group_bound = new_group_bound
704 .into_iter()
705 .filter_map(|(ident, (_, payloads))| {
706 let generalized_payload = group_bound
707 .get(&ident)
708 .map(|(generalized_payload, _)| generalized_payload)
709 .or_else(|| other_bound.get(&ident))
710 .unwrap();
711
712 let payload = if let Some(payload) = other_bound.get(&ident) {
713 let mut curr_payload_subs = all_payload_subs.clone();
714
715 let _ = generalized_payload.generalize(
716 payload,
717 &self.params,
718 &other.params,
719 &mut curr_payload_subs,
720 )?;
721
722 all_payload_subs = curr_payload_subs;
723 Some(payload)
724 } else {
725 None
726 };
727
728 let mut payloads = payloads.clone();
729 payloads.push(payload.cloned());
730
731 Some((ident, (generalized_payload, payload, payloads)))
732 })
733 .collect::<IndexMap<_, _>>();
734
735 let bound_subs_diff = bound_subs.difference(id_substitutions);
736 let payload_subs_diff = all_payload_subs.difference(id_substitutions);
737
738 generalized_bounds.push((
739 group_bound_id,
740 other_bound_id,
741 new_group_bound,
742 bound_subs_diff,
743 payload_subs_diff,
744 ));
745 }
746 }
747
748 let mut subs = id_substitutions.clone();
751 let mut result = Vec::new();
752
753 loop {
754 let ready: Vec<_> = generalized_bounds
755 .iter()
756 .enumerate()
757 .filter_map(|(i, (_, _, _, bound_subs, _))| {
758 bound_subs.difference(&subs).is_empty().then_some(i)
759 })
760 .collect();
761
762 if ready.is_empty() {
763 if result.is_empty() {
764 return None;
765 }
766
767 break;
768 }
769
770 for idx in ready.into_iter().rev() {
771 let (group_bound_id, other_bound_id, bound, _, payload_subs) =
772 generalized_bounds.swap_remove(idx);
773
774 result.push((group_bound_id, other_bound_id, bound));
775 subs = subs.unify(payload_subs);
776 }
777 }
778
779 *implicit_params_container = result
780 .iter()
781 .flat_map(|(_, _, bound)| {
782 bound
783 .values()
784 .filter(|(_, other_payload, _)| other_payload.is_none())
785 })
786 .enumerate()
787 .map(|(i, _)| {
788 let ident = format_ident!("_MŠČ{}", i);
789 parse_quote!(#ident)
790 })
791 .collect::<Vec<_>>();
792
793 let mut subs = id_substitutions.clone().unify(subs);
796
797 let mut implicit_params = implicit_params_container.iter();
798 let mut trait_bounds = IndexMap::new();
799 for (group_bound_id, other_bound_id, bound) in result {
800 let generalized_bound_id = group_bound_id
801 .generalize(other_bound_id, &self.params, &other.params, &mut subs)
802 .unwrap();
803
804 let mut generalized_bound = IndexMap::new();
805 for (ident, (generalized_payload, other_payload, payloads)) in bound {
806 let other_payload =
807 other_payload.unwrap_or_else(|| implicit_params.next().unwrap());
808
809 let generalized_payload = generalized_payload
810 .generalize(other_payload, &self.params, &other.params, &mut subs)
811 .unwrap();
812
813 generalized_bound.insert(ident, (generalized_payload, payloads));
814 }
815
816 let mut bounds = self.trait_bounds.0[group_bound_id].0.clone();
817 bounds.push(other_bound_id.clone());
818 trait_bounds.insert(generalized_bound_id, (bounds, generalized_bound));
819 }
820
821 Some((TraitBoundsBuilder(trait_bounds), subs))
822 }
823
824 fn intersection(&self, other: &ItemImplDesc) -> Option<Self> {
825 let mut implicit_params_container = vec![];
826 let mut id_subs = Default::default();
827
828 let generalized_id =
829 self.id
830 .generalize(&other.id, &self.params, &other.params, &mut id_subs)?;
831
832 let (group, subs) =
833 self.find_valid_trait_bound_groups(other, &id_subs, &mut implicit_params_container)?;
834
835 let impl_items = if self.id.is_inherent() {
836 Some(self.items.as_ref().unwrap().generalize(
837 other.items.as_ref().unwrap(),
838 &self.params,
839 &other.params,
840 &subs,
841 )?)
842 } else {
843 None
844 };
845
846 let (lifetimes, params) = subs.build_params();
847
848 Some(Self {
849 id: generalized_id.clone(),
850 lifetimes,
851 params,
852 trait_bounds: group,
853 items: impl_items,
854 subgroups: vec![],
855 })
856 }
857}
858
859impl ImplGroups {
860 fn new(trait_: Option<ItemTrait>, impl_groups: Vec<ImplGroup>) -> Self {
861 if let Some(trait_) = &trait_ {
862 for ImplGroup { impls, .. } in &impl_groups {
863 validate::validate_trait_impls(trait_, impls.iter().map(|(impl_, _)| impl_));
864 }
865 } else {
866 for ImplGroup { impls, .. } in &impl_groups {
867 validate::validate_inherent_impls(impls.iter().map(|(impl_, _)| impl_));
868 }
869 }
870
871 Self {
872 trait_,
873 impl_groups,
874 }
875 }
876}
877
878fn compute_inherent_args(
879 builder: &ImplGroupBuilder,
880 impl_indices: &[usize],
881 all_descs: &[ItemImplDesc],
882) -> Vec<Vec<syn::GenericArgument>> {
883 if !builder.id.is_inherent() || impl_indices.len() <= 1 && builder.subgroups.is_empty() {
884 return Vec::new();
885 }
886
887 let Some((&_, (rows, _))) = builder.trait_bounds.0.get_index(0) else {
888 return Vec::new();
889 };
890
891 let group_impls = impl_indices
892 .iter()
893 .map(|&idx| &all_descs[idx])
894 .collect::<Vec<_>>();
895
896 let nrows = rows.len().min(group_impls.len());
897 if nrows == 0 {
898 return Vec::new();
899 }
900
901 let payloads = builder
902 .trait_bounds
903 .0
904 .values()
905 .flat_map(|(_, bindings)| bindings.values())
906 .collect::<Vec<_>>();
907
908 let mut args = Vec::with_capacity(nrows);
909 for row in 0..nrows {
910 let impl_desc = group_impls[row];
911 let mut subs = Generalizations::default();
912
913 if builder
914 .id
915 .generalize(&impl_desc.id, &builder.params, &impl_desc.params, &mut subs)
916 .is_none()
917 {
918 continue;
919 }
920
921 for (generalized_payload, payloads_vec) in &payloads {
922 if let Some(payload) = &payloads_vec[row] {
923 let _ = generalized_payload
924 .generalize(payload, &builder.params, &impl_desc.params, &mut subs)
925 .unwrap();
926 }
927 }
928
929 args.push(subs.generic_args().map(|(_, arg)| arg).collect::<Vec<_>>());
930 }
931
932 args
933}
934
935fn instantiate_impl_group(
936 builder: ImplGroupBuilder,
937 impl_indices: Vec<usize>,
938 all_impls: &mut [Option<ItemImpl>],
939 all_descs: &[ItemImplDesc],
940) -> ImplGroup {
941 let args = compute_inherent_args(&builder, &impl_indices, all_descs);
942
943 let ImplGroupBuilder {
944 id,
945 lifetimes,
946 mut params,
947 trait_bounds,
948 items,
949 subgroups,
950 } = builder;
951
952 let subgroups = subgroups
953 .into_iter()
954 .map(|(mut sub_builder, indices, overlapping_bounds)| {
955 let common_types = find_common_types(&overlapping_bounds, &sub_builder.trait_bounds);
956 remove_trait_bounds(&overlapping_bounds, &mut sub_builder);
957
958 (
959 instantiate_impl_group(sub_builder, indices, all_impls, all_descs),
960 common_types,
961 )
962 })
963 .collect::<Vec<_>>();
964
965 let trait_bounds = trait_bounds.build(&id, &mut params);
966 let params = lifetimes
967 .into_iter()
968 .map(syn::GenericParam::Lifetime)
969 .chain(as_generics(¶ms))
970 .collect();
971
972 let impl_items = impl_indices
973 .iter()
974 .map(|&idx| all_impls[idx].take().unwrap())
975 .collect::<Vec<_>>();
976
977 let impls = if id.is_inherent() && (impl_items.len() > 1 || !subgroups.is_empty()) {
978 impl_items.into_iter().zip_eq(args).collect()
979 } else {
980 impl_items
981 .into_iter()
982 .map(|impl_| (impl_, Vec::new()))
983 .collect()
984 };
985
986 ImplGroup {
987 id,
988 params,
989 trait_bounds,
990 items,
991 impls,
992 subgroups,
993 }
994}
995
996fn build_disjoint_impl_group(
997 trait_: Option<&ItemTrait>,
998 mut impl_group: ImplGroup,
999 group_idx: usize,
1000) -> (TokenStream2, Vec<ItemImpl>) {
1001 let mut helper_traits = Vec::new();
1002 let mut trait_impls = Vec::new();
1003 let mut item_impls = Vec::new();
1004 let mut subgroup_tokens = Vec::new();
1005
1006 if impl_group.impls.len() > 1 || !impl_group.subgroups.is_empty() {
1007 let helper_trait = helper_trait::generate(trait_, group_idx, &impl_group);
1008 helper_traits.push(helper_trait.clone());
1009
1010 if let Some(main_impl) = main_trait::generate_impl(trait_, group_idx, &impl_group) {
1011 trait_impls.push(main_impl);
1012 }
1013
1014 let mut dispatch_bindings_cnt: usize = impl_group
1015 .trait_bounds
1016 .0
1017 .iter()
1018 .map(|(_, bindings)| bindings.1.len())
1019 .sum();
1020
1021 let mut subgroup_trait = helper_trait;
1022 subgroup_trait.generics.params = subgroup_trait
1023 .generics
1024 .params
1025 .into_iter()
1026 .filter(|param| {
1027 if let syn::GenericParam::Type(_) = param
1028 && dispatch_bindings_cnt > 0
1029 {
1030 dispatch_bindings_cnt -= 1;
1031 return false;
1032 }
1033
1034 true
1035 })
1036 .collect();
1037
1038 let subgroup_impls = core::mem::take(&mut impl_group.subgroups);
1039 for (subgroup_idx, (mut subgroup, common_args)) in subgroup_impls.into_iter().enumerate() {
1040 let subgroup_trait_ident = &subgroup_trait.ident;
1041
1042 let is_trait_inherent = subgroup.id.is_inherent();
1043 if let Some(trait_) = &mut subgroup.id.trait_ {
1044 trait_.segments.last_mut().unwrap().ident = subgroup_trait_ident.clone();
1045
1046 subgroup.impls.iter_mut().for_each(|(impl_, _)| {
1047 impl_.trait_ = Some((None, trait_.clone(), Default::default()));
1048 })
1049 } else {
1050 let helper_trait_args = &subgroup.params;
1051
1052 subgroup.id.trait_ =
1053 Some(parse_quote! { #subgroup_trait_ident<#helper_trait_args> });
1054
1055 for (impl_, args) in &mut subgroup.impls {
1056 traitize_inherent_impl(args, impl_, &subgroup.id.self_ty);
1057 }
1058 }
1059
1060 let (tokens, mut subgroup_main_impls) =
1061 build_disjoint_impl_group(Some(&subgroup_trait), subgroup, subgroup_idx);
1062
1063 subgroup_tokens.push(tokens);
1064 subgroup_main_impls.iter_mut().for_each(|trait_impl| {
1065 let trait_path = &mut trait_impl.trait_.as_mut().unwrap().1;
1066 let last_seg = trait_path.segments.last_mut().unwrap();
1067
1068 prepend_args(&mut last_seg.arguments, &common_args);
1069
1070 if is_trait_inherent {
1071 match &mut last_seg.arguments {
1072 syn::PathArguments::None => {}
1073 syn::PathArguments::AngleBracketed(bracketed) => {
1074 let replace_at = bracketed.args.len() - common_args.len();
1075 let mut args = core::mem::take(&mut bracketed.args)
1076 .into_iter()
1077 .collect::<Vec<_>>();
1078
1079 args.splice(
1080 replace_at..,
1081 common_args.iter().cloned().map(syn::GenericArgument::Type),
1082 );
1083
1084 bracketed.args = args.into_iter().collect();
1085 }
1086 syn::PathArguments::Parenthesized(_) => {
1087 unreachable!("Not a valid trait name")
1088 }
1089 }
1090 }
1091 });
1092
1093 subgroup_tokens.extend(
1094 subgroup_main_impls
1095 .into_iter()
1096 .map(|trait_impl| quote!(#trait_impl)),
1097 );
1098 }
1099
1100 item_impls.extend(disjoint::generate(group_idx, impl_group));
1101 } else if let Some((main_impl, _)) = impl_group.impls.pop() {
1102 trait_impls.push(main_impl);
1103 }
1104
1105 let tokens = quote! {
1106 #( #helper_traits )*
1107 #( #item_impls )*
1108
1109 #( #subgroup_tokens )*
1110 };
1111
1112 (tokens, trait_impls)
1113}
1114
1115fn prepend_args<'a>(
1116 arguments: &mut syn::PathArguments,
1117 types: impl IntoIterator<Item = &'a syn::Type>,
1118) {
1119 let types = types.into_iter();
1120
1121 match arguments {
1122 syn::PathArguments::None => {
1123 let bracketed = parse_quote! { <#( #types ),*> };
1124 *arguments = syn::PathArguments::AngleBracketed(bracketed);
1125 }
1126 syn::PathArguments::AngleBracketed(bracketed) => {
1127 bracketed.args = types
1128 .map(|param| parse_quote!(#param))
1129 .chain(core::mem::take(&mut bracketed.args))
1130 .collect();
1131 }
1132 syn::PathArguments::Parenthesized(_) => unreachable!("Not a valid trait name"),
1133 }
1134}
1135
1136impl ItemImplDescVisitor {
1137 fn find(item_impl: &ItemImpl) -> ItemImplDesc {
1138 let trait_ = item_impl.trait_.as_ref().map(|(_, trait_, _)| trait_);
1139
1140 let items = trait_.is_none().then(|| ImplItemsDesc {
1141 fns: item_impl
1142 .items
1143 .iter()
1144 .filter_map(|item| match item {
1145 syn::ImplItem::Fn(item) => Some((item.sig.ident.clone(), item.sig.clone())),
1146 _ => None,
1147 })
1148 .collect(),
1149 assoc_types: item_impl
1150 .items
1151 .iter()
1152 .filter_map(|item| match item {
1153 syn::ImplItem::Type(item) => Some(item.ident.clone()),
1154 _ => None,
1155 })
1156 .collect(),
1157 assoc_consts: item_impl
1158 .items
1159 .iter()
1160 .filter_map(|item| match item {
1161 syn::ImplItem::Const(item) => Some((item.ident.clone(), item.ty.clone())),
1162 _ => None,
1163 })
1164 .collect(),
1165 });
1166
1167 let mut visitor =
1168 Self {
1169 curr_bounded_ty: None,
1170 curr_trait_bound: None,
1171
1172 impl_desc: ItemImplDesc {
1173 id: ImplGroupId {
1174 trait_: trait_.cloned(),
1175 self_ty: (*item_impl.self_ty).clone(),
1176 },
1177 params: item_impl
1178 .generics
1179 .type_params()
1180 .map(|param| {
1181 let ident = param.ident.clone();
1182
1183 let sizedness = if param.bounds.iter().any(|bound| {
1184 matches!(
1185 bound,
1186 syn::TypeParamBound::Trait(syn::TraitBound {
1187 modifier: syn::TraitBoundModifier::Maybe(_),
1188 ..
1189 })
1190 )
1191 }) {
1192 Sizedness::Unsized
1193 } else {
1194 Sizedness::Sized
1195 };
1196
1197 (ident, GenericParam::Type(sizedness, IndexSet::new()))
1198 })
1199 .chain(item_impl.generics.const_params().map(|param| {
1200 (param.ident.clone(), GenericParam::Const(param.ty.clone()))
1201 }))
1202 .collect(),
1203 trait_bounds: IndexMap::new(),
1204 items,
1205 },
1206 };
1207
1208 visitor.visit_generics(&item_impl.generics);
1209 visitor.resolve_qself_types();
1210 visitor.impl_desc
1211 }
1212
1213 fn resolve_qself_types(&mut self) {
1214 let mut qself_resolver = QSelfResolver {
1215 params: core::mem::take(&mut self.impl_desc.params),
1216 trait_bounds: &mut self.impl_desc.trait_bounds,
1217 };
1218
1219 for i in 0..qself_resolver.trait_bounds.len() {
1220 let entry = qself_resolver.trait_bounds.shift_remove_index(i).unwrap();
1221 let ((mut bounded, mut bounds), mut bindings) = entry;
1222
1223 qself_resolver.visit_type_mut(&mut bounded.0);
1224 qself_resolver.visit_trait_bound_mut(&mut bounds.0);
1225
1226 bindings
1227 .values_mut()
1228 .for_each(|binding| qself_resolver.visit_type_mut(binding));
1229
1230 qself_resolver
1231 .trait_bounds
1232 .insert_before(i, (bounded, bounds), bindings);
1233 }
1234
1235 self.impl_desc.params = qself_resolver.params;
1236 }
1237}
1238
1239struct QSelfResolver<'a> {
1240 trait_bounds: &'a mut IndexMap<TraitBoundIdent, IndexMap<syn::Ident, AssocBindingPayload>>,
1241 params: IndexMap<syn::Ident, GenericParam>,
1242}
1243
1244impl VisitMut for QSelfResolver<'_> {
1245 fn visit_type_path_mut(&mut self, node: &mut syn::TypePath) {
1246 syn::visit_mut::visit_type_path_mut(self, node);
1247
1248 if let Some(syn::QSelf { ty, position, .. }) = &node.qself {
1249 let trait_segments = node
1250 .path
1251 .segments
1252 .iter()
1253 .take(*position)
1254 .cloned()
1255 .collect::<Punctuated<_, Token![::]>>();
1256
1257 if trait_segments.is_empty() {
1258 return;
1259 }
1260
1261 let trait_bound = syn::TraitBound {
1262 paren_token: None,
1263 modifier: syn::TraitBoundModifier::None,
1264 lifetimes: None,
1265 path: syn::Path {
1266 leading_colon: node.path.leading_colon,
1267 segments: trait_segments,
1268 },
1269 };
1270
1271 let trait_bound_ident = ((**ty).clone().into(), trait_bound.into());
1272 let assoc_ident = node.path.segments.last().unwrap().ident.clone();
1273
1274 let Some(bindings) = self.trait_bounds.get_mut(&trait_bound_ident) else {
1275 return;
1276 };
1277
1278 *node = if let Some(existing) = bindings.get(&assoc_ident) {
1279 parse_quote!(#existing)
1280 } else {
1281 let param = GenericParam::Type(Sizedness::Unsized, IndexSet::new());
1282 let param_ident = format_ident!("_TŠČ{}", self.params.len());
1283
1284 let param_ty: syn::Type = parse_quote!(#param_ident);
1285 self.params.entry(param_ident).or_insert(param);
1286 bindings.insert(assoc_ident, param_ty.clone());
1287
1288 parse_quote!(#param_ty)
1289 };
1290 }
1291 }
1292}
1293
1294impl Visit<'_> for ItemImplDescVisitor {
1295 fn visit_item_impl(&mut self, node: &ItemImpl) {
1296 self.visit_generics(&node.generics);
1297 }
1298 fn visit_constraint(&mut self, node: &syn::Constraint) {
1299 let curr_bounded_ty = self.curr_bounded_ty.take().unwrap();
1300 let curr_trait_bound = self.curr_trait_bound.take().unwrap();
1301
1302 let ident = &node.ident;
1303 let generics = &node.generics;
1304
1305 self.curr_bounded_ty = Some(parse_quote! {
1306 <#curr_bounded_ty as #curr_trait_bound>::#ident #generics
1307 });
1308
1309 for bound in &node.bounds {
1310 syn::visit::visit_type_param_bound(self, bound);
1311 }
1312
1313 self.curr_bounded_ty = Some(curr_bounded_ty);
1314 self.curr_trait_bound = Some(curr_trait_bound);
1315 }
1316
1317 fn visit_type_param(&mut self, node: &syn::TypeParam) {
1318 self.curr_bounded_ty = Some(node.into());
1319 syn::visit::visit_type_param(self, node);
1320 self.curr_bounded_ty = None;
1321 }
1322
1323 fn visit_predicate_type(&mut self, node: &syn::PredicateType) {
1324 self.curr_bounded_ty = Some(node.bounded_ty.clone().into());
1325 syn::visit::visit_predicate_type(self, node);
1326 self.curr_bounded_ty = None;
1327 }
1328
1329 fn visit_trait_bound(&mut self, node: &syn::TraitBound) {
1330 self.curr_trait_bound = Some(node.clone().into());
1331
1332 let trait_bound_ident = (
1333 self.curr_bounded_ty.clone().unwrap(),
1334 self.curr_trait_bound.clone().unwrap(),
1335 );
1336
1337 self.impl_desc
1338 .trait_bounds
1339 .entry(trait_bound_ident)
1340 .or_default();
1341
1342 visit_trait_bound(self, node);
1343 self.curr_trait_bound = None;
1344 }
1345
1346 fn visit_assoc_type(&mut self, node: &syn::AssocType) {
1347 let trait_bound_ident = (
1348 self.curr_bounded_ty.clone().unwrap(),
1349 self.curr_trait_bound.clone().unwrap(),
1350 );
1351
1352 self.impl_desc.trait_bounds[&trait_bound_ident].insert(node.ident.clone(), node.ty.clone());
1353 }
1354}
1355
1356#[proc_macro]
1525#[proc_macro_error]
1526pub fn disjoint_impls(input: TokenStream) -> TokenStream {
1527 let ImplGroups {
1528 trait_,
1529 impl_groups,
1530 } = parse_macro_input!(input);
1531
1532 let mut trait_impls_tokens = Vec::new();
1533 let groups = impl_groups
1534 .into_iter()
1535 .enumerate()
1536 .map(|(idx, impl_group)| {
1537 let (tokens, trait_impls) = build_disjoint_impl_group(trait_.as_ref(), impl_group, idx);
1538 trait_impls_tokens.extend(trait_impls);
1539 tokens
1540 })
1541 .collect::<Vec<_>>();
1542
1543 let groups = quote! { #(#groups)* };
1544 let trait_ = trait_.filter(|trait_| !trait_.attrs.iter().any(is_remote));
1545
1546 let trait_impls = trait_impls_tokens
1547 .into_iter()
1548 .map(|trait_impl| quote!(#trait_impl))
1549 .collect::<Vec<_>>();
1550
1551 quote! {
1552 #trait_
1553
1554 #[allow(clippy::needless_lifetimes)]
1555 const _: () = {
1556 #groups
1557 #( #trait_impls )*
1558 };
1559 }
1560 .into()
1561}
1562
1563impl Parse for ImplGroups {
1564 fn parse(input: ParseStream) -> syn::parse::Result<Self> {
1565 let main_trait = input.parse::<ItemTrait>().ok();
1566
1567 let mut impls = Vec::new();
1568 let mut descs = Vec::new();
1569
1570 while let Ok(item) = input.parse::<ItemImpl>() {
1571 validate_impl_syntax(&item);
1572
1573 let impl_ = normalize::normalize(item);
1574 let desc = ItemImplDescVisitor::find(&impl_);
1575
1576 impls.push(impl_);
1577 descs.push(desc);
1578 }
1579
1580 let mut dsu = Dsu::new(impls.len());
1581 for i in 0..impls.len() {
1582 for j in (i + 1)..impls.len() {
1583 let mut subs = Default::default();
1584
1585 let desc_i = &descs[i];
1586 let desc_j = &descs[j];
1587
1588 if desc_i
1589 .id
1590 .generalize(&desc_j.id, &desc_i.params, &desc_j.params, &mut subs)
1591 .is_some()
1592 && subs
1593 .is_disjoint(&desc_i.params, &desc_j.params)
1594 .is_none_or(|disjoint| !disjoint)
1595 {
1596 dsu.union(i, j);
1597 }
1598 }
1599 }
1600
1601 let groups = dsu.groups();
1602 let impl_group_builders = groups
1603 .iter()
1604 .flat_map(|subset| {
1605 partition_impl_groups(subset, &descs).expect_or_abort("Impls overlap")
1607 })
1608 .collect::<Vec<_>>();
1609
1610 let mut impls = impls.into_iter().map(Some).collect::<Vec<_>>();
1611
1612 let impl_groups = impl_group_builders
1613 .into_iter()
1614 .map(|(builder, impl_group)| {
1615 instantiate_impl_group(builder, impl_group, &mut impls, &descs)
1616 })
1617 .collect();
1618
1619 Ok(Self::new(main_trait, impl_groups))
1620 }
1621}
1622
1623fn partition_impl_groups(
1630 subset: &[usize],
1631 impls: &[ItemImplDesc],
1632) -> Option<Vec<(ImplGroupBuilder, Vec<usize>)>> {
1633 partition_impl_groups_rec(subset, impls, &mut Vec::new())
1634}
1635
1636fn partition_impl_groups_rec(
1637 subset: &[usize],
1638 impls: &[ItemImplDesc],
1639 impl_groups: &mut Vec<(ImplGroupBuilder, Vec<usize>)>,
1640) -> Option<Vec<(ImplGroupBuilder, Vec<usize>)>> {
1641 let Some((&curr_impl_idx, rest)) = subset.split_first() else {
1642 return build_impl_groups(impls, impl_groups).collect();
1643 };
1644
1645 let mut min = None::<Vec<_>>;
1646 let curr_impl = &impls[curr_impl_idx];
1647
1648 for impl_group_idx in 0..impl_groups.len() {
1649 let impl_group = &impl_groups[impl_group_idx];
1650
1651 if let Some(intersection) = impl_group.0.intersection(curr_impl) {
1652 let (builder, impl_group) = &mut impl_groups[impl_group_idx];
1653 let prev_builder = core::mem::replace(builder, intersection);
1654 impl_group.push(curr_impl_idx);
1655
1656 match (
1657 partition_impl_groups_rec(rest, impls, impl_groups),
1658 &mut min,
1659 ) {
1660 (Some(res), Some(min)) if res.len() < min.len() => *min = res,
1661 (Some(res), None) => min = Some(res),
1662 _ => {}
1663 }
1664
1665 let impl_group_to_restore = &mut impl_groups[impl_group_idx];
1667 impl_group_to_restore.0 = prev_builder;
1668 impl_group_to_restore.1.pop();
1669
1670 if min.as_ref().is_some_and(|m| m.len() == impl_groups.len()) {
1671 break;
1673 }
1674 }
1675 }
1676
1677 if min.as_ref().is_none_or(|m| m.len() > 1 + impl_groups.len())
1679 && (curr_impl.id.is_inherent() || impl_groups.iter().all(|g| g.0.id != curr_impl.id))
1680 {
1681 impl_groups.push((ImplGroupBuilder::new(curr_impl), vec![curr_impl_idx]));
1682
1683 match (
1684 partition_impl_groups_rec(rest, impls, impl_groups),
1685 &mut min,
1686 ) {
1687 (Some(res), Some(min)) if res.len() < min.len() => *min = res,
1688 (Some(res), None) => min = Some(res),
1689 _ => {}
1690 }
1691
1692 impl_groups.pop();
1694 }
1695
1696 min
1697}
1698
1699fn build_impl_groups(
1702 impls: &[ItemImplDesc],
1703 impl_groups: &[(ImplGroupBuilder, Vec<usize>)],
1704) -> impl Iterator<Item = Option<(ImplGroupBuilder, Vec<usize>)>> {
1705 impl_groups.iter().map(|(builder, impl_group)| {
1706 let (non_overlapping, overlapping) = split_overlapping_impls(impls, builder, impl_group);
1707 let non_overlapping_set = non_overlapping.iter().copied().collect::<IndexSet<_>>();
1708
1709 let mut builder = builder.clone();
1710 if non_overlapping_set.is_empty() {
1711 return None;
1712 }
1713
1714 if !overlapping.is_empty() {
1715 let mut subgroups = vec![];
1716
1717 for overlapping in &overlapping {
1718 subgroups.extend(partition_impl_groups(overlapping, impls)?);
1719 }
1720
1721 if subgroups.iter().any(|(sub_builder, _)| {
1722 sub_builder.trait_bounds.0.len() <= builder.trait_bounds.0.len()
1723 }) {
1724 return None;
1725 }
1726
1727 let mut non_overlapping_pos: Vec<_> = impl_group
1728 .iter()
1729 .enumerate()
1730 .filter(|&(_, idx)| non_overlapping_set.contains(idx))
1731 .map(|(pos, _)| pos)
1732 .collect();
1733 non_overlapping_pos.sort_unstable();
1734
1735 let overlapping_trait_bounds = builder
1736 .trait_bounds
1737 .retain_impl_by_pos(&non_overlapping_pos);
1738
1739 builder.subgroups = subgroups
1740 .into_iter()
1741 .map(|(sub_builder, idxs)| {
1742 (sub_builder, idxs, overlapping_trait_bounds.clone())
1745 })
1746 .collect();
1747 }
1748
1749 Some((builder, non_overlapping))
1750 })
1751}
1752
1753fn split_overlapping_impls(
1754 impls: &[ItemImplDesc],
1755 builder: &ImplGroupBuilder,
1756 group: &[usize],
1757) -> (Vec<usize>, Vec<Vec<usize>>) {
1758 let mut dsu = Dsu::new(group.len());
1759
1760 for i in 0..group.len() {
1761 for j in (i + 1)..group.len() {
1762 let mut subs = Generalizations::default();
1763
1764 let desc_i = &impls[group[i]];
1765 let desc_j = &impls[group[j]];
1766
1767 if desc_i
1768 .id
1769 .generalize(&desc_j.id, &desc_i.params, &desc_j.params, &mut subs)
1770 .is_none()
1771 {
1772 continue;
1773 }
1774
1775 if subs
1776 .is_disjoint(&desc_i.params, &desc_j.params)
1777 .is_none_or(|disjoint| !disjoint)
1778 {
1779 let assoc_bindings = builder
1780 .trait_bounds
1781 .0
1782 .values()
1783 .map(|(_, bindings)| bindings);
1784
1785 let is_overlapping = assoc_bindings
1786 .flat_map(|assoc_bindings| assoc_bindings.values())
1787 .all(|(_, payloads)| {
1788 let (binding_i, binding_j) = (&payloads[i], &payloads[j]);
1789
1790 if binding_i
1791 .generalize(binding_j, &desc_i.params, &desc_j.params, &mut subs)
1792 .is_none()
1793 {
1794 return false;
1795 }
1796
1797 subs.is_disjoint(&desc_i.params, &desc_j.params) == Some(false)
1798 });
1799
1800 if is_overlapping {
1801 dsu.union(i, j);
1802 }
1803 }
1804 }
1805 }
1806
1807 let mut non_overlapping = Vec::new();
1808 let mut overlapping = Vec::new();
1809
1810 for component in dsu.groups() {
1811 if component.len() > 1 {
1812 overlapping.push(component.into_iter().map(|pos| group[pos]).collect());
1813 } else {
1814 non_overlapping.push(group[component[0]]);
1815 }
1816 }
1817
1818 (non_overlapping, overlapping)
1819}
1820
1821fn remove_trait_bounds(trait_bounds: &TraitBoundsBuilder, impl_group: &mut ImplGroupBuilder) {
1822 for (parent_orig, _) in trait_bounds.0.values() {
1823 impl_group
1824 .subgroups
1825 .iter_mut()
1826 .for_each(|(subgroup, _, common_bounds)| {
1827 remove_trait_bounds(trait_bounds, subgroup);
1828
1829 common_bounds.0.retain(|_, target_orig| {
1830 target_orig
1831 .0
1832 .iter()
1833 .any(|target_bound| !parent_orig.contains(target_bound))
1834 });
1835 });
1836
1837 impl_group.trait_bounds.0.retain(|_, target_orig| {
1838 target_orig
1839 .0
1840 .iter()
1841 .any(|target_bound| !parent_orig.contains(target_bound))
1842 });
1843 }
1844}
1845
1846fn find_common_types(
1847 parent_trait_bounds: &TraitBoundsBuilder,
1848 subgroup_trait_bounds: &TraitBoundsBuilder,
1849) -> Vec<AssocBindingPayload> {
1850 let mut result = Vec::new();
1851
1852 for (parent_bound_id, (parent_orig, parent_bindings)) in &parent_trait_bounds.0 {
1853 if let Some((_, (_, sub_bindings))) =
1854 subgroup_trait_bounds.0.iter().find(|(_, (sub_orig, _))| {
1855 sub_orig
1856 .iter()
1857 .all(|sub_bound| parent_orig.contains(sub_bound))
1858 })
1859 {
1860 result.extend(parent_bindings.iter().map(|(ident, _)| {
1861 sub_bindings
1862 .get(ident)
1863 .map(|(payload, _)| payload.clone())
1864 .unwrap_or_else(|| assoc_binding_default(parent_bound_id, ident))
1865 }));
1866 }
1867 }
1868
1869 result
1870}
1871
1872fn assoc_binding_default(trait_ident: &TraitBoundIdent, ident: &syn::Ident) -> syn::Type {
1873 let Bounded(bounded_ty) = &trait_ident.0;
1874 let TraitBound(trait_bound) = &trait_ident.1;
1875 parse_quote!(<#bounded_ty as #trait_bound>::#ident)
1876}