1#![doc = include_str!("../README.md")]
2
3mod normalize;
4mod substitute;
5
6use normalize::WherePredicateBinding;
7use proc_macro::TokenStream as TokenStream1;
8use proc_macro2::{Span, TokenStream};
9use proc_macro_error::{abort, proc_macro_error};
10use std::collections::{HashMap, HashSet};
11use substitute::{Substitute, SubstituteEnvironment};
12use syn::punctuated::Punctuated;
13use syn::spanned::Spanned;
14use syn::visit_mut::VisitMut;
15use syn::*;
16use template_quote::quote;
17
18fn replace_type_of_trait_item_fn(mut ty: TraitItemFn, from: &Type, to: &Type) -> TraitItemFn {
19 use syn::visit_mut::VisitMut;
20 struct Visitor<'a>(&'a Type, &'a Type);
21 impl<'a> VisitMut for Visitor<'a> {
22 fn visit_type_mut(&mut self, ty: &mut Type) {
23 if &ty == &self.0 {
24 *ty = self.1.clone();
25 }
26 syn::visit_mut::visit_type_mut(self, ty)
27 }
28 }
29 let mut visitor = Visitor(from, to);
30 visitor.visit_trait_item_fn_mut(&mut ty);
31 ty
32}
33
34fn map_lifetimes(mut ty: Type, to: Lifetime) -> Type {
40 struct V(Lifetime);
41 impl VisitMut for V {
42 fn visit_lifetime_mut(&mut self, i: &mut Lifetime) {
43 if i.ident != "static" {
44 *i = self.0.clone();
45 }
46 }
47 }
48 V(to).visit_type_mut(&mut ty);
49 ty
50}
51
52fn check_defaultness(item_impl: &ItemImpl) -> Option<bool> {
53 let mut ret = false;
54 if item_impl.defaultness.is_some() {
56 return None;
57 }
58 for item in item_impl.items.iter() {
59 match item {
60 ImplItem::Const(item_const) if item_const.defaultness.is_some() => {
61 return None;
62 }
63 ImplItem::Fn(item_method) if item_method.defaultness.is_some() => {
64 ret = true;
65 }
66 ImplItem::Type(item_type) if item_type.defaultness.is_some() => {
67 return None;
68 }
69 _ => (),
70 }
71 }
72 Some(ret)
73}
74
75fn normalize_params_and_predicates(
76 impl_: &ItemImpl,
77) -> (HashSet<GenericParam>, HashSet<WherePredicateBinding>) {
78 let (mut gps, mut wps) = (HashSet::new(), HashSet::new());
79 for gp in impl_.generics.params.iter() {
80 let (gp, nwps) = normalize::normalize_generic_param(gp.clone());
81 gps.insert(gp);
82 wps.extend(nwps);
83 }
84 if let Some(wc) = &impl_.generics.where_clause {
85 for p in wc.predicates.iter() {
86 let nwps = normalize::normalize_where_predicate(p.clone());
87 wps.extend(nwps);
88 }
89 }
90 (gps, wps)
91}
92
93fn get_param_ident(p: GenericParam) -> Option<Ident> {
94 match p {
95 GenericParam::Type(tp) => Some(tp.ident),
96 _ => None,
97 }
98}
99
100fn get_type_ident(ty: Type) -> Option<Ident> {
101 match ty {
102 Type::Path(tp) if tp.qself.is_none() => tp.path.get_ident().cloned(),
103 _ => None,
104 }
105}
106
107fn find_type_ident(ty: &Type, ident: &Ident) -> bool {
108 use syn::visit::Visit;
109 struct Visitor<'a>(&'a Ident, bool);
110 impl<'ast, 'a> Visit<'ast> for Visitor<'a> {
111 fn visit_type(&mut self, i: &'ast Type) {
112 match i {
113 Type::Path(tp) if tp.qself.is_none() && tp.path.get_ident() == Some(&self.0) => {
114 self.1 = true;
115 }
116 _ => {
117 syn::visit::visit_type(self, i);
118 }
119 }
120 }
121 }
122 let mut vis = Visitor(ident, false);
123 vis.visit_type(ty);
124 vis.1
125}
126
127fn get_trivial_substitutions(
128 special_params: &HashSet<Ident>,
129 substitution: &HashMap<Ident, Type>,
130) -> Vec<(Ident, Ident)> {
131 substitution
132 .iter()
133 .filter_map(|(d, s)| {
134 get_type_ident(s.clone())
135 .and_then(|i| special_params.iter().find(|ii| &&i == ii).cloned())
136 .map(|s| (d.clone(), s))
137 })
138 .collect()
139}
140
141fn substitute_impl(
142 default_impl: &ItemImpl,
143 special_impl: &ItemImpl,
144) -> Vec<(HashMap<Ident, Type>, usize)> {
145 let (d_ps, d_ws) = normalize_params_and_predicates(default_impl);
146 let (s_ps, s_ws) = normalize_params_and_predicates(special_impl);
147 let self_ident = Ident::new("Self", Span::call_site());
149 let d_ws = d_ws
150 .into_iter()
151 .map(|w| {
152 w.replace_type_params(
153 core::iter::once((self_ident.clone(), default_impl.self_ty.as_ref().clone()))
154 .collect(),
155 )
156 })
157 .collect::<HashSet<_>>();
158 let s_ws = s_ws
159 .into_iter()
160 .map(|w| {
161 w.replace_type_params(
162 core::iter::once((self_ident.clone(), special_impl.self_ty.as_ref().clone()))
163 .collect(),
164 )
165 })
166 .collect::<HashSet<_>>();
167 let s_ps: HashSet<_> = s_ps.into_iter().filter_map(get_param_ident).collect();
168 let env = SubstituteEnvironment {
169 general_params: d_ps.into_iter().filter_map(get_param_ident).collect(),
170 };
171 let s = env.substitute(&d_ws, &s_ws)
172 * env.substitute(
173 &default_impl.trait_.as_ref().unwrap().1,
174 &special_impl.trait_.as_ref().unwrap().1,
175 )
176 * env.substitute(&*default_impl.self_ty, &*special_impl.self_ty);
177 s.0.into_iter()
179 .filter(|m| {
180 m.iter().all(|(_, ty)| {
181 s_ps.iter().all(|i| {
182 &get_type_ident(ty.clone()).as_ref() == &Some(i) || !find_type_ident(ty, &i)
183 })
184 })
185 })
186 .map(|r| {
187 (
188 r.clone(),
189 r.len() - get_trivial_substitutions(&s_ps, &r).len(),
190 )
191 })
192 .collect()
193}
194
195trait ReplaceTypeParams {
196 fn replace_type_params(self, map: HashMap<Ident, Type>) -> Self;
197}
198
199const _: () = {
200 fn filter_map_with_generics(
201 map: &HashMap<Ident, Type>,
202 generics: &Generics,
203 ) -> HashMap<Ident, Type> {
204 map.clone()
205 .into_iter()
206 .filter(|(k, _)| {
207 generics
208 .params
209 .iter()
210 .filter_map(|o| {
211 if let GenericParam::Type(pt) = o {
212 Some(&pt.ident)
213 } else {
214 None
215 }
216 })
217 .all(|id| k != id)
218 })
219 .collect()
220 }
221 #[derive(Clone)]
222 struct Visitor(HashMap<Ident, Type>);
223 impl VisitMut for Visitor {
224 fn visit_type_mut(&mut self, i: &mut Type) {
225 if let Type::Path(tp) = i {
226 if let Some(id) = tp.path.get_ident() {
227 if let Some(replaced) = self.0.get(id) {
228 *i = replaced.clone();
229 return;
230 }
231 }
232 }
233 syn::visit_mut::visit_type_mut(self, i)
234 }
235 fn visit_item_fn_mut(&mut self, i: &mut ItemFn) {
236 let mut this = Visitor(filter_map_with_generics(&self.0, &i.sig.generics));
237 syn::visit_mut::visit_item_fn_mut(&mut this, i);
238 }
239 fn visit_item_impl_mut(&mut self, i: &mut ItemImpl) {
240 let mut this = Visitor(filter_map_with_generics(&self.0, &i.generics));
241 syn::visit_mut::visit_item_impl_mut(&mut this, i);
242 }
243 fn visit_item_trait_mut(&mut self, i: &mut ItemTrait) {
244 let mut this = Visitor(filter_map_with_generics(&self.0, &i.generics));
245 syn::visit_mut::visit_item_trait_mut(&mut this, i);
246 }
247 fn visit_item_struct_mut(&mut self, i: &mut ItemStruct) {
248 let mut this = Visitor(filter_map_with_generics(&self.0, &i.generics));
249 syn::visit_mut::visit_item_struct_mut(&mut this, i);
250 }
251 fn visit_item_enum_mut(&mut self, i: &mut ItemEnum) {
252 let mut this = Visitor(filter_map_with_generics(&self.0, &i.generics));
253 syn::visit_mut::visit_item_enum_mut(&mut this, i);
254 }
255 fn visit_item_type_mut(&mut self, i: &mut ItemType) {
256 let mut this = Visitor(filter_map_with_generics(&self.0, &i.generics));
257 syn::visit_mut::visit_item_type_mut(&mut this, i);
258 }
259 fn visit_item_union_mut(&mut self, i: &mut ItemUnion) {
260 let mut this = Visitor(filter_map_with_generics(&self.0, &i.generics));
261 syn::visit_mut::visit_item_union_mut(&mut this, i);
262 }
263 }
264
265 impl ReplaceTypeParams for WherePredicateBinding {
266 fn replace_type_params(self, map: HashMap<Ident, Type>) -> Self {
267 match self {
268 WherePredicateBinding::Lifetime(lt) => {
269 WherePredicateBinding::Lifetime(lt.replace_type_params(map))
270 }
271 WherePredicateBinding::Type(pt) => {
272 WherePredicateBinding::Type(pt.replace_type_params(map))
273 }
274 WherePredicateBinding::Eq {
275 lhs_ty,
276 eq_token,
277 rhs_ty,
278 } => WherePredicateBinding::Eq {
279 lhs_ty: lhs_ty.replace_type_params(map.clone()),
280 eq_token,
281 rhs_ty: rhs_ty.replace_type_params(map),
282 },
283 }
284 }
285 }
286 impl ReplaceTypeParams for PredicateType {
287 fn replace_type_params(mut self, map: HashMap<Ident, Type>) -> Self {
288 let mut visitor = Visitor(map);
289 visitor.visit_predicate_type_mut(&mut self);
290 self
291 }
292 }
293 impl ReplaceTypeParams for PredicateLifetime {
294 fn replace_type_params(mut self, map: HashMap<Ident, Type>) -> Self {
295 let mut visitor = Visitor(map);
296 visitor.visit_predicate_lifetime_mut(&mut self);
297 self
298 }
299 }
300 impl ReplaceTypeParams for ImplItemFn {
301 fn replace_type_params(mut self, map: HashMap<Ident, Type>) -> Self {
302 let mut visitor = Visitor(map);
303 visitor.visit_impl_item_fn_mut(&mut self);
304 self
305 }
306 }
307 impl ReplaceTypeParams for Type {
308 fn replace_type_params(mut self, map: HashMap<Ident, Type>) -> Self {
309 let mut visitor = Visitor(map);
310 visitor.visit_type_mut(&mut self);
311 self
312 }
313 }
314};
315
316fn contains_generics_param(param: &GenericParam, ty: &Type) -> bool {
317 use syn::visit::Visit;
318 struct Visitor<'a>(&'a GenericParam, bool);
319 impl<'ast, 'a> Visit<'ast> for Visitor<'a> {
320 fn visit_lifetime(&mut self, i: &Lifetime) {
321 if matches!(&self.0, GenericParam::Lifetime(l) if &l.lifetime == i) {
322 self.1 = true;
323 }
324 }
325 fn visit_type_path(&mut self, i: &TypePath) {
326 if matches!(
327 (&self.0, &i.qself, i.path.get_ident()),
328 (GenericParam::Type(TypeParam {ident, ..}), &None, Some(id)) |
329 (GenericParam::Const(ConstParam {ident, ..}), &None, Some(id))
330 if ident == id
331 ) {
332 self.1 = true;
333 } else {
334 syn::visit::visit_type_path(self, i)
335 }
336 }
337 }
338 let mut visitor = Visitor(param, false);
339 visitor.visit_type(ty);
340 visitor.1
341}
342
343fn generic_param_key(p: &GenericParam) -> String {
345 match p {
346 GenericParam::Lifetime(l) => format!("'{}", l.lifetime.ident),
347 GenericParam::Type(t) => t.ident.to_string(),
348 GenericParam::Const(c) => c.ident.to_string(),
349 }
350}
351
352fn param_in_sig(p: &GenericParam, sig: &Signature) -> bool {
355 let used = |ty: &Type| contains_generics_param(p, ty);
356 sig.inputs.iter().any(|arg| match arg {
357 FnArg::Typed(pt) => used(&pt.ty),
358 FnArg::Receiver(r) => used(&r.ty),
359 }) || matches!(&sig.output, ReturnType::Type(_, ty) if used(ty))
360}
361
362fn specialize_item_fn_trait(
363 impl_: &ItemImpl,
364 extra_generics: &Punctuated<GenericParam, Token![,]>,
365 ident: &Ident,
366 fn_ident: &Ident,
367 impl_item_fn: &ImplItemFn,
368 needs_sized_bound: bool,
369 self_ty: &Type,
370) -> (TokenStream, Punctuated<GenericParam, Token![,]>) {
371 let trait_path = &impl_.trait_.as_ref().unwrap().1;
372 let trait_ty = Type::Path(TypePath {
373 qself: None,
374 path: trait_path.clone(),
375 });
376
377 let mut item_fn = replace_type_of_trait_item_fn(
378 TraitItemFn {
379 attrs: vec![],
380 sig: impl_item_fn.sig.clone(),
381 default: None,
382 semi_token: Some(Default::default()),
383 },
384 &impl_.self_ty,
385 &parse_quote!(Self),
386 );
387 item_fn.sig.ident = fn_ident.clone();
388 set_argument_named(&mut item_fn.sig);
392
393 let mut pool: Vec<GenericParam> = Vec::new();
397 for p in impl_.generics.params.iter().chain(extra_generics.iter()) {
398 let key = generic_param_key(p);
399 if !pool.iter().any(|q| generic_param_key(q) == key) {
400 pool.push(p.clone());
401 }
402 }
403
404 let impl_generics: Punctuated<_, Token![,]> = pool
407 .iter()
408 .filter(|p| contains_generics_param(p, &trait_ty) || contains_generics_param(p, self_ty))
409 .cloned()
410 .collect();
411 let mut method_extra_lifetimes: Vec<GenericParam> = pool
415 .iter()
416 .filter(|p| matches!(p, GenericParam::Lifetime(_)))
417 .filter(|p| {
418 param_in_sig(p, &item_fn.sig)
419 && !impl_generics
420 .iter()
421 .any(|q| generic_param_key(q) == generic_param_key(p))
422 })
423 .cloned()
424 .collect();
425 for p in &mut method_extra_lifetimes {
426 if let GenericParam::Lifetime(l) = p {
427 l.attrs.clear();
428 l.colon_token = None;
429 l.bounds = Punctuated::new();
430 }
431 }
432 let ty_generics: Punctuated<_, Token![,]> = pool
433 .iter()
434 .filter(|p| contains_generics_param(p, &trait_ty))
435 .map(|p| {
436 let mut p = p.clone();
437 match &mut p {
438 GenericParam::Lifetime(p) => {
439 p.attrs = Vec::new();
440 p.colon_token = None;
441 p.bounds = Punctuated::new();
442 }
443 GenericParam::Type(t) => {
444 t.attrs = Vec::new();
445 t.colon_token = None;
446 t.bounds = Punctuated::new();
447 t.eq_token = None;
448 t.default = None;
449 }
450 GenericParam::Const(c) => {
451 c.attrs = Vec::new();
452 c.eq_token = None;
453 c.default = None;
454 }
455 }
456 p
457 })
458 .collect();
459 let mut impl_item_fn = impl_item_fn.clone();
460 impl_item_fn.defaultness = None;
461 impl_item_fn.sig.ident = fn_ident.clone();
462 for lt in method_extra_lifetimes.into_iter().rev() {
465 item_fn.sig.generics.params.insert(0, lt.clone());
466 impl_item_fn.sig.generics.params.insert(0, lt);
467 }
468 let out = quote! {
469 trait #ident<#ty_generics>: #trait_path
470 #(if needs_sized_bound) { + ::core::marker::Sized }
471 {
472 #item_fn
473 }
474 impl<#impl_generics> #ident<#ty_generics> for #self_ty
475 #{&impl_.generics.where_clause}
476 {
477 #impl_item_fn
478 }
479 };
480 (out, ty_generics)
481}
482
483fn set_argument_named(sig: &mut Signature) {
493 for (n, arg) in sig.inputs.iter_mut().enumerate() {
494 if let FnArg::Typed(PatType { pat, .. }) = arg {
495 *pat = Box::new(Pat::Ident(PatIdent {
496 attrs: Vec::new(),
497 by_ref: None,
498 mutability: None,
499 ident: Ident::new(&format!("_min_specialization_v{}", n), pat.span()),
500 subpat: None,
501 }));
502 }
503 }
504}
505
506fn specialize_item_fn(
507 default_impl: &ItemImpl,
508 mut ifn: ImplItemFn,
509 specials: Vec<(HashMap<Ident, Type>, ItemImpl, ImplItemFn)>,
510 needs_sized_bound: bool,
511) -> ImplItemFn {
512 let itrait_name = Ident::new("__MinSpecialization_InnerTrait", Span::call_site());
513 let ifn_name = Ident::new("__min_specialization__inner_fn", Span::call_site());
514 let orig_ifn = ifn.clone();
517 set_argument_named(&mut ifn.sig);
518 let method_turbofish: TokenStream = {
524 let args: Vec<&Ident> = ifn
525 .sig
526 .generics
527 .params
528 .iter()
529 .filter_map(|p| match p {
530 GenericParam::Type(t) => Some(&t.ident),
531 GenericParam::Const(c) => Some(&c.ident),
532 GenericParam::Lifetime(_) => None,
533 })
534 .collect();
535 if args.is_empty() {
536 quote! {}
537 } else {
538 quote! { ::<#(#args),*> }
539 }
540 };
541 let specials_out = specials
542 .into_iter()
543 .enumerate()
544 .map(|(n, (m, simpl, mut sfn))| {
545 let strait_name = Ident::new(
546 &format!("__MinSpecialization_InnerTrait_{}", n),
547 Span::call_site(),
548 );
549 let sfn_name = Ident::new(
550 &format!("__min_specialization__inner_fn_{}", n),
551 Span::call_site(),
552 );
553 sfn.sig.ident = sfn_name.clone();
554 let mut condition = quote! {true};
555 let mut replacement = HashMap::new();
556 for (lhs, rhs) in m.iter() {
557 if let Some(rhs) = get_type_ident(rhs.clone()) {
558 if simpl
559 .generics
560 .params
561 .iter()
562 .filter_map(|p| {
563 if let GenericParam::Type(p) = p {
564 Some(&p.ident)
565 } else {
566 None
567 }
568 })
569 .any(|p| p == &rhs)
570 {
571 let lhs = Type::Path(TypePath {
572 qself: None,
573 path: Path {
574 leading_colon: None,
575 segments: Some(PathSegment {
576 ident: lhs.clone(),
577 arguments: PathArguments::None,
578 })
579 .into_iter()
580 .collect(),
581 },
582 });
583 replacement.insert(rhs, lhs);
584 continue;
585 }
586 }
587 let rhs = map_lifetimes(rhs.clone(), parse_quote!('static));
592 condition.extend(quote! {
593 && __min_specialization_type_id::<#lhs>()
594 == __min_specialization_type_id::<#rhs>()
595 });
596 }
597 let sfn = sfn.replace_type_params(replacement.clone());
598 let replaced_self_ty = default_impl.self_ty.clone().replace_type_params(m.clone());
599 let replaced_self_ty_call = map_lifetimes(replaced_self_ty.clone(), parse_quote!('_));
603 let (special_trait_impl, special_trait_params) = specialize_item_fn_trait(
604 default_impl,
605 &simpl.generics.params,
606 &strait_name,
607 &sfn_name,
608 &sfn,
609 needs_sized_bound,
610 &replaced_self_ty,
611 );
612 quote! {
613 if #condition {
614 #special_trait_impl
615 __min_specialization_transmute(
616 <#replaced_self_ty_call as #strait_name<
617 #(for par in &special_trait_params), {
618 #(if let GenericParam::Type(TypeParam{ident, ..}) = par) {
619 #(if let Some(ident) = replacement.get(ident)) {
620 #ident
621 }
622 #(else) {
623 #ident
624 }
625 } #(else) {
626 #par
627 }
628 }
629 >>::#sfn_name #{&method_turbofish}(
630 #(for arg in &ifn.sig.inputs), {
631 #(if let FnArg::Receiver(_) = arg) {
632 __min_specialization_transmute(self)
633 }
634 #(if let FnArg::Typed(pt) = arg) {
635 __min_specialization_transmute(#{&pt.pat})
636 }
637 }
638 )
639 )
640 } else
641 }
642 })
643 .collect::<Vec<_>>();
644 let no_extra_generics = Punctuated::new();
645 let (default_trait_impl, default_trait_params) = specialize_item_fn_trait(
646 default_impl,
647 &no_extra_generics,
648 &itrait_name,
649 &ifn_name,
650 &orig_ifn,
651 needs_sized_bound,
652 &default_impl.self_ty,
653 );
654 let inner = quote! {
655 #(for attr in &ifn.attrs) {#attr}
656 #{&ifn.vis}
657 #{&ifn.sig}
658 {
659 fn __min_specialization_type_id<T: ?::core::marker::Sized>() -> ::core::any::TypeId {
670 trait __MinSpecializationNonStaticAny {
671 fn __min_specialization_type_id(&self) -> ::core::any::TypeId
672 where
673 Self: 'static;
674 }
675 impl<T: ?::core::marker::Sized> __MinSpecializationNonStaticAny
676 for ::core::marker::PhantomData<T>
677 {
678 fn __min_specialization_type_id(&self) -> ::core::any::TypeId
679 where
680 Self: 'static,
681 {
682 ::core::any::TypeId::of::<T>()
683 }
684 }
685 let it = ::core::marker::PhantomData::<T>;
686 let it: &dyn __MinSpecializationNonStaticAny = ⁢
687 let it: &(dyn __MinSpecializationNonStaticAny + 'static) =
688 unsafe { ::core::mem::transmute(it) };
689 it.__min_specialization_type_id()
690 }
691 fn __min_specialization_transmute<T, U>(input: T) -> U {
696 ::core::assert_eq!(
697 ::core::mem::size_of::<T>(),
698 ::core::mem::size_of::<U>()
699 );
700 ::core::assert_eq!(
701 ::core::mem::align_of::<T>(),
702 ::core::mem::align_of::<U>()
703 );
704 let mut rhs = ::core::mem::MaybeUninit::new(input);
705 let mut lhs = ::core::mem::MaybeUninit::<U>::uninit();
706 unsafe {
707 let rhs = ::core::mem::transmute::<
708 _, &mut ::core::mem::MaybeUninit<U>
709 >(&mut rhs);
710 ::core::ptr::swap(lhs.as_mut_ptr(), rhs.as_mut_ptr());
711 lhs.assume_init()
712 }
713 }
714 #( #specials_out)*
715 {
716 #default_trait_impl
717 <#{&default_impl.self_ty} as #itrait_name<#default_trait_params>>::#ifn_name #{&method_turbofish}(
718 #(for arg in &ifn.sig.inputs),{
719 #(if let FnArg::Receiver(Receiver{self_token, ..}) = arg) {
720 #self_token
721 }
722 #(if let FnArg::Typed(PatType{pat, ..}) = arg) {
723 #pat
724 }
725 }
726 )
727 }
728 }
729 };
730 parse2(inner).unwrap_or_else(|e| {
731 abort!(
732 e.span(),
733 "#[specialization] generated code that failed to parse: {}", e;
734 note = "this is a bug in min-specialization; please report it with the offending impl"
735 )
736 })
737}
738
739fn check_needs_sized_bound(impl_: &ItemImpl) -> bool {
740 impl_
741 .items
742 .iter()
743 .filter_map(|item| {
744 if let ImplItem::Fn(item) = item {
745 Some(item)
746 } else {
747 None
748 }
749 })
750 .any(|item| {
751 item.sig
752 .inputs
753 .iter()
754 .filter_map(|item| {
755 if let FnArg::Typed(PatType { ty, .. }) = item {
756 Some(&*ty)
757 } else {
758 None
759 }
760 })
761 .chain(if let ReturnType::Type(_, ty) = &item.sig.output {
762 Some(&*ty)
763 } else {
764 None
765 })
766 .any(|ty| ty == &impl_.self_ty || ty == &parse_quote!(Self))
767 })
768}
769
770fn strip_defaultness(impl_: &mut ItemImpl) {
774 impl_.defaultness = None;
775 for item in impl_.items.iter_mut() {
776 match item {
777 ImplItem::Fn(f) => f.defaultness = None,
778 ImplItem::Const(c) => c.defaultness = None,
779 ImplItem::Type(t) => t.defaultness = None,
780 _ => {}
781 }
782 }
783}
784
785fn specialize_impl(
786 mut default_impl: ItemImpl,
787 special_impls: Vec<(ItemImpl, HashMap<Ident, Type>)>,
788) -> ItemImpl {
789 if special_impls.len() == 0 {
790 strip_defaultness(&mut default_impl);
793 return default_impl;
794 }
795 let needs_sized_bound = check_needs_sized_bound(&default_impl);
796 let default_fn_idents: HashSet<Ident> = default_impl
797 .items
798 .iter()
799 .filter_map(|item| match item {
800 ImplItem::Fn(ifn) => Some(ifn.sig.ident.clone()),
801 _ => None,
802 })
803 .collect();
804 let mut fn_map = HashMap::new();
805 for (simpl, ssub) in special_impls.into_iter() {
806 for item in simpl.items.iter() {
807 match item {
808 ImplItem::Fn(ifn) => {
809 if !default_fn_idents.contains(&ifn.sig.ident) {
812 abort!(
813 ifn.sig.ident.span(),
814 "`{}` is overridden in a specialization but is not defined in the \
815 default impl, so it cannot be specialized",
816 ifn.sig.ident;
817 help = "give the default impl a `default fn {}` to specialize",
818 ifn.sig.ident
819 );
820 }
821 fn_map
822 .entry(ifn.sig.ident.clone())
823 .or_insert(Vec::new())
824 .push((ssub.clone(), simpl.clone(), ifn.clone()));
825 }
826 o => abort!(o.span(), "This item cannot be specialized"),
827 }
828 }
829 }
830 let mut out = Vec::new();
831 for item in &default_impl.items {
832 match item {
833 ImplItem::Fn(ifn) => {
834 let specials = fn_map.get(&ifn.sig.ident).cloned().unwrap_or(Vec::new());
835 out.push(ImplItem::Fn(specialize_item_fn(
836 &default_impl,
837 ifn.clone(),
838 specials,
839 needs_sized_bound,
840 )));
841 }
842 o => out.push(o.clone()),
843 }
844 }
845 default_impl.items = out;
846 default_impl
847}
848
849fn specialize_trait(
850 default_impls: Vec<ItemImpl>,
851 special_impls: Vec<ItemImpl>,
852) -> (Vec<ItemImpl>, Vec<ItemImpl>) {
853 let mut default_specials: Vec<Vec<(ItemImpl, HashMap<Ident, Type>)>> =
854 default_impls.iter().map(|_| Vec::new()).collect();
855 let mut orphan_impls = Vec::new();
856 for s in special_impls.into_iter() {
857 let best = default_impls
861 .iter()
862 .enumerate()
863 .flat_map(|(i, d)| substitute_impl(d, &s).into_iter().map(move |(sub, n)| (i, sub, n)))
864 .min_by_key(|(_, _, n)| *n);
865 if let Some((i, sub, _)) = best {
866 default_specials[i].push((s, sub));
867 } else {
868 orphan_impls.push(s);
869 }
870 }
871 for specials in &default_specials {
876 for (i, (a, _)) in specials.iter().enumerate() {
877 for (b, _) in specials.iter().skip(i + 1) {
878 if a.trait_.as_ref().map(|t| &t.1) == b.trait_.as_ref().map(|t| &t.1)
879 && a.self_ty == b.self_ty
880 {
881 abort!(
882 b.span(),
883 "conflicting specializations: this impl overlaps another \
884 specialization of the same trait for the same type";
885 note = "min-specialization cannot order overlapping specializations"
886 );
887 }
888 }
889 }
890 }
891 let impls = default_impls
892 .into_iter()
893 .zip(default_specials)
894 .map(|(d, specials)| specialize_impl(d, specials))
895 .collect();
896 (impls, orphan_impls)
897}
898
899fn specialization_mod(module: ItemMod) -> TokenStream {
900 let (_, content) = if let Some(inner) = module.content {
901 inner
902 } else {
903 abort!(module.span(), "Require mod content")
904 };
905 let (mut defaults, mut specials): (Vec<ItemImpl>, Vec<ItemImpl>) = (Vec::new(), Vec::new());
909 let mut generated_content = Vec::new();
910 for item in content.into_iter() {
911 if let Item::Impl(item_impl) = &item {
912 if item_impl.trait_.is_some() {
913 if let Some(defaultness) = check_defaultness(&item_impl) {
914 if defaultness {
915 defaults.push(item_impl.clone());
916 } else {
917 specials.push(item_impl.clone());
918 }
919 continue;
920 }
921 }
922 }
923 generated_content.push(item);
924 }
925 let (impls, orphans) = specialize_trait(defaults, specials);
926 generated_content.extend(impls.into_iter().map(Item::Impl));
927 generated_content.extend(orphans.into_iter().map(Item::Impl));
928
929 quote! {
930 #(for attr in &module.attrs) { #attr }
931 #{&module.vis}
932 #{&module.mod_token}
933 #{&module.ident}
934 {
935 #(#generated_content)*
936 }
937 }
938}
939
940#[proc_macro_error]
1040#[proc_macro_attribute]
1041pub fn specialization(_attr: TokenStream1, input: TokenStream1) -> TokenStream1 {
1042 let module = parse_macro_input!(input);
1043 specialization_mod(module).into()
1044}