1use self::generics_list::GenericsList;
2use scale_info::{form::PortableForm, Field, PortableRegistry, Type, TypeDef};
3use std::collections::{HashMap, HashSet};
4
5use crate::TypegenError;
6
7pub fn syn_type_path(ty: &Type<PortableForm>) -> Result<syn::TypePath, TypegenError> {
9 let joined_path = ty.path.segments.join("::");
10 let ty_path: syn::TypePath = syn::parse_str(&joined_path)?;
11 Ok(ty_path)
12}
13
14pub(crate) fn sanity_pass(types: &PortableRegistry) -> Result<(), TypegenError> {
15 for (idx, ty) in types.types.iter().enumerate() {
16 let idx = idx as u32;
17 if ty.id != idx {
18 return Err(TypegenError::RegistryTypeIdsInvalid {
19 given_ty_id: ty.id,
20 expected_ty_id: idx,
21 ty_def: format!("{:#?}", ty.ty),
22 });
23 }
24 }
25 Ok(())
26}
27
28pub fn ensure_unique_type_paths(types: &mut PortableRegistry) -> Result<(), TypegenError> {
30 sanity_pass(types)?;
31 let mut types_with_same_type_path_grouped_by_shape = HashMap::<&[String], Vec<Vec<u32>>>::new();
32
33 for (ty_idx, ty) in types.types.iter().enumerate() {
35 let ty_idx = ty_idx as u32;
40 let ty = &ty.ty;
41
42 if ty.path.namespace().is_empty() {
44 continue;
45 };
46
47 let groups_with_same_path = types_with_same_type_path_grouped_by_shape
49 .entry(&ty.path.segments)
50 .or_default();
51
52 let mut added_to_existing_group = false;
54 for group in groups_with_same_path.iter_mut() {
55 let other_ty_in_group_idx = group[0]; if types_equal(ty_idx, other_ty_in_group_idx, types) {
57 group.push(ty_idx);
58 added_to_existing_group = true;
59 break;
60 }
61 }
62
63 if !added_to_existing_group {
65 groups_with_same_path.push(vec![ty_idx])
66 }
67 }
68
69 let groups_that_need_renaming = types_with_same_type_path_grouped_by_shape
71 .into_values()
72 .filter(|g| g.len() > 1)
73 .collect::<Vec<_>>(); for groups_with_same_path in groups_that_need_renaming {
76 let mut n = 1;
77 for group_with_same_shape in groups_with_same_path {
78 for ty_id in group_with_same_shape {
79 let ty = types
80 .types
81 .get_mut(ty_id as usize)
82 .expect("type is present (2); qed;");
83 let name = ty.ty.path.segments.last_mut().expect("This is only empty for builtin types, that are filtered out with namespace().is_empty() above; qed;");
84 *name = format!("{name}{n}"); }
86 n += 1;
87 }
88 }
89 Ok(())
90}
91
92pub(crate) fn types_equal(a: u32, b: u32, types: &PortableRegistry) -> bool {
102 let mut a_visited = HashSet::new();
103 let mut b_visited = HashSet::new();
104 types_equal_inner(
105 a,
106 &GenericsList::empty(),
107 &mut a_visited,
108 b,
109 &GenericsList::empty(),
110 &mut b_visited,
111 types,
112 )
113}
114
115fn types_equal_inner(
117 a: u32,
118 a_parent_params: &GenericsList,
119 a_visited: &mut HashSet<u32>,
120 b: u32,
121 b_parent_params: &GenericsList,
122 b_visited: &mut HashSet<u32>,
123 types: &PortableRegistry,
124) -> bool {
125 if a == b {
127 return true;
128 }
129
130 let seen_a = !a_visited.insert(a);
132 let seen_b = !b_visited.insert(b);
133
134 if seen_a != seen_b {
137 return false;
138 }
139
140 if seen_a && seen_b {
143 return true;
144 }
145
146 let a_generic_idx = a_parent_params.index_for_type_id(a);
148 let b_generic_idx = b_parent_params.index_for_type_id(b);
149
150 let a_ty = types.resolve(a).expect("type a should exist in registry");
151 let b_ty = types.resolve(b).expect("type b should exist in registry");
152
153 let mut types_equal_recurse =
155 |a: u32, a_params: &GenericsList, b: u32, b_params: &GenericsList| -> bool {
156 types_equal_inner(a, a_params, a_visited, b, b_params, b_visited, types)
157 };
158
159 let calc_params = || {
161 let a_params = a_parent_params.extend(&a_ty.type_params);
162 let b_params = b_parent_params.extend(&b_ty.type_params);
163 (a_params, b_params)
164 };
165
166 if let (Some(a_idx), Some(b_idx)) = (a_generic_idx, b_generic_idx) {
170 if a_idx == b_idx {
171 return true;
172 }
173 }
174
175 if a_ty.path.segments != b_ty.path.segments {
177 return false;
178 }
179
180 #[rustfmt::skip]
181 let mut compare_fields = |
182 a: &Field<PortableForm>,
183 a_params: &GenericsList,
184 b: &Field<PortableForm>,
185 b_params: &GenericsList
186 | -> bool {
187 if a.name != b.name {
188 return false;
189 }
190
191 let ty_is_skipped_or_wrapped = a_params
194 .index_for_type_id(a.ty.id)
195 .zip(b_params.index_for_type_id(b.ty.id))
196 .is_none();
197
198 match (&a.type_name, &b.type_name) {
200 (Some(a_type_name), Some(b_type_name)) if !ty_is_skipped_or_wrapped => {
201 a_params
203 .index_for_type_name(a_type_name)
204 .zip(b_params.index_for_type_name(b_type_name))
205 .is_some_and(|(a, b)| a == b)
206 }
207 _ => types_equal_recurse(a.ty.id, a_params, b.ty.id, b_params),
208 }
209 };
210
211 #[rustfmt::skip]
213 let mut fields_equal = |
214 a: &[Field<PortableForm>],
215 a_params: &GenericsList,
216 b: &[Field<PortableForm>],
217 b_params: &GenericsList,
218 | -> bool {
219 if a.len() != b.len() {
220 return false;
221 }
222 a.iter().zip(b.iter()).all(|(a, b)| {
223 compare_fields(a, a_params, b, b_params)
224 })
225 };
226
227 match (&a_ty.type_def, &b_ty.type_def) {
229 (TypeDef::Composite(a), TypeDef::Composite(b)) => {
230 let (a_params, b_params) = calc_params();
231 fields_equal(&a.fields, &a_params, &b.fields, &b_params)
232 }
233 (TypeDef::Variant(a), TypeDef::Variant(b)) => {
234 let (a_params, b_params) = calc_params();
235 a.variants.len() == b.variants.len()
236 && a.variants.iter().zip(b.variants.iter()).all(|(a, b)| {
237 a.name == b.name && fields_equal(&a.fields, &a_params, &b.fields, &b_params)
238 })
239 }
240 (TypeDef::Sequence(a), TypeDef::Sequence(b)) => {
241 let (a_params, b_params) = calc_params();
242 types_equal_recurse(a.type_param.id, &a_params, b.type_param.id, &b_params)
243 }
244 (TypeDef::Array(a), TypeDef::Array(b)) => {
245 let (a_params, b_params) = calc_params();
246 a.len == b.len
247 && types_equal_recurse(a.type_param.id, &a_params, b.type_param.id, &b_params)
248 }
249 (TypeDef::Tuple(a), TypeDef::Tuple(b)) => {
250 let (a_params, b_params) = calc_params();
251 a.fields.len() == b.fields.len()
252 && a.fields
253 .iter()
254 .zip(b.fields.iter())
255 .all(|(a, b)| types_equal_recurse(a.id, &a_params, b.id, &b_params))
256 }
257 (TypeDef::Primitive(a), TypeDef::Primitive(b)) => a == b,
258 (TypeDef::Compact(a), TypeDef::Compact(b)) => {
259 let (a_params, b_params) = calc_params();
260 types_equal_recurse(a.type_param.id, &a_params, b.type_param.id, &b_params)
261 }
262 (TypeDef::BitSequence(a), scale_info::TypeDef::BitSequence(b)) => {
263 let (a_params, b_params) = calc_params();
264 let order_equal = types_equal_recurse(
265 a.bit_order_type.id,
266 &a_params,
267 b.bit_order_type.id,
268 &b_params,
269 );
270 let store_equal = types_equal_recurse(
271 a.bit_store_type.id,
272 &a_params,
273 b.bit_store_type.id,
274 &b_params,
275 );
276 order_equal && store_equal
277 }
278 _ => false,
280 }
281}
282
283mod generics_list {
286 use scale_info::{form::PortableForm, TypeParameter};
287 use std::rc::Rc;
288
289 #[derive(Clone, Debug)]
293 pub struct GenericsList {
294 inner: Rc<GenericsListInner>,
295 }
296
297 #[derive(Clone, Debug)]
298 struct GenericsListInner {
299 previous: Option<GenericsList>,
300 start_idx: usize,
301 generics_by_id: Vec<(u32, String)>,
302 }
303
304 impl GenericsList {
305 pub fn index_for_type_id(&self, type_id: u32) -> Option<usize> {
307 let maybe_index = self
308 .inner
309 .generics_by_id
310 .iter()
311 .position(|(id, _)| *id == type_id)
312 .map(|index| self.inner.start_idx + index);
313
314 maybe_index.or_else(|| {
316 self.inner
317 .previous
318 .as_ref()
319 .and_then(|prev| prev.index_for_type_id(type_id))
320 })
321 }
322 pub fn index_for_type_name(&self, name: &str) -> Option<usize> {
324 let maybe_index = self
325 .inner
326 .generics_by_id
327 .iter()
328 .position(|(_, type_name)| *type_name == name)
329 .map(|index| self.inner.start_idx + index);
330
331 maybe_index.or_else(|| {
333 self.inner
334 .previous
335 .as_ref()
336 .and_then(|prev| prev.index_for_type_name(name))
337 })
338 }
339
340 pub fn empty() -> Self {
342 Self::new_inner(None, &[])
343 }
344
345 pub fn extend(&self, params: &[TypeParameter<PortableForm>]) -> Self {
347 Self::new_inner(Some(self.clone()), params)
348 }
349
350 fn new_inner(
351 maybe_self: Option<GenericsList>,
352 params: &[TypeParameter<PortableForm>],
353 ) -> Self {
354 let generics_by_id = params
355 .iter()
356 .filter_map(|p| p.ty.map(|ty| (ty.id, p.name.clone())))
357 .collect();
358
359 let start_idx = match &maybe_self {
360 Some(list) => list.inner.start_idx + list.inner.generics_by_id.len(),
361 None => 0,
362 };
363
364 GenericsList {
365 inner: Rc::new(GenericsListInner {
366 previous: maybe_self,
367 start_idx,
368 generics_by_id,
369 }),
370 }
371 }
372 }
373}
374
375#[cfg(test)]
376mod tests {
377 use crate::typegen::ir::ToTokensWithSettings;
378 use pretty_assertions::assert_eq;
379
380 use super::*;
381 use quote::quote;
382 use scale_info::{
383 meta_type, Field, Path, PortableRegistry, TypeDef, TypeDefComposite, TypeInfo,
384 TypeParameter,
385 };
386
387 #[test]
388 fn associated_types_are_properly_deduplicated() {
389 trait X {
390 type Assoc;
391 }
392 struct A;
393 impl X for A {
394 type Assoc = u8;
395 }
396 struct B;
397 impl X for B {
398 type Assoc = u32;
399 }
400
401 #[derive(TypeInfo)]
402 #[scale_info(skip_type_params(T))] struct Foo<T: X> {
404 _field: T::Assoc,
405 }
406
407 #[allow(unused)]
408 #[derive(TypeInfo)]
409 struct Bar {
410 p: Foo<A>,
411 q: Foo<B>,
412 }
413
414 let mut registry = scale_info::Registry::new();
415 let _ = registry.register_type(&scale_info::meta_type::<Bar>()).id;
416 let mut registry = scale_info::PortableRegistry::from(registry);
417
418 ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
419
420 let settings = crate::TypeGeneratorSettings::new();
421 let generated = crate::typegen::ir::ToTokensWithSettings::to_token_stream(
422 &crate::TypeGenerator::new(®istry, &settings)
423 .generate_types_mod()
424 .unwrap(),
425 &settings,
426 );
427
428 let expected = quote!(
429 pub mod types {
430 use super::types;
431 pub mod scale_typegen {
432 use super::types;
433 pub mod utils {
434 use super::types;
435 pub mod tests {
436 use super::types;
437 pub struct Bar {
438 pub p: types::scale_typegen::utils::tests::Foo1,
439 pub q: types::scale_typegen::utils::tests::Foo2,
440 }
441 pub struct Foo1 {
442 pub _field: ::core::primitive::u8,
443 }
444 pub struct Foo2 {
445 pub _field: ::core::primitive::u32,
446 }
447 }
448 }
449 }
450 }
451 );
452
453 assert_eq!(expected.to_string(), generated.to_string());
454 }
455
456 #[test]
457 fn generics_unification() {
458 macro_rules! nested_type {
459 ($ty:ident, $generic:ty, $inner:ty) => {
460 struct $ty;
461 impl scale_info::TypeInfo for $ty {
462 type Identity = Self;
463 fn type_info() -> scale_info::Type {
464 scale_info::Type {
465 path: Path::new("ParamType", "my::module"),
466 type_params: vec![TypeParameter::new(
467 "T",
468 Some(meta_type::<$generic>()),
469 )],
470 type_def: TypeDef::Composite(TypeDefComposite::new([Field::new(
471 None,
472 meta_type::<$inner>(),
473 Some("T"),
474 Vec::new(),
475 )])),
476 docs: vec![],
477 }
478 }
479 }
480 };
481 }
482
483 struct A;
484 impl scale_info::TypeInfo for A {
485 type Identity = Self;
486 fn type_info() -> scale_info::Type {
487 scale_info::Type {
488 path: Path::new("NestedType", "my::module"),
489 type_params: vec![
490 TypeParameter::new("T", Some(meta_type::<u8>())),
491 TypeParameter::new("U", Some(meta_type::<u16>())),
492 TypeParameter::new("V", Some(meta_type::<u32>())),
493 ],
494 type_def: TypeDef::Composite(TypeDefComposite::new([
495 Field::new(None, meta_type::<u8>(), Some("T"), Vec::new()),
496 Field::new(None, meta_type::<u16>(), Some("U"), Vec::new()),
497 Field::new(None, meta_type::<u32>(), Some("V"), Vec::new()),
498 ])),
499 docs: vec![],
500 }
501 }
502 }
503
504 struct B;
505 impl scale_info::TypeInfo for B {
506 type Identity = Self;
507 fn type_info() -> scale_info::Type {
508 scale_info::Type {
509 path: Path::new("NestedType", "my::module"),
510 type_params: vec![
511 TypeParameter::new("T", Some(meta_type::<u8>())),
512 TypeParameter::new("U", Some(meta_type::<u16>())),
513 TypeParameter::new("V", Some(meta_type::<u32>())),
514 ],
515 type_def: TypeDef::Composite(TypeDefComposite::new([
516 Field::new(None, meta_type::<u32>(), Some("V"), Vec::new()),
517 Field::new(None, meta_type::<u16>(), Some("U"), Vec::new()),
518 Field::new(None, meta_type::<u8>(), Some("T"), Vec::new()),
519 ])),
520 docs: vec![],
521 }
522 }
523 }
524 struct BB;
525 impl scale_info::TypeInfo for BB {
526 type Identity = Self;
527 fn type_info() -> scale_info::Type {
528 scale_info::Type {
529 path: Path::new("NestedType", "my::module"),
530 type_params: vec![
531 TypeParameter::new("V", Some(meta_type::<u8>())),
532 TypeParameter::new("U", Some(meta_type::<u16>())),
533 TypeParameter::new("T", Some(meta_type::<u32>())),
534 ],
535 type_def: TypeDef::Composite(TypeDefComposite::new([
536 Field::new(None, meta_type::<u32>(), Some("T"), Vec::new()),
537 Field::new(None, meta_type::<u16>(), Some("U"), Vec::new()),
538 Field::new(None, meta_type::<u8>(), Some("V"), Vec::new()),
539 ])),
540 docs: vec![],
541 }
542 }
543 }
544
545 struct C;
546 impl scale_info::TypeInfo for C {
547 type Identity = Self;
548 fn type_info() -> scale_info::Type {
549 scale_info::Type {
550 path: Path::new("NestedType", "my::module"),
551 type_params: vec![
552 TypeParameter::new("A", Some(meta_type::<u8>())),
553 TypeParameter::new("D", Some(meta_type::<u16>())),
554 TypeParameter::new("B", Some(meta_type::<u32>())),
555 ],
556 type_def: TypeDef::Composite(TypeDefComposite::new([
557 Field::new(None, meta_type::<u8>(), Some("A"), Vec::new()),
558 Field::new(None, meta_type::<u16>(), Some("D"), Vec::new()),
559 Field::new(None, meta_type::<u32>(), Some("B"), Vec::new()),
560 ])),
561 docs: vec![],
562 }
563 }
564 }
565
566 struct D;
567 impl scale_info::TypeInfo for D {
568 type Identity = Self;
569 fn type_info() -> scale_info::Type {
570 scale_info::Type {
571 path: Path::new("Foo", "my::module"),
572 type_params: vec![TypeParameter::new("A", Some(meta_type::<u8>()))],
573 type_def: TypeDef::Composite(TypeDefComposite::new([Field::new(
574 None,
575 meta_type::<u8>(),
576 Some("A"),
577 Vec::new(),
578 )])),
579 docs: vec![],
580 }
581 }
582 }
583 struct E;
584 impl scale_info::TypeInfo for E {
585 type Identity = Self;
586 fn type_info() -> scale_info::Type {
587 scale_info::Type {
588 path: Path::new("Foo", "my::module"),
589 type_params: vec![TypeParameter::new("B", Some(meta_type::<u16>()))],
590 type_def: TypeDef::Composite(TypeDefComposite::new([Field::new(
591 None,
592 meta_type::<u16>(),
593 Some("B"),
594 Vec::new(),
595 )])),
596 docs: vec![],
597 }
598 }
599 }
600
601 let mut registry = scale_info::Registry::new();
602 let id_b = registry.register_type(&meta_type::<B>()).id;
603 let id_bb = registry.register_type(&meta_type::<BB>()).id;
604 let id_a = registry.register_type(&meta_type::<A>()).id;
605 let id_c = registry.register_type(&meta_type::<C>()).id;
606
607 let id_d = registry.register_type(&meta_type::<D>()).id;
608 let id_e = registry.register_type(&meta_type::<E>()).id;
609
610 nested_type!(Y, A, A);
611 nested_type!(W, B, B);
612 nested_type!(Z, C, C);
613
614 let id_y = registry.register_type(&meta_type::<Y>()).id;
615 let id_w = registry.register_type(&meta_type::<W>()).id;
616 let id_z = registry.register_type(&meta_type::<Z>()).id;
617
618 let mut registry = PortableRegistry::from(registry);
619
620 assert!(!types_equal(id_a, id_b, ®istry));
622 assert!(!types_equal(id_a, id_bb, ®istry));
623
624 assert!(types_equal(id_a, id_c, ®istry));
626
627 assert!(types_equal(id_d, id_e, ®istry));
629
630 assert!(types_equal(id_w, id_y, ®istry));
631 assert!(types_equal(id_z, id_y, ®istry));
632
633 ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
634 let settings = crate::TypeGeneratorSettings::new();
635 let output = crate::TypeGenerator::new(®istry, &settings)
636 .generate_types_mod()
637 .unwrap()
638 .to_token_stream(&settings);
639
640 let expected = quote! {
641 pub mod types {
642 use super::types;
643 pub mod my {
644 use super::types;
645 pub mod module {
646 use super::types;
647 pub struct Foo<_0>(pub _0, );
648 pub struct NestedType1<_0, _1, _2>(pub _2, pub _1, pub _0, );
649 pub struct NestedType2<_0, _1, _2>(pub _0, pub _1, pub _2, );
650 pub struct ParamType < _0 > (pub _0 ,) ;
651 }
652 }
653 }
654 };
655
656 assert_eq!(expected.to_string(), output.to_string())
657 }
658
659 #[test]
660 fn recursive_data() {
661 #[derive(TypeInfo)]
662 #[allow(dead_code)]
663 pub enum Test<A> {
664 None,
665 Many { inner: Vec<Self> },
666 Param(A),
667 }
668
669 #[derive(TypeInfo)]
670 #[allow(dead_code)]
671 pub struct TestStruct<A> {
672 param: A,
673 inner: Vec<Self>,
674 }
675
676 #[derive(TypeInfo)]
677 #[allow(dead_code)]
678 pub struct Foo<T> {
679 inner: Vec<T>,
680 }
681
682 #[derive(TypeInfo)]
683 #[allow(dead_code)]
684 pub enum FooEnum<T> {
685 None,
686 Go(Vec<T>),
687 }
688
689 let mut registry = scale_info::Registry::new();
690 let id_a = registry.register_type(&meta_type::<Test<u8>>()).id;
691 let id_b = registry.register_type(&meta_type::<Test<u32>>()).id;
692
693 let id_foo = registry.register_type(&meta_type::<Foo<u32>>()).id;
694
695 let id_foo_foo = registry
696 .register_type(&meta_type::<Foo<Foo<TestStruct<u32>>>>())
697 .id;
698
699 let id_foo_enum = registry.register_type(&meta_type::<FooEnum<u32>>()).id;
700 let id_foo_foo_enum = registry
701 .register_type(&meta_type::<FooEnum<FooEnum<TestStruct<u32>>>>())
702 .id;
703 let id_a_struct = registry.register_type(&meta_type::<TestStruct<u32>>()).id;
704 let id_b_struct = registry
705 .register_type(&meta_type::<TestStruct<TestStruct<u64>>>())
706 .id;
707
708 let registry = PortableRegistry::from(registry);
709
710 assert!(types_equal(id_foo, id_foo_foo, ®istry));
711 assert!(types_equal(id_foo_enum, id_foo_foo_enum, ®istry));
712
713 assert!(types_equal(id_a, id_b, ®istry));
714 assert!(types_equal(id_a_struct, id_b_struct, ®istry));
715
716 let settings = crate::TypeGeneratorSettings::new();
717 let output = crate::TypeGenerator::new(®istry, &settings)
718 .generate_types_mod()
719 .unwrap()
720 .to_token_stream(&settings);
721 let expected = quote! {
723 pub mod types {
724 use super::types;
725 pub mod scale_typegen {
726 use super::types;
727 pub mod utils {
728 use super::types;
729 pub mod tests {
730 use super::types;
731 pub struct Foo < _0 > {
732 pub inner : :: std :: vec :: Vec < _0 > ,
733 }
734 pub enum FooEnum < _0 > {
735 None ,
736 Go (:: std :: vec :: Vec < _0 > ,) ,
737 }
738 pub enum Test<_0> {
739 None,
740 Many {
741 inner: ::std::vec::Vec<
742 types::scale_typegen::utils::tests::Test<_0>
743 >,
744 },
745 Param(_0, ),
746 }
747 pub struct TestStruct<_0> {
748 pub param: _0,
749 pub inner: ::std::vec::Vec<
750 types::scale_typegen::utils::tests::TestStruct<_0>
751 >,
752 }
753 }
754 }
755 }
756 }
757 };
758
759 assert_eq!(expected.to_string(), output.to_string())
760 }
761 #[test]
762 fn ensure_unique_type_paths_test() {
763 macro_rules! foo {
764 ($ty:ident, $prim:ident ) => {
765 struct $ty;
766 impl scale_info::TypeInfo for $ty {
767 type Identity = Self;
768 fn type_info() -> scale_info::Type {
769 scale_info::Type {
770 path: Path::new("Foo", "my::module"),
771 type_params: vec![],
772 type_def: scale_info::TypeDef::Primitive(
773 scale_info::TypeDefPrimitive::$prim,
774 ),
775 docs: vec![],
776 }
777 }
778 }
779 };
780 }
781
782 foo!(Foo1, Bool);
783 foo!(Foo2, Bool);
784 foo!(Foo3, U32);
785 foo!(Foo4, U128);
786 foo!(Foo5, U128);
787 foo!(Foo6, U128);
788
789 let mut registry = scale_info::Registry::new();
790 let id_1 = registry.register_type(&meta_type::<Foo1>()).id;
791 let id_2 = registry.register_type(&meta_type::<Foo2>()).id;
792 let id_3 = registry.register_type(&meta_type::<Foo3>()).id;
793 let id_4 = registry.register_type(&meta_type::<Foo4>()).id;
794 let id_5 = registry.register_type(&meta_type::<Foo5>()).id;
795 let id_6 = registry.register_type(&meta_type::<Foo6>()).id;
796 let mut registry = PortableRegistry::from(registry);
797
798 let ident = |id: u32| registry.resolve(id).unwrap().path.ident().unwrap();
800 assert_eq!(ident(id_1), "Foo");
801 assert_eq!(ident(id_2), "Foo");
802 assert_eq!(ident(id_3), "Foo");
803 assert_eq!(ident(id_4), "Foo");
804 assert_eq!(ident(id_5), "Foo");
805 assert_eq!(ident(id_6), "Foo");
806
807 ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
809
810 let ident = |id: u32| registry.resolve(id).unwrap().path.ident().unwrap();
811 assert_eq!(ident(id_1), "Foo1");
812 assert_eq!(ident(id_2), "Foo1");
813 assert_eq!(ident(id_3), "Foo2");
814 assert_eq!(ident(id_4), "Foo3");
815 assert_eq!(ident(id_5), "Foo3");
816 assert_eq!(ident(id_6), "Foo3");
817 }
818
819 #[test]
820 fn types_equal_recursing_test() {
821 #[derive(TypeInfo)]
822 struct Foo<T> {
823 _inner: T,
824 }
825
826 macro_rules! nested_type {
827 ($ty:ident, $generic:ty, $inner:ty, $param_name:literal) => {
828 struct $ty;
829 impl scale_info::TypeInfo for $ty {
830 type Identity = Self;
831 fn type_info() -> scale_info::Type {
832 scale_info::Type {
833 path: Path::new("NestedType", "my::module"),
834 type_params: vec![TypeParameter::new(
835 $param_name,
836 Some(meta_type::<$generic>()),
837 )],
838 type_def: TypeDef::Composite(TypeDefComposite::new([Field::new(
839 None,
840 meta_type::<$inner>(),
841 None,
842 Vec::new(),
843 )])),
844 docs: vec![],
845 }
846 }
847 }
848 };
849 }
850
851 nested_type!(A, u32, u32, "T");
856 nested_type!(B, bool, bool, "T");
857 nested_type!(G, u64, u64, "B");
858
859 nested_type!(C, bool, Vec<bool>, "T");
864 nested_type!(D, u32, Vec<u32>, "T");
865
866 nested_type!(E, bool, Vec<Foo<bool>>, "T");
871 nested_type!(F, u32, Vec<Foo<u32>>, "T");
872
873 let mut registry = scale_info::Registry::new();
874 let id_a = registry.register_type(&meta_type::<A>()).id;
875 let id_b = registry.register_type(&meta_type::<B>()).id;
876 let id_c = registry.register_type(&meta_type::<C>()).id;
877 let id_d = registry.register_type(&meta_type::<D>()).id;
878 let id_e = registry.register_type(&meta_type::<E>()).id;
879 let id_f = registry.register_type(&meta_type::<F>()).id;
880 let id_g = registry.register_type(&meta_type::<G>()).id;
881
882 let mut registry = PortableRegistry::from(registry);
883
884 assert!(types_equal(id_a, id_b, ®istry));
887 assert!(types_equal(id_c, id_d, ®istry));
888 assert!(types_equal(id_e, id_f, ®istry));
889 assert!(types_equal(id_a, id_g, ®istry));
890
891 assert!(!types_equal(id_a, id_c, ®istry));
893 assert!(!types_equal(id_a, id_e, ®istry));
894 assert!(!types_equal(id_c, id_e, ®istry));
895
896 ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
899 let settings = crate::TypeGeneratorSettings::new();
900 let output = crate::TypeGenerator::new(®istry, &settings)
901 .generate_types_mod()
902 .unwrap()
903 .to_token_stream(&settings);
904
905 let expected = quote! {
910 pub mod types {
911 use super::types;
912 pub mod my {
913 use super::types;
914 pub mod module {
915 use super::types;
916 pub struct NestedType1<_0>(pub _0,);
917 pub struct NestedType2<_0>(pub ::std::vec::Vec<_0>,);
918 pub struct NestedType3<_0>(
919 pub ::std::vec::Vec<types::scale_typegen::utils::tests::Foo<_0> >,
920 );
921 }
922 }
923 pub mod scale_typegen {
924 use super::types;
925 pub mod utils {
926 use super::types;
927 pub mod tests {
928 use super::types;
929 pub struct Foo<_0> {
930 pub _inner: _0,
931 }
932 }
933 }
934 }
935 }
936 };
937
938 assert_eq!(output.to_string(), expected.to_string());
939 }
940}