wit_parser/resolve/
clone.rs

1//! A helper, non public, module to assist with cloning items within a
2//! `Resolve`.
3//!
4//! Cloning items is not as simple as calling `Clone` due to the nature of how
5//! `TypeId` tracks relationships between interfaces and types. A full deep
6//! clone requires walking the full structure and allocating new id links. This
7//! is akin to, for example, creating a deep copy of an `Rc<T>` by calling
8//! `Clone for T`.
9//!
10//! This is currently used when merging worlds together to help copy anonymously
11//! named items from one world to another.
12//!
13//! The general structure of this module is that each method takes a mutable
14//! reference to an AST item and updates it as necessary internally, delegating
15//! to other methods for internal AST items.
16//!
17//! This module does not at the time of this writing have full support for
18//! cloning everything within a `Resolve`.
19
20use crate::*;
21use std::collections::HashMap;
22
23pub struct Cloner<'a> {
24    resolve: &'a mut Resolve,
25    prev_owner: TypeOwner,
26    new_owner: TypeOwner,
27
28    /// This map keeps track, in the current scope of types, of all copied
29    /// types. This deduplicates copying types to ensure that they're only
30    /// copied at most once.
31    types: HashMap<TypeId, TypeId>,
32}
33
34impl<'a> Cloner<'a> {
35    pub fn new(
36        resolve: &'a mut Resolve,
37        prev_owner: TypeOwner,
38        new_owner: TypeOwner,
39    ) -> Cloner<'a> {
40        Cloner {
41            prev_owner,
42            new_owner,
43            resolve,
44            types: Default::default(),
45        }
46    }
47
48    pub fn register_world_type_overlap(&mut self, from: WorldId, into: WorldId) {
49        let into = &self.resolve.worlds[into];
50        let from = &self.resolve.worlds[from];
51        for (name, into_import) in into.imports.iter() {
52            let WorldKey::Name(_) = name else { continue };
53            let WorldItem::Type(into_id) = into_import else {
54                continue;
55            };
56            let Some(WorldItem::Type(from_id)) = from.imports.get(name) else {
57                continue;
58            };
59            self.types.insert(*from_id, *into_id);
60        }
61    }
62
63    pub fn world_item(&mut self, key: &WorldKey, item: &mut WorldItem) {
64        match key {
65            WorldKey::Name(_) => {}
66            WorldKey::Interface(_) => return,
67        }
68
69        match item {
70            WorldItem::Type(t) => {
71                self.type_id(t);
72            }
73            WorldItem::Function(f) => {
74                self.function(f);
75            }
76            WorldItem::Interface { id, .. } => {
77                self.interface(id);
78            }
79        }
80    }
81
82    fn type_id(&mut self, ty: &mut TypeId) {
83        if !self.types.contains_key(ty) {
84            let mut new = self.resolve.types[*ty].clone();
85            self.type_def(&mut new);
86            let id = self.resolve.types.alloc(new);
87            self.types.insert(*ty, id);
88        }
89        *ty = self.types[ty];
90    }
91
92    fn type_def(&mut self, def: &mut TypeDef) {
93        if def.owner != TypeOwner::None {
94            assert_eq!(def.owner, self.prev_owner);
95            def.owner = self.new_owner;
96        }
97        match &mut def.kind {
98            TypeDefKind::Type(Type::Id(id)) => {
99                if self.resolve.types[*id].owner == self.prev_owner {
100                    self.type_id(id);
101                } else {
102                    // ..
103                }
104            }
105            TypeDefKind::Type(_)
106            | TypeDefKind::Resource
107            | TypeDefKind::Flags(_)
108            | TypeDefKind::Enum(_) => {}
109            TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
110                self.type_id(ty);
111            }
112            TypeDefKind::Option(ty)
113            | TypeDefKind::List(ty)
114            | TypeDefKind::FixedSizeList(ty, ..) => {
115                self.ty(ty);
116            }
117            TypeDefKind::Tuple(list) => {
118                for ty in list.types.iter_mut() {
119                    self.ty(ty);
120                }
121            }
122            TypeDefKind::Record(r) => {
123                for field in r.fields.iter_mut() {
124                    self.ty(&mut field.ty);
125                }
126            }
127            TypeDefKind::Variant(r) => {
128                for case in r.cases.iter_mut() {
129                    if let Some(ty) = &mut case.ty {
130                        self.ty(ty);
131                    }
132                }
133            }
134            TypeDefKind::Result(r) => {
135                if let Some(ok) = &mut r.ok {
136                    self.ty(ok);
137                }
138                if let Some(err) = &mut r.err {
139                    self.ty(err);
140                }
141            }
142            TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
143                if let Some(ty) = ty {
144                    self.ty(ty);
145                }
146            }
147            TypeDefKind::Unknown => {}
148        }
149    }
150
151    fn ty(&mut self, ty: &mut Type) {
152        match ty {
153            Type::Id(id) => self.type_id(id),
154            _ => {}
155        }
156    }
157
158    fn function(&mut self, func: &mut Function) {
159        if let Some(id) = func.kind.resource_mut() {
160            self.type_id(id);
161        }
162        for (_, ty) in func.params.iter_mut() {
163            self.ty(ty);
164        }
165        if let Some(ty) = &mut func.result {
166            self.ty(ty);
167        }
168    }
169
170    fn interface(&mut self, id: &mut InterfaceId) {
171        let mut new = self.resolve.interfaces[*id].clone();
172        let next_id = self.resolve.interfaces.next_id();
173        let mut clone = Cloner::new(
174            self.resolve,
175            TypeOwner::Interface(*id),
176            TypeOwner::Interface(next_id),
177        );
178        for id in new.types.values_mut() {
179            clone.type_id(id);
180        }
181        for func in new.functions.values_mut() {
182            clone.function(func);
183        }
184        new.package = Some(match self.new_owner {
185            TypeOwner::Interface(id) => self.resolve.interfaces[id].package.unwrap(),
186            TypeOwner::World(id) => self.resolve.worlds[id].package.unwrap(),
187            TypeOwner::None => unreachable!(),
188        });
189        *id = self.resolve.interfaces.alloc(new);
190        assert_eq!(*id, next_id);
191    }
192}