disjoint_impls/
lib.rs

1//! Unlock support for a variety of mutually disjoint implementations that the Rust compiler
2//! [does not (yet?) support](https://github.com/rust-lang/rust/issues/20400).
3//!
4//! Works for trait and inherent implementations alike (no special syntax).
5//!
6//! # Trait implementations
7//!
8//! ```
9//! use disjoint_impls::disjoint_impls;
10//!
11//! pub trait Dispatch {
12//!     type Group;
13//! }
14//!
15//! disjoint_impls! {
16//!     pub trait Kita {}
17//!
18//!     impl<T: Dispatch<Group = u32>> Kita for T {}
19//!     impl<T: Dispatch<Group = i32>> Kita for T {}
20//! }
21//! ```
22//!
23//! # Inherent implementations
24//!
25//! ```
26//! use disjoint_impls::disjoint_impls;
27//!
28//! pub trait Dispatch {
29//!     type Group;
30//! }
31//!
32//! struct Wrapper<T>(T);
33//!
34//! disjoint_impls! {
35//!     impl<T: Dispatch<Group = u32>> Wrapper<T> {}
36//!     impl<T: Dispatch<Group = i32>> Wrapper<T> {}
37//! }
38//! ```
39//!
40//! See the [`disjoint_impls!`] macro for details.
41
42use 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
72/// Identifier of a type bounded with a trait such as:
73///     `Option<T>: Kita` in `impl<T> Foo for T where Option<T>: Kita`
74type TraitBoundIdent = (Bounded, TraitBound);
75
76/// AST node type of the associated bound constraint such as:
77///     `bool` in `impl<T: Deref<Target = bool>> for Clone for T`
78type AssocBindingPayload = syn::Type;
79
80/// Mapping from an associated type identifier to it's payload such as:
81///     `Target = bool` in `impl<T: Deref<Target = bool>> Clone for T`
82///
83/// This mapping tracks generalized payload (payload to be used in the main trait impl)
84/// and a concrete payload of every impl
85type AssocBindings = IndexMap<
86    syn::Ident,
87    (
88        Option<AssocBindingPayload>,
89        Vec<Option<AssocBindingPayload>>,
90    ),
91>;
92
93/// Builder for [`AssocBindings`].
94type AssocBindingsBuilder =
95    IndexMap<syn::Ident, (AssocBindingPayload, Vec<Option<AssocBindingPayload>>)>;
96
97/// All generalized trait bounded types of the impl group with their associated bindings.
98#[derive(Debug, Clone)]
99struct TraitBounds(IndexMap<TraitBoundIdent, (Vec<TraitBoundIdent>, AssocBindings)>);
100
101/// Builder for [`TraitBoundGroup`]
102#[derive(Debug, Clone)]
103struct TraitBoundsBuilder(IndexMap<TraitBoundIdent, (Vec<TraitBoundIdent>, AssocBindingsBuilder)>);
104
105/// A this wrapper around [`syn::PredicateType::bounded_ty`](syn::PredicateType::bounded_ty).
106/// Note, however, that generic type parameters are also considered to be bounded types
107///
108/// # Example
109///
110/// ```ignore
111/// impl<T: Dispatch<Group = GroupA>> Kita for T {}
112/// impl<T> Kita for T where T: Dispatch<Group = GroupB> {}
113/// ```
114///
115/// both have `T` as a bounded type
116#[derive(Debug, Clone, PartialEq, Eq, Hash)]
117#[repr(transparent)]
118struct Bounded(syn::Type);
119
120/// A thin wrapper around [`syn::TraitBound`](syn::TraitBound) but with associated bindings removed
121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
122#[repr(transparent)]
123struct TraitBound(syn::TraitBound);
124
125/// Unique id of an impl group, i.e. ([`ItemImpl::trait_`], [`ItemImpl::self_ty`]).
126///
127/// All [`ItemImpl`]s that have matching group ids are handled by one main trait impl.
128#[derive(Debug, Clone, PartialEq, Eq, Hash)]
129struct ImplGroupId {
130    trait_: Option<syn::Path>,
131    self_ty: syn::Type,
132}
133
134/// [`syn::ImplItem`]s descriptor
135#[derive(Debug, Clone, Default)]
136struct ImplItemsDesc {
137    /// Fns that are contained in this group
138    fns: IndexMap<syn::Ident, syn::Signature>,
139    /// Associated types that are contained in this group
140    assoc_types: IndexSet<syn::Ident>,
141    /// Associated constants that are contained in this group
142    assoc_consts: IndexMap<syn::Ident, syn::Type>,
143}
144
145/// [`syn::ItemImpl`] descriptor
146#[derive(Debug, Clone)]
147struct ItemImplDesc {
148    /// Id of this impl
149    id: ImplGroupId,
150    /// Type and const parameters of this impl
151    params: Params,
152    /// All trait bounds of this impl (optionally with associated bindings)
153    trait_bounds: IndexMap<TraitBoundIdent, IndexMap<syn::Ident, AssocBindingPayload>>,
154    /// [Items](syn::ImplItem) of this impl if the impl is inherent, [`None`] otherwise
155    items: Option<ImplItemsDesc>,
156}
157
158/// Builder for [`ImplGroup`]
159#[derive(Debug, Clone)]
160struct ImplGroupBuilder {
161    /// Id of this group
162    id: ImplGroupId,
163    /// Lifetime parameters common to this group
164    lifetimes: Vec<syn::LifetimeParam>,
165    /// Type and const parameters common to this group
166    params: Params,
167    /// All trait bounds common to this impl group (optionally with associated bindings)
168    trait_bounds: TraitBoundsBuilder,
169    /// Generalized items of the impl group if the impls are inherent, [`None`] otherwise
170    items: Option<ImplItemsDesc>,
171    /// All impls that overlap on associated bindings this group is dispatched on.
172    subgroups: Vec<(Self, Vec<usize>, TraitBoundsBuilder)>,
173}
174
175/// Collection of disjoint [`ItemImpl`]s grouped by [`ImplGroupId`] and dispatched on associated bindings
176#[derive(Debug, Clone)]
177struct ImplGroup {
178    /// Id of this group
179    id: ImplGroupId,
180    /// Type and const parameters common to this group
181    params: Punctuated<syn::GenericParam, Token![,]>,
182    /// All trait bounds common to this impl group (optionally with associated bindings)
183    trait_bounds: TraitBounds,
184    /// Generalized items of the impl group if the impls are inherent, [`None`] otherwise
185    items: Option<ImplItemsDesc>,
186
187    /// All disjoint [impls](syn::ItemImpl) that are part of this group
188    impls: Vec<(syn::ItemImpl, Vec<syn::GenericArgument>)>,
189
190    /// All remaining impls that overlap on associated bindings this group is dispatched on.
191    ///
192    /// For instance, the following 3 impls will form a group where the last 2 impls
193    /// overlap on `Group1 = GroupB` but form a subgroup on `Group2` assoc binding:
194    ///
195    /// ```ignore
196    /// impl<T> Kita for T where T: Dispatch<Group1 = GroupA> {}
197    /// impl<T> Kita for T where T: Dispatch<Group1 = GroupB, Group2 = GroupA> {}
198    /// impl<T> Kita for T where T: Dispatch<Group1 = GroupB, Group2 = GroupB> {}
199    /// ```
200    subgroups: Vec<(ImplGroup, Vec<AssocBindingPayload>)>,
201}
202
203/// Body of the [`disjoint_impls`] macro
204#[derive(Debug, Clone)]
205struct ImplGroups {
206    /// Definition of the trait current group is implementing. [`None`] for inherent impls
207    trait_: Option<ItemTrait>,
208    /// Collection of [`ItemImpl`] blocks grouped by [`ImplGroupId`].
209    /// Each impl group is dispatched on a set of associated bounds
210    impl_groups: Vec<ImplGroup>,
211}
212
213struct ItemImplDescVisitor {
214    /// Bounded type currently being visited
215    curr_bounded_ty: Option<Bounded>,
216    /// Trait bound currently being visited
217    curr_trait_bound: Option<TraitBound>,
218
219    /// Bounds of an impl block
220    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
312/// Helper struct for disjoint-set union algorithm
313struct 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    /// Removes impls at positions not in `keep`. Returns removed impls.
356    ///
357    /// The remove is stable. This means that relative order of impls of both original
358    /// and removed impls is preserved. Total order of trait bounds is also preserved.
359    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    /// Try to remove all unconstrained params because Rust's trait solver can overflow
411    /// when exploring valid implementations that have too many degrees of freedom.
412    ///
413    /// Prefer `impl<T> Kita for T where Self: Kita0<<T as Dispatch>::Group>, T: Dispatch {}`
414    /// instead of: `impl<T, U> Kita for T where Self: Kita0<<U>, T: Dispatch<Group = U> {}`
415    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        // NOTE: Only pick out trait bounds that, when generalized, don't introduce a new type
749        // unbounded parameter that is not found in any of the associated binding payloads
750        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        // NOTE: After finding out which substitutions are valid,
794        // the generalization is done once again with results kept
795        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(&params))
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/// Enables writing non-overlapping (*disjoint*) impls distinguished by a set of associated types.
1357///
1358/// # Trait implementations
1359///
1360/// ```
1361/// use disjoint_impls::disjoint_impls;
1362///
1363/// pub trait Dispatch {
1364///     type Group;
1365/// }
1366///
1367/// pub enum GroupA {}
1368/// pub enum GroupB {}
1369///
1370/// impl Dispatch for u32 {
1371///     type Group = GroupA;
1372/// }
1373/// impl Dispatch for i32 {
1374///     type Group = GroupB;
1375/// }
1376///
1377/// impl Dispatch for Option<u32> {
1378///     type Group = GroupA;
1379/// }
1380///
1381/// disjoint_impls! {
1382///     pub trait Kita {
1383///         const NAME: &'static str;
1384///
1385///         fn name() -> &'static str {
1386///             "Default blanket"
1387///         }
1388///     }
1389///
1390///     impl<T, U> Kita for (T, U)
1391///     where
1392///         T: Dispatch<Group = GroupA>,
1393///         U: Dispatch<Group = GroupA>,
1394///     {
1395///         const NAME: &'static str = "Blanket AA";
1396///     }
1397///
1398///     impl<T, U> Kita for (T, U)
1399///     where
1400///         T: Dispatch<Group = GroupA>,
1401///         U: Dispatch<Group = GroupB>,
1402///     {
1403///         const NAME: &'static str = "Blanket AB";
1404///     }
1405///
1406///     impl<T, U> Kita for (T, U)
1407///     where
1408///         T: Dispatch<Group = GroupB>,
1409///         U: Dispatch,
1410///     {
1411///         const NAME: &'static str = "Blanket B*";
1412///     }
1413///
1414///     impl<T> Kita for T
1415///     where
1416///         Option<T>: Dispatch<Group = GroupA>,
1417///     {
1418///         const NAME: &'static str = "Option blanket";
1419///
1420///         fn name() -> &'static str {
1421///             <Self as Kita>::NAME
1422///         }
1423///     }
1424/// }
1425///
1426/// fn main() {
1427///     assert_eq!("Blanket AA", <(u32, u32)>::NAME);
1428///     assert_eq!("Blanket AB", <(u32, i32)>::NAME);
1429///     assert_eq!("Blanket B*", <(i32, u32)>::NAME);
1430///
1431///     assert_eq!("Option blanket", u32::name());
1432/// }
1433/// ```
1434///
1435/// # Inherent implementations
1436///
1437/// ```
1438/// use disjoint_impls::disjoint_impls;
1439///
1440/// pub trait Dispatch {
1441///     type Group;
1442/// }
1443///
1444/// impl Dispatch for u32 {
1445///     type Group = Self;
1446/// }
1447/// impl Dispatch for i32 {
1448///     type Group = Self;
1449/// }
1450///
1451/// struct Wrapper<T>(T);
1452///
1453/// disjoint_impls! {
1454///     impl<T: Dispatch<Group = U>, U: Dispatch<Group = u32>> Wrapper<T> {
1455///         const NAME: &'static str = "Blanket A";
1456///     }
1457///     impl<T: Dispatch<Group = U>, U: Dispatch<Group = i32>> Wrapper<T> {
1458///         const NAME: &'static str = "Blanket B";
1459///     }
1460/// }
1461///
1462/// fn main() {
1463///     assert_eq!("Blanket A", Wrapper::<u32>::NAME);
1464///     assert_eq!("Blanket B", Wrapper::<i32>::NAME);
1465/// }
1466/// ```
1467///
1468/// # Foreign(remote) traits
1469///
1470/// For traits defined outside the current crate (a.k.a. foreign or remote traits), duplicate
1471/// the trait definition inside the macro and annotate it with `#[disjoint_impls(remote)]`.
1472///
1473/// ```
1474/// use disjoint_impls::disjoint_impls;
1475/// // A foreign trait must be brought into scope so
1476/// // the `disjoint_impls!` macro can refer to it.
1477/// use remote_trait::ForeignKita;
1478///
1479/// pub trait Dispatch {
1480///     type Group;
1481/// }
1482///
1483/// pub enum GroupA {}
1484/// pub enum GroupB {}
1485///
1486/// impl Dispatch for u32 {
1487///     type Group = GroupA;
1488/// }
1489/// impl Dispatch for i32 {
1490///     type Group = GroupB;
1491/// }
1492///
1493/// // (orphan rule): You can define blanket impls only
1494/// // for types that are defined in the current crate
1495/// pub struct LocalType<T>(T);
1496///
1497/// disjoint_impls! {
1498///     // Trait annotated with `#[disjoint_impls(remote)]` must be an exact duplicate of
1499///     // the foreign/remote trait it refers to (default values and fn bodies excluded)
1500///     #[disjoint_impls(remote)]
1501///     pub trait ForeignKita<U> {
1502///         fn kita() -> &'static str;
1503///     }
1504///
1505///     impl<T: Dispatch<Group = GroupA>> ForeignKita<T> for LocalType<T> {
1506///         fn kita() -> &'static str {
1507///             "Blanket A"
1508///         }
1509///     }
1510///     impl<T: Dispatch<Group = GroupB>> ForeignKita<T> for LocalType<T> {
1511///         fn kita() -> &'static str {
1512///             "Blanket B"
1513///         }
1514///     }
1515/// }
1516///
1517/// fn main() {
1518///     assert_eq!("Blanket A", LocalType::<u32>::kita());
1519///     assert_eq!("Blanket B", LocalType::<i32>::kita());
1520/// }
1521/// ```
1522///
1523/// Other, much more complex examples, can be found in tests.
1524#[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                // TODO: Write better error message
1606                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
1623/// Further partitions the given subset into smaller, non-overlapping groups of impls.
1624///
1625/// The input `subset` comes from an initial partition where any two impls in **different** subsets
1626/// are guaranteed by the Rust compiler to be non-overlapping. However, impls within the **same**
1627/// subset may still potentially overlap. This function refines those subsets by detecting and
1628/// separating impls that are found not to overlap.
1629fn 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            // NOTE: Restore impl group changes before the next iteration
1666            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                // NOTE: One of the shortest solutions has been found
1672                break;
1673            }
1674        }
1675    }
1676
1677    // NOTE: Try create a new group if shorter solution is possible
1678    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        // NOTE: Restore changes to impl groups
1693        impl_groups.pop();
1694    }
1695
1696    min
1697}
1698
1699/// Separates the given impls into two groups: those that don't overlap and those that do.
1700/// Overlapping impls are then recursively partitioned into smaller, non-overlapping groups.
1701fn 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                    // FIXME: It's not necessary to clone trait bounds. Trait bounds should be
1743                    // partitioned to extract impls rows pertaining to a particular subgroup
1744                    (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}