Skip to main content

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::*;
21
22/// Represents the results of cloning types and/or interfaces as part of a
23/// `Resolve::merge_worlds` operation.
24#[derive(Default, Clone)]
25pub struct CloneMaps {
26    pub(super) types: HashMap<TypeId, TypeId>,
27    pub(super) interfaces: HashMap<InterfaceId, InterfaceId>,
28}
29
30impl CloneMaps {
31    /// The types cloned during a `Resolve::merge_worlds` operation.
32    ///
33    /// The key is the original type, and the value is the clone.
34    pub fn types(&self) -> &HashMap<TypeId, TypeId> {
35        &self.types
36    }
37
38    /// The interfaces cloned during a `Resolve::merge_worlds` operation.
39    ///
40    /// The key is the original interface, and the value is the clone.
41    pub fn interfaces(&self) -> &HashMap<InterfaceId, InterfaceId> {
42        &self.interfaces
43    }
44}
45
46pub struct Cloner<'a> {
47    pub resolve: &'a mut Resolve,
48    pub maps: &'a mut CloneMaps,
49    prev_owner: TypeOwner,
50    new_owner: TypeOwner,
51
52    /// If `None` then it's inferred from `self.new_owner`.
53    pub new_package: Option<PackageId>,
54}
55
56impl<'a> Cloner<'a> {
57    pub fn new(
58        resolve: &'a mut Resolve,
59        maps: &'a mut CloneMaps,
60        prev_owner: TypeOwner,
61        new_owner: TypeOwner,
62    ) -> Cloner<'a> {
63        Cloner {
64            prev_owner,
65            new_owner,
66            resolve,
67            maps,
68            new_package: None,
69        }
70    }
71
72    pub fn register_world_type_overlap(&mut self, from: WorldId, into: WorldId) {
73        let into = &self.resolve.worlds[into];
74        let from = &self.resolve.worlds[from];
75        for (name, into_import) in into.imports.iter() {
76            let WorldKey::Name(_) = name else { continue };
77            let WorldItem::Type { id: into_id, .. } = into_import else {
78                continue;
79            };
80            let Some(WorldItem::Type { id: from_id, .. }) = from.imports.get(name) else {
81                continue;
82            };
83            self.maps.types.insert(*from_id, *into_id);
84        }
85    }
86
87    pub fn world_item(&mut self, key: &WorldKey, item: &mut WorldItem) {
88        match key {
89            WorldKey::Name(_) => {}
90            WorldKey::Interface(_) => return,
91        }
92
93        match item {
94            WorldItem::Type { id, .. } => {
95                self.type_id(id);
96            }
97            WorldItem::Function(f) => {
98                self.function(f);
99            }
100            WorldItem::Interface { id, .. } => {
101                // Only clone anonymous interfaces, for named interfaces they're
102                // left as-is for worlds.
103                if self.resolve.interfaces[*id].name.is_some() {
104                    return;
105                }
106                self.interface(id);
107            }
108        }
109    }
110
111    fn type_id(&mut self, ty: &mut TypeId) {
112        if !self.maps.types.contains_key(ty) {
113            let mut new = self.resolve.types[*ty].clone();
114            self.type_def(&mut new);
115            let id = self.resolve.types.alloc(new);
116            self.maps.types.insert(*ty, id);
117        }
118        *ty = self.maps.types[&*ty];
119    }
120
121    fn type_def(&mut self, def: &mut TypeDef) {
122        if def.owner != TypeOwner::None {
123            assert_eq!(def.owner, self.prev_owner);
124            def.owner = self.new_owner;
125        }
126        match &mut def.kind {
127            TypeDefKind::Type(Type::Id(id)) => {
128                if self.resolve.types[*id].owner == self.prev_owner {
129                    self.type_id(id);
130                } else if let Some(new_id) = self.maps.types.get(id) {
131                    *id = *new_id;
132                } else {
133                    // This type isn't owned by `self.prev_owner`, nor is there
134                    // a listed mapping for it. This most likely means that
135                    // `def` is equivalent to a `use` importing from another
136                    // interface and `id` is the type being imported. In this
137                    // situation it's left as-is to continue importing from
138                    // that interface.
139                }
140            }
141            TypeDefKind::Type(_)
142            | TypeDefKind::Resource
143            | TypeDefKind::Flags(_)
144            | TypeDefKind::Enum(_) => {}
145            TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
146                self.type_id(ty);
147            }
148            TypeDefKind::Option(ty)
149            | TypeDefKind::List(ty)
150            | TypeDefKind::FixedLengthList(ty, ..) => {
151                self.ty(ty);
152            }
153            TypeDefKind::Map(k, v) => {
154                self.ty(k);
155                self.ty(v);
156            }
157            TypeDefKind::Tuple(list) => {
158                for ty in list.types.iter_mut() {
159                    self.ty(ty);
160                }
161            }
162            TypeDefKind::Record(r) => {
163                for field in r.fields.iter_mut() {
164                    self.ty(&mut field.ty);
165                }
166            }
167            TypeDefKind::Variant(r) => {
168                for case in r.cases.iter_mut() {
169                    if let Some(ty) = &mut case.ty {
170                        self.ty(ty);
171                    }
172                }
173            }
174            TypeDefKind::Result(r) => {
175                if let Some(ok) = &mut r.ok {
176                    self.ty(ok);
177                }
178                if let Some(err) = &mut r.err {
179                    self.ty(err);
180                }
181            }
182            TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
183                if let Some(ty) = ty {
184                    self.ty(ty);
185                }
186            }
187            TypeDefKind::Unknown => {}
188        }
189    }
190
191    fn ty(&mut self, ty: &mut Type) {
192        match ty {
193            Type::Id(id) => self.type_id(id),
194            _ => {}
195        }
196    }
197
198    fn function(&mut self, func: &mut Function) {
199        if let Some(id) = func.kind.resource_mut() {
200            self.type_id(id);
201        }
202        for param in func.params.iter_mut() {
203            self.ty(&mut param.ty);
204        }
205        if let Some(ty) = &mut func.result {
206            self.ty(ty);
207        }
208    }
209
210    pub fn interface(&mut self, id: &mut InterfaceId) {
211        let old_id = *id;
212        let mut new = self.resolve.interfaces[old_id].clone();
213        let next_id = self.resolve.interfaces.next_id();
214        let mut clone = Cloner::new(
215            self.resolve,
216            self.maps,
217            TypeOwner::Interface(old_id),
218            TypeOwner::Interface(next_id),
219        );
220        for id in new.types.values_mut() {
221            clone.type_id(id);
222        }
223        for func in new.functions.values_mut() {
224            clone.function(func);
225        }
226        new.package = Some(self.new_package.unwrap_or_else(|| match self.new_owner {
227            TypeOwner::Interface(id) => self.resolve.interfaces[id].package.unwrap(),
228            TypeOwner::World(id) => self.resolve.worlds[id].package.unwrap(),
229            TypeOwner::None => unreachable!(),
230        }));
231        new.clone_of = Some(old_id);
232        *id = self.resolve.interfaces.alloc(new);
233        let prev = self.maps.interfaces.insert(old_id, next_id);
234        assert!(prev.is_none());
235        assert_eq!(*id, next_id);
236    }
237}