Skip to main content

lust/embed/
native_types.rs

1use crate::ast::{
2    EnumDef, EnumVariant, FieldOwnership, FunctionDef, FunctionParam, ImplBlock, Span, StructDef,
3    StructField, TraitBound, TraitDef, TraitMethod, Type, TypeKind, Visibility,
4};
5use crate::typechecker::{FunctionSignature, TypeChecker};
6use crate::vm::VM;
7use crate::Result;
8use hashbrown::HashMap;
9use std::collections::BTreeMap;
10
11/// Aggregates Lust type declarations that originate from Rust.
12#[derive(Clone, Default)]
13pub struct ExternRegistry {
14    structs: Vec<StructDef>,
15    enums: Vec<EnumDef>,
16    traits: Vec<TraitDef>,
17    impls: Vec<ImplBlock>,
18    functions: Vec<FunctionDef>,
19    constants: Vec<(String, Type)>,
20}
21
22impl ExternRegistry {
23    pub fn new() -> Self {
24        Self::default()
25    }
26
27    pub fn add_struct(&mut self, def: StructDef) -> &mut Self {
28        self.structs.push(def);
29        self
30    }
31
32    pub fn add_enum(&mut self, def: EnumDef) -> &mut Self {
33        self.enums.push(def);
34        self
35    }
36
37    pub fn add_trait(&mut self, def: TraitDef) -> &mut Self {
38        self.traits.push(def);
39        self
40    }
41
42    pub fn add_impl(&mut self, impl_block: ImplBlock) -> &mut Self {
43        self.impls.push(impl_block);
44        self
45    }
46
47    pub fn add_function(&mut self, func: FunctionDef) -> &mut Self {
48        self.functions.push(func);
49        self
50    }
51
52    pub fn add_const(&mut self, name: impl Into<String>, ty: Type) -> &mut Self {
53        self.constants.push((name.into(), ty));
54        self
55    }
56
57    pub fn extend(&mut self, other: &ExternRegistry) {
58        self.structs.extend(other.structs.iter().cloned());
59        self.enums.extend(other.enums.iter().cloned());
60        self.traits.extend(other.traits.iter().cloned());
61        self.impls.extend(other.impls.iter().cloned());
62        self.functions.extend(other.functions.iter().cloned());
63        self.constants.extend(other.constants.iter().cloned());
64    }
65
66    pub fn register_with_typechecker(&self, checker: &mut TypeChecker) -> Result<()> {
67        for def in &self.structs {
68            checker.register_external_struct(def.clone())?;
69        }
70        for def in &self.enums {
71            checker.register_external_enum(def.clone())?;
72        }
73        for def in &self.traits {
74            checker.register_external_trait(def.clone())?;
75        }
76        for func in &self.functions {
77            checker.register_external_function(function_signature_for(func))?;
78        }
79        for impl_block in &self.impls {
80            checker.register_external_impl(impl_block.clone())?;
81        }
82        for (name, ty) in &self.constants {
83            checker.register_external_constant(name.clone(), ty.clone())?;
84        }
85        Ok(())
86    }
87
88    pub fn register_with_vm(&self, vm: &mut VM) {
89        self.register_struct_layouts(vm);
90        self.register_type_stubs(vm);
91    }
92
93    pub fn register_struct_layouts(&self, vm: &mut VM) {
94        let prefix = vm.export_prefix();
95        let mut struct_map: HashMap<String, StructDef> = HashMap::new();
96        for def in &self.structs {
97            let canonical = canonicalize_struct(def, prefix.as_deref());
98            struct_map.insert(canonical.name.clone(), canonical);
99        }
100        if !struct_map.is_empty() {
101            vm.register_structs(&struct_map);
102        }
103    }
104
105    pub fn register_type_stubs(&self, vm: &mut VM) {
106        if self.structs.is_empty()
107            && self.enums.is_empty()
108            && self.traits.is_empty()
109            && self.impls.is_empty()
110            && self.constants.is_empty()
111        {
112            return;
113        }
114        let prefix = vm.export_prefix();
115        vm.register_type_stubs(self.module_stubs_with_prefix(prefix.as_deref()));
116    }
117
118    pub fn module_stubs(&self) -> Vec<ModuleStub> {
119        self.module_stubs_with_prefix(None)
120    }
121
122    fn module_stubs_with_prefix(&self, prefix: Option<&str>) -> Vec<ModuleStub> {
123        let mut modules: BTreeMap<String, ModuleStub> = BTreeMap::new();
124        for def in &self.structs {
125            let canonical = canonicalize_struct(def, prefix);
126            if let Some((module, name)) = module_and_name(&canonical.name) {
127                let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
128                    module,
129                    ..ModuleStub::default()
130                });
131                entry.struct_defs.push(format_struct_def(name, &canonical));
132            }
133        }
134        for def in &self.enums {
135            let canonical = canonicalize_enum(def, prefix);
136            if let Some((module, name)) = module_and_name(&canonical.name) {
137                let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
138                    module,
139                    ..ModuleStub::default()
140                });
141                entry.enum_defs.push(format_enum_def(name, &canonical));
142            }
143        }
144        for def in &self.traits {
145            let canonical = canonicalize_trait(def, prefix);
146            if let Some((module, name)) = module_and_name(&canonical.name) {
147                let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
148                    module,
149                    ..ModuleStub::default()
150                });
151                entry.trait_defs.push(format_trait_def(name, &canonical));
152            }
153        }
154        for (name, ty) in &self.constants {
155            let canonical_name = canonicalize_simple_name(name, prefix);
156            if let Some((module, short)) = module_and_name(&canonical_name) {
157                let entry = modules.entry(module.clone()).or_insert_with(|| ModuleStub {
158                    module,
159                    ..ModuleStub::default()
160                });
161                entry
162                    .const_defs
163                    .push(format_const_def(short, &canonicalize_type(ty, prefix)));
164            }
165        }
166        for def in &self.impls {
167            let canonical = canonicalize_impl(def, prefix);
168            if let Some(module) = impl_module(&canonical) {
169                modules.entry(module.clone()).or_insert_with(|| ModuleStub {
170                    module,
171                    ..ModuleStub::default()
172                });
173            }
174        }
175        modules.into_values().collect()
176    }
177
178    pub fn structs(&self) -> impl Iterator<Item = &StructDef> {
179        self.structs.iter()
180    }
181
182    pub fn enums(&self) -> impl Iterator<Item = &EnumDef> {
183        self.enums.iter()
184    }
185}
186
187#[derive(Clone, Debug, Default)]
188pub struct ModuleStub {
189    pub module: String,
190    pub struct_defs: Vec<String>,
191    pub enum_defs: Vec<String>,
192    pub trait_defs: Vec<String>,
193    pub const_defs: Vec<String>,
194}
195
196impl ModuleStub {
197    pub fn is_empty(&self) -> bool {
198        self.struct_defs.is_empty()
199            && self.enum_defs.is_empty()
200            && self.trait_defs.is_empty()
201            && self.const_defs.is_empty()
202    }
203}
204
205#[derive(Clone)]
206pub struct StructBuilder {
207    def: StructDef,
208}
209
210impl StructBuilder {
211    pub fn new(name: impl Into<String>) -> Self {
212        StructBuilder {
213            def: StructDef {
214                name: name.into(),
215                type_params: Vec::new(),
216                trait_bounds: Vec::new(),
217                fields: Vec::new(),
218                visibility: Visibility::Public,
219            },
220        }
221    }
222
223    pub fn visibility(mut self, visibility: Visibility) -> Self {
224        self.def.visibility = visibility;
225        self
226    }
227
228    pub fn type_param(mut self, name: impl Into<String>) -> Self {
229        self.def.type_params.push(name.into());
230        self
231    }
232
233    pub fn trait_bound(mut self, bound: TraitBound) -> Self {
234        self.def.trait_bounds.push(bound);
235        self
236    }
237
238    pub fn field(mut self, field: StructField) -> Self {
239        self.def.fields.push(field);
240        self
241    }
242
243    pub fn finish(self) -> StructDef {
244        self.def
245    }
246}
247
248#[derive(Clone)]
249pub struct EnumBuilder {
250    def: EnumDef,
251}
252
253impl EnumBuilder {
254    pub fn new(name: impl Into<String>) -> Self {
255        EnumBuilder {
256            def: EnumDef {
257                name: name.into(),
258                type_params: Vec::new(),
259                trait_bounds: Vec::new(),
260                variants: Vec::new(),
261                visibility: Visibility::Public,
262            },
263        }
264    }
265
266    pub fn visibility(mut self, visibility: Visibility) -> Self {
267        self.def.visibility = visibility;
268        self
269    }
270
271    pub fn type_param(mut self, name: impl Into<String>) -> Self {
272        self.def.type_params.push(name.into());
273        self
274    }
275
276    pub fn trait_bound(mut self, bound: TraitBound) -> Self {
277        self.def.trait_bounds.push(bound);
278        self
279    }
280
281    pub fn variant(mut self, variant: EnumVariant) -> Self {
282        self.def.variants.push(variant);
283        self
284    }
285
286    pub fn finish(self) -> EnumDef {
287        self.def
288    }
289}
290
291#[derive(Clone)]
292pub struct TraitBuilder {
293    def: TraitDef,
294}
295
296impl TraitBuilder {
297    pub fn new(name: impl Into<String>) -> Self {
298        TraitBuilder {
299            def: TraitDef {
300                name: name.into(),
301                type_params: Vec::new(),
302                methods: Vec::new(),
303                visibility: Visibility::Public,
304            },
305        }
306    }
307
308    pub fn visibility(mut self, visibility: Visibility) -> Self {
309        self.def.visibility = visibility;
310        self
311    }
312
313    pub fn type_param(mut self, name: impl Into<String>) -> Self {
314        self.def.type_params.push(name.into());
315        self
316    }
317
318    pub fn method(mut self, method: TraitMethod) -> Self {
319        self.def.methods.push(method);
320        self
321    }
322
323    pub fn finish(self) -> TraitDef {
324        self.def
325    }
326}
327
328#[derive(Clone)]
329pub struct ImplBuilder {
330    block: ImplBlock,
331}
332
333impl ImplBuilder {
334    pub fn new(target_type: Type) -> Self {
335        ImplBuilder {
336            block: ImplBlock {
337                type_params: Vec::new(),
338                trait_name: None,
339                target_type,
340                methods: Vec::new(),
341                where_clause: Vec::new(),
342            },
343        }
344    }
345
346    pub fn for_trait(mut self, trait_name: impl Into<String>) -> Self {
347        self.block.trait_name = Some(trait_name.into());
348        self
349    }
350
351    pub fn type_param(mut self, name: impl Into<String>) -> Self {
352        self.block.type_params.push(name.into());
353        self
354    }
355
356    pub fn where_bound(mut self, bound: TraitBound) -> Self {
357        self.block.where_clause.push(bound);
358        self
359    }
360
361    pub fn method(mut self, method: FunctionDef) -> Self {
362        self.block.methods.push(method);
363        self
364    }
365
366    pub fn finish(self) -> ImplBlock {
367        self.block
368    }
369}
370
371#[derive(Clone)]
372pub struct TraitMethodBuilder {
373    method: TraitMethod,
374}
375
376impl TraitMethodBuilder {
377    pub fn new(name: impl Into<String>) -> Self {
378        TraitMethodBuilder {
379            method: TraitMethod {
380                name: name.into(),
381                type_params: Vec::new(),
382                params: Vec::new(),
383                return_type: None,
384                default_impl: None,
385            },
386        }
387    }
388
389    pub fn type_param(mut self, name: impl Into<String>) -> Self {
390        self.method.type_params.push(name.into());
391        self
392    }
393
394    pub fn param(mut self, param: FunctionParam) -> Self {
395        self.method.params.push(param);
396        self
397    }
398
399    pub fn return_type(mut self, ty: Type) -> Self {
400        self.method.return_type = Some(ty);
401        self
402    }
403
404    pub fn finish(self) -> TraitMethod {
405        self.method
406    }
407}
408
409#[derive(Clone)]
410pub struct FunctionBuilder {
411    function: FunctionDef,
412}
413
414impl FunctionBuilder {
415    pub fn new(name: impl Into<String>) -> Self {
416        let name = name.into();
417        FunctionBuilder {
418            function: FunctionDef {
419                name,
420                type_params: Vec::new(),
421                trait_bounds: Vec::new(),
422                params: Vec::new(),
423                return_type: None,
424                body: Vec::new(),
425                is_method: false,
426                visibility: Visibility::Public,
427            },
428        }
429    }
430
431    pub fn visibility(mut self, visibility: Visibility) -> Self {
432        self.function.visibility = visibility;
433        self
434    }
435
436    pub fn type_param(mut self, name: impl Into<String>) -> Self {
437        self.function.type_params.push(name.into());
438        self
439    }
440
441    pub fn trait_bound(mut self, bound: TraitBound) -> Self {
442        self.function.trait_bounds.push(bound);
443        self
444    }
445
446    pub fn param(mut self, param: FunctionParam) -> Self {
447        if param.is_self {
448            self.function.is_method = true;
449        }
450        self.function.params.push(param);
451        self
452    }
453
454    pub fn return_type(mut self, ty: Type) -> Self {
455        self.function.return_type = Some(ty);
456        self
457    }
458
459    pub fn finish(self) -> FunctionDef {
460        self.function
461    }
462}
463
464pub fn struct_field_decl(name: impl Into<String>, ty: Type) -> StructField {
465    StructField {
466        name: name.into(),
467        ty,
468        visibility: Visibility::Public,
469        ownership: FieldOwnership::Strong,
470        weak_target: None,
471    }
472}
473
474pub fn weak_struct_field_decl(name: impl Into<String>, ty: Type) -> StructField {
475    let span = ty.span;
476    let option = Type::new(TypeKind::Option(Box::new(ty.clone())), span);
477    StructField {
478        name: name.into(),
479        ty: option,
480        visibility: Visibility::Public,
481        ownership: FieldOwnership::Weak,
482        weak_target: Some(ty),
483    }
484}
485
486pub fn private_struct_field_decl(name: impl Into<String>, ty: Type) -> StructField {
487    StructField {
488        name: name.into(),
489        ty,
490        visibility: Visibility::Private,
491        ownership: FieldOwnership::Strong,
492        weak_target: None,
493    }
494}
495
496pub fn enum_variant(name: impl Into<String>) -> EnumVariant {
497    EnumVariant {
498        name: name.into(),
499        fields: None,
500    }
501}
502
503pub fn enum_variant_with(
504    name: impl Into<String>,
505    fields: impl IntoIterator<Item = Type>,
506) -> EnumVariant {
507    EnumVariant {
508        name: name.into(),
509        fields: Some(fields.into_iter().collect()),
510    }
511}
512
513pub fn trait_bound(
514    param: impl Into<String>,
515    traits: impl IntoIterator<Item = String>,
516) -> TraitBound {
517    TraitBound {
518        type_param: param.into(),
519        traits: traits.into_iter().collect(),
520    }
521}
522
523pub fn function_param(name: impl Into<String>, ty: Type) -> FunctionParam {
524    FunctionParam {
525        name: name.into(),
526        ty,
527        is_self: false,
528    }
529}
530
531pub fn self_param(ty: Option<Type>) -> FunctionParam {
532    FunctionParam {
533        name: "self".to_string(),
534        ty: ty.unwrap_or_else(|| Type::new(TypeKind::Infer, Span::dummy())),
535        is_self: true,
536    }
537}
538
539pub fn type_named(name: impl Into<String>) -> Type {
540    Type::new(TypeKind::Named(name.into()), Span::dummy())
541}
542
543pub fn type_unit() -> Type {
544    Type::new(TypeKind::Unit, Span::dummy())
545}
546
547pub fn type_unknown() -> Type {
548    Type::new(TypeKind::Unknown, Span::dummy())
549}
550
551fn function_signature_for(func: &FunctionDef) -> (String, FunctionSignature) {
552    let params: Vec<Type> = func.params.iter().map(|p| p.ty.clone()).collect();
553    let return_type = func
554        .return_type
555        .clone()
556        .unwrap_or_else(|| Type::new(TypeKind::Unit, Span::dummy()));
557    (
558        func.name.clone(),
559        FunctionSignature {
560            params,
561            return_type,
562            is_method: func.is_method,
563        },
564    )
565}
566
567fn module_and_name(name: &str) -> Option<(String, String)> {
568    if let Some((module, rest)) = name.rsplit_once("::") {
569        return Some((module.replace("::", "."), rest.to_string()));
570    }
571    if let Some((module, rest)) = name.rsplit_once('.') {
572        return Some((module.to_string(), rest.to_string()));
573    }
574    None
575}
576
577fn impl_module(impl_block: &ImplBlock) -> Option<String> {
578    match &impl_block.target_type.kind {
579        TypeKind::Named(name) => module_and_name(name).map(|(module, _)| module),
580        TypeKind::GenericInstance { name, .. } => module_and_name(name).map(|(module, _)| module),
581        _ => None,
582    }
583}
584
585fn format_struct_def(name: String, def: &StructDef) -> String {
586    let mut out = String::new();
587    if matches!(def.visibility, Visibility::Public) {
588        out.push_str("pub ");
589    }
590    out.push_str("struct ");
591    out.push_str(&name);
592    if !def.type_params.is_empty() {
593        out.push('<');
594        out.push_str(&def.type_params.join(", "));
595        out.push('>');
596    }
597    out.push('\n');
598    for field in &def.fields {
599        out.push_str("    ");
600        if matches!(field.visibility, Visibility::Public) {
601            out.push_str("pub ");
602        }
603        out.push_str(&field.name);
604        out.push_str(": ");
605        match field.ownership {
606            FieldOwnership::Weak => {
607                out.push_str("ref ");
608                if let Some(target) = &field.weak_target {
609                    out.push_str(&format_type(target));
610                } else {
611                    out.push_str(&format_type(&field.ty));
612                }
613            }
614            FieldOwnership::Strong => {
615                out.push_str(&format_type(&field.ty));
616            }
617        }
618        out.push('\n');
619    }
620    out.push_str("end\n");
621    out
622}
623
624fn format_enum_def(name: String, def: &EnumDef) -> String {
625    let mut out = String::new();
626    if matches!(def.visibility, Visibility::Public) {
627        out.push_str("pub ");
628    }
629    out.push_str("enum ");
630    out.push_str(&name);
631    if !def.type_params.is_empty() {
632        out.push('<');
633        out.push_str(&def.type_params.join(", "));
634        out.push('>');
635    }
636    out.push('\n');
637    for variant in &def.variants {
638        out.push_str("    ");
639        out.push_str(&variant.name);
640        if let Some(fields) = &variant.fields {
641            let parts: Vec<String> = fields.iter().map(format_type).collect();
642            out.push('(');
643            out.push_str(&parts.join(", "));
644            out.push(')');
645        }
646        out.push('\n');
647    }
648    out.push_str("end\n");
649    out
650}
651
652fn format_trait_def(name: String, def: &TraitDef) -> String {
653    let mut out = String::new();
654    if matches!(def.visibility, Visibility::Public) {
655        out.push_str("pub ");
656    }
657    out.push_str("trait ");
658    out.push_str(&name);
659    if !def.type_params.is_empty() {
660        out.push('<');
661        out.push_str(&def.type_params.join(", "));
662        out.push('>');
663    }
664    out.push('\n');
665    for method in &def.methods {
666        out.push_str("    ");
667        out.push_str(&format_trait_method(method));
668        out.push('\n');
669    }
670    out.push_str("end\n");
671    out
672}
673
674fn format_const_def(name: String, ty: &Type) -> String {
675    let mut out = String::new();
676    out.push_str("pub const ");
677    out.push_str(&name);
678    out.push_str(": ");
679    out.push_str(&format_type(ty));
680    out.push('\n');
681    out
682}
683
684fn format_trait_method(method: &TraitMethod) -> String {
685    let mut out = String::new();
686    out.push_str("function ");
687    out.push_str(&method.name);
688    if !method.type_params.is_empty() {
689        out.push('<');
690        out.push_str(&method.type_params.join(", "));
691        out.push('>');
692    }
693    out.push('(');
694    out.push_str(
695        &method
696            .params
697            .iter()
698            .map(format_param_signature)
699            .collect::<Vec<_>>()
700            .join(", "),
701    );
702    out.push(')');
703    if let Some(ret) = &method.return_type {
704        if !matches!(ret.kind, TypeKind::Unit) {
705            out.push_str(": ");
706            out.push_str(&format_type(ret));
707        }
708    }
709    out
710}
711
712fn format_param_signature(param: &FunctionParam) -> String {
713    if param.is_self {
714        return "self".to_string();
715    }
716    if matches!(param.ty.kind, TypeKind::Infer) {
717        param.name.clone()
718    } else {
719        format!("{}: {}", param.name, format_type(&param.ty))
720    }
721}
722
723fn format_type(ty: &Type) -> String {
724    match &ty.kind {
725        TypeKind::Named(name) => {
726            let (_, simple) =
727                module_and_name(name).unwrap_or_else(|| (String::new(), name.clone()));
728            if simple.is_empty() {
729                name.clone()
730            } else {
731                simple
732            }
733        }
734        TypeKind::GenericInstance { name, type_args } => {
735            let (_, simple) =
736                module_and_name(name).unwrap_or_else(|| (String::new(), name.clone()));
737            let args = type_args
738                .iter()
739                .map(format_type)
740                .collect::<Vec<_>>()
741                .join(", ");
742            format!("{}<{}>", simple, args)
743        }
744        _ => format!("{}", ty),
745    }
746}
747
748fn canonicalize_struct(def: &StructDef, prefix: Option<&str>) -> StructDef {
749    let mut cloned = def.clone();
750    cloned.name = canonicalize_simple_name(&cloned.name, prefix);
751    for field in &mut cloned.fields {
752        field.ty = canonicalize_type(&field.ty, prefix);
753        if let Some(target) = &field.weak_target {
754            field.weak_target = Some(canonicalize_type(target, prefix));
755        }
756    }
757    cloned
758}
759
760fn canonicalize_enum(def: &EnumDef, prefix: Option<&str>) -> EnumDef {
761    let mut cloned = def.clone();
762    cloned.name = canonicalize_simple_name(&cloned.name, prefix);
763    for variant in &mut cloned.variants {
764        if let Some(fields) = &mut variant.fields {
765            for field in fields {
766                *field = canonicalize_type(field, prefix);
767            }
768        }
769    }
770    cloned
771}
772
773fn canonicalize_trait(def: &TraitDef, prefix: Option<&str>) -> TraitDef {
774    let mut cloned = def.clone();
775    cloned.name = canonicalize_simple_name(&cloned.name, prefix);
776    for method in &mut cloned.methods {
777        for param in &mut method.params {
778            param.ty = canonicalize_type(&param.ty, prefix);
779        }
780        if let Some(ret) = method.return_type.clone() {
781            method.return_type = Some(canonicalize_type(&ret, prefix));
782        }
783    }
784    cloned
785}
786
787fn canonicalize_impl(def: &ImplBlock, prefix: Option<&str>) -> ImplBlock {
788    let mut cloned = def.clone();
789    cloned.target_type = canonicalize_type(&cloned.target_type, prefix);
790    let struct_name = match &cloned.target_type.kind {
791        TypeKind::Named(name) => name.clone(),
792        TypeKind::GenericInstance { name, .. } => name.clone(),
793        _ => cloned.target_type.to_string(),
794    };
795    if let Some(trait_name) = &cloned.trait_name {
796        cloned.trait_name = Some(canonicalize_simple_name(trait_name, prefix));
797    }
798    for method in &mut cloned.methods {
799        for param in &mut method.params {
800            param.ty = canonicalize_type(&param.ty, prefix);
801        }
802        if let Some(ret) = method.return_type.clone() {
803            method.return_type = Some(canonicalize_type(&ret, prefix));
804        }
805        if let Some((_, rest)) = method.name.split_once(':') {
806            method.name = format!("{}:{}", struct_name, rest);
807        } else if let Some((_, rest)) = method.name.split_once('.') {
808            method.name = format!("{}.{}", struct_name, rest);
809        } else {
810            method.name = format!("{}:{}", struct_name, method.name);
811        }
812        #[cfg(debug_assertions)]
813        eprintln!("canonicalized method name -> {}", method.name);
814    }
815    cloned
816}
817
818fn canonicalize_type(ty: &Type, prefix: Option<&str>) -> Type {
819    use TypeKind as TK;
820    let mut canonical = ty.clone();
821    canonical.kind = match &ty.kind {
822        TK::Named(name) => TK::Named(canonicalize_simple_name(name, prefix)),
823        TK::GenericInstance { name, type_args } => TK::GenericInstance {
824            name: canonicalize_simple_name(name, prefix),
825            type_args: type_args
826                .iter()
827                .map(|arg| canonicalize_type(arg, prefix))
828                .collect(),
829        },
830        TK::Array(inner) => TK::Array(Box::new(canonicalize_type(inner, prefix))),
831        TK::Option(inner) => TK::Option(Box::new(canonicalize_type(inner, prefix))),
832        TK::Result(ok, err) => TK::Result(
833            Box::new(canonicalize_type(ok, prefix)),
834            Box::new(canonicalize_type(err, prefix)),
835        ),
836        TK::Ref(inner) => TK::Ref(Box::new(canonicalize_type(inner, prefix))),
837        TK::MutRef(inner) => TK::MutRef(Box::new(canonicalize_type(inner, prefix))),
838        TK::Map(key, value) => TK::Map(
839            Box::new(canonicalize_type(key, prefix)),
840            Box::new(canonicalize_type(value, prefix)),
841        ),
842        TK::Tuple(elements) => TK::Tuple(
843            elements
844                .iter()
845                .map(|element| canonicalize_type(element, prefix))
846                .collect(),
847        ),
848        TK::Union(types) => TK::Union(
849            types
850                .iter()
851                .map(|variant| canonicalize_type(variant, prefix))
852                .collect(),
853        ),
854        other => other.clone(),
855    };
856    canonical
857}
858
859fn canonicalize_simple_name(name: &str, prefix: Option<&str>) -> String {
860    if name.is_empty() {
861        return name.to_string();
862    }
863    if is_qualified_name(name) {
864        return name.replace("::", ".");
865    }
866    if let Some(prefix) = prefix {
867        if prefix.is_empty() {
868            return name.to_string();
869        }
870        return format!("{}.{}", prefix, name);
871    }
872    name.to_string()
873}
874
875fn is_qualified_name(name: &str) -> bool {
876    name.contains('.') || name.contains("::")
877}