Coverage Report

Created: 2026-10-24 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wit-parser/src/resolve/clone.rs
Line
Count
Source
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
20
use 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)]
25
pub struct CloneMaps {
26
    pub(super) types: HashMap<TypeId, TypeId>,
27
    pub(super) interfaces: HashMap<InterfaceId, InterfaceId>,
28
}
29
30
impl 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
0
    pub fn types(&self) -> &HashMap<TypeId, TypeId> {
35
0
        &self.types
36
0
    }
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
0
    pub fn interfaces(&self) -> &HashMap<InterfaceId, InterfaceId> {
42
0
        &self.interfaces
43
0
    }
44
}
45
46
pub 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
56
impl<'a> Cloner<'a> {
57
22.1k
    pub fn new(
58
22.1k
        resolve: &'a mut Resolve,
59
22.1k
        maps: &'a mut CloneMaps,
60
22.1k
        prev_owner: TypeOwner,
61
22.1k
        new_owner: TypeOwner,
62
22.1k
    ) -> Cloner<'a> {
63
22.1k
        Cloner {
64
22.1k
            prev_owner,
65
22.1k
            new_owner,
66
22.1k
            resolve,
67
22.1k
            maps,
68
22.1k
            new_package: None,
69
22.1k
        }
70
22.1k
    }
71
72
6.46k
    pub fn register_world_type_overlap(&mut self, from: WorldId, into: WorldId) {
73
6.46k
        let into = &self.resolve.worlds[into];
74
6.46k
        let from = &self.resolve.worlds[from];
75
6.46k
        for (name, into_import) in into.imports.iter() {
76
0
            let WorldKey::Name(_) = name else { continue };
77
0
            let WorldItem::Type { id: into_id, .. } = into_import else {
78
0
                continue;
79
            };
80
0
            let Some(WorldItem::Type { id: from_id, .. }) = from.imports.get(name) else {
81
0
                continue;
82
            };
83
0
            self.maps.types.insert(*from_id, *into_id);
84
        }
85
6.46k
    }
86
87
14.8k
    pub fn world_item(&mut self, key: &WorldKey, item: &mut WorldItem) {
88
14.8k
        match key {
89
13.9k
            WorldKey::Name(_) => {}
90
862
            WorldKey::Interface(_) => return,
91
        }
92
93
13.9k
        match item {
94
2.36k
            WorldItem::Type { id, .. } => {
95
2.36k
                self.type_id(id);
96
2.36k
            }
97
1.76k
            WorldItem::Function(f) => {
98
1.76k
                self.function(f);
99
1.76k
            }
100
9.84k
            WorldItem::Interface { id, .. } => {
101
                // Only clone anonymous interfaces, for named interfaces they're
102
                // left as-is for worlds.
103
9.84k
                if self.resolve.interfaces[*id].name.is_some() {
104
9.06k
                    return;
105
784
                }
106
784
                self.interface(id);
107
            }
108
        }
109
14.8k
    }
110
111
60.5k
    fn type_id(&mut self, ty: &mut TypeId) {
112
60.5k
        if !self.maps.types.contains_key(ty) {
113
55.1k
            let mut new = self.resolve.types[*ty].clone();
114
55.1k
            self.type_def(&mut new);
115
55.1k
            let id = self.resolve.types.alloc(new);
116
55.1k
            self.maps.types.insert(*ty, id);
117
55.1k
        }
118
60.5k
        *ty = self.maps.types[&*ty];
119
60.5k
    }
120
121
55.1k
    fn type_def(&mut self, def: &mut TypeDef) {
122
55.1k
        if def.owner != TypeOwner::None {
123
33.0k
            assert_eq!(def.owner, self.prev_owner);
124
33.0k
            def.owner = self.new_owner;
125
22.1k
        }
126
376
        match &mut def.kind {
127
1.55k
            TypeDefKind::Type(Type::Id(id)) => {
128
1.55k
                if self.resolve.types[*id].owner == self.prev_owner {
129
12
                    self.type_id(id);
130
1.54k
                } else if let Some(new_id) = self.maps.types.get(id) {
131
18
                    *id = *new_id;
132
1.52k
                } else {
133
1.52k
                    // This type isn't owned by `self.prev_owner`, nor is there
134
1.52k
                    // a listed mapping for it. This most likely means that
135
1.52k
                    // `def` is equivalent to a `use` importing from another
136
1.52k
                    // interface and `id` is the type being imported. In this
137
1.52k
                    // situation it's left as-is to continue importing from
138
1.52k
                    // that interface.
139
1.52k
                }
140
            }
141
            TypeDefKind::Type(_)
142
            | TypeDefKind::Resource
143
            | TypeDefKind::Flags(_)
144
28.5k
            | TypeDefKind::Enum(_) => {}
145
376
            TypeDefKind::Handle(Handle::Own(ty) | Handle::Borrow(ty)) => {
146
376
                self.type_id(ty);
147
376
            }
148
5.00k
            TypeDefKind::Option(ty)
149
1.55k
            | TypeDefKind::List(ty)
150
7.07k
            | TypeDefKind::FixedLengthList(ty, ..) => {
151
7.07k
                self.ty(ty);
152
7.07k
            }
153
0
            TypeDefKind::Map(k, v) => {
154
0
                self.ty(k);
155
0
                self.ty(v);
156
0
            }
157
9.80k
            TypeDefKind::Tuple(list) => {
158
38.3k
                for ty in list.types.iter_mut() {
159
38.3k
                    self.ty(ty);
160
38.3k
                }
161
            }
162
1.60k
            TypeDefKind::Record(r) => {
163
7.35k
                for field in r.fields.iter_mut() {
164
7.35k
                    self.ty(&mut field.ty);
165
7.35k
                }
166
            }
167
928
            TypeDefKind::Variant(r) => {
168
5.16k
                for case in r.cases.iter_mut() {
169
5.16k
                    if let Some(ty) = &mut case.ty {
170
3.36k
                        self.ty(ty);
171
3.36k
                    }
172
                }
173
            }
174
1.69k
            TypeDefKind::Result(r) => {
175
1.69k
                if let Some(ok) = &mut r.ok {
176
1.40k
                    self.ty(ok);
177
1.40k
                }
178
1.69k
                if let Some(err) = &mut r.err {
179
1.23k
                    self.ty(err);
180
1.23k
                }
181
            }
182
2.53k
            TypeDefKind::Future(ty) | TypeDefKind::Stream(ty) => {
183
3.56k
                if let Some(ty) = ty {
184
3.43k
                    self.ty(ty);
185
3.43k
                }
186
            }
187
0
            TypeDefKind::Unknown => {}
188
        }
189
55.1k
    }
190
191
89.5k
    fn ty(&mut self, ty: &mut Type) {
192
89.5k
        match ty {
193
25.7k
            Type::Id(id) => self.type_id(id),
194
63.7k
            _ => {}
195
        }
196
89.5k
    }
197
198
6.17k
    fn function(&mut self, func: &mut Function) {
199
6.17k
        if let Some(id) = func.kind.resource_mut() {
200
1.39k
            self.type_id(id);
201
4.78k
        }
202
22.2k
        for param in func.params.iter_mut() {
203
22.2k
            self.ty(&mut param.ty);
204
22.2k
        }
205
6.17k
        if let Some(ty) = &mut func.result {
206
5.06k
            self.ty(ty);
207
5.06k
        }
208
6.17k
    }
209
210
8.22k
    pub fn interface(&mut self, id: &mut InterfaceId) {
211
8.22k
        let old_id = *id;
212
8.22k
        let mut new = self.resolve.interfaces[old_id].clone();
213
8.22k
        let next_id = self.resolve.interfaces.next_id();
214
8.22k
        let mut clone = Cloner::new(
215
8.22k
            self.resolve,
216
8.22k
            self.maps,
217
8.22k
            TypeOwner::Interface(old_id),
218
8.22k
            TypeOwner::Interface(next_id),
219
        );
220
30.6k
        for id in new.types.values_mut() {
221
30.6k
            clone.type_id(id);
222
30.6k
        }
223
8.22k
        for func in new.functions.values_mut() {
224
4.41k
            clone.function(func);
225
4.41k
        }
226
8.22k
        new.package = Some(self.new_package.unwrap_or_else(|| match self.new_owner {
227
0
            TypeOwner::Interface(id) => self.resolve.interfaces[id].package.unwrap(),
228
784
            TypeOwner::World(id) => self.resolve.worlds[id].package.unwrap(),
229
0
            TypeOwner::None => unreachable!(),
230
784
        }));
231
8.22k
        new.clone_of = Some(old_id);
232
8.22k
        *id = self.resolve.interfaces.alloc(new);
233
8.22k
        let prev = self.maps.interfaces.insert(old_id, next_id);
234
8.22k
        assert!(prev.is_none());
235
8.22k
        assert_eq!(*id, next_id);
236
8.22k
    }
237
}