Skip to content

Commit 599a4cd

Browse files
Remove the invariant that interfaces must be sorted (#2494)
Signed-off-by: Brian Hardock <brian.hardock@fermyon.com>
1 parent 31e9899 commit 599a4cd

File tree

5 files changed

+1
-217
lines changed

5 files changed

+1
-217
lines changed

crates/wit-component/tests/merge/topo-sort-needed/README.md

Lines changed: 0 additions & 14 deletions
This file was deleted.

crates/wit-component/tests/merge/topo-sort-needed/from/a.wit

Lines changed: 0 additions & 19 deletions
This file was deleted.

crates/wit-component/tests/merge/topo-sort-needed/into/a.wit

Lines changed: 0 additions & 7 deletions
This file was deleted.

crates/wit-component/tests/merge/topo-sort-needed/merge/bar.wit

Lines changed: 0 additions & 21 deletions
This file was deleted.

crates/wit-parser/src/resolve/mod.rs

Lines changed: 1 addition & 156 deletions
Original file line numberDiff line numberDiff line change
@@ -714,11 +714,6 @@ package {name} is defined in two different locations:\n\
714714

715715
log::trace!("now have {} packages", self.packages.len());
716716

717-
// Ensure the interfaces arena is in topological order after the
718-
// merge. Newly-added interfaces may have been appended after
719-
// existing interfaces that now depend on them.
720-
self.topologically_sort_interfaces(Some(&mut remap));
721-
722717
// Re-elaborate all worlds after the merge. Merging may have added
723718
// extra types to existing interfaces that introduce new interface
724719
// dependencies not yet present in the world's imports.
@@ -1598,149 +1593,6 @@ package {name} is defined in two different locations:\n\
15981593
pushed[id.index()] = true;
15991594
}
16001595

1601-
/// Rebuilds the interfaces arena in topological order and updates all
1602-
/// InterfaceId references throughout this `Resolve`.
1603-
///
1604-
/// After a merge, newly-added interfaces may appear after existing
1605-
/// interfaces that now depend on them. This method re-orders the
1606-
/// interfaces arena so that dependencies always precede dependents
1607-
/// within each package.
1608-
///
1609-
/// The optional `remap` is updated so that its interface entries reflect
1610-
/// the new interface IDs.
1611-
fn topologically_sort_interfaces(&mut self, remap: Option<&mut Remap>) {
1612-
// Compute a global topological order: iterate packages in topological
1613-
// order, and within each package topologically sort interfaces based
1614-
// on their `use`-type dependencies.
1615-
let mut order = Vec::with_capacity(self.interfaces.len());
1616-
let mut visited = vec![false; self.interfaces.len()];
1617-
1618-
for pkg_id in self.topological_packages() {
1619-
let pkg = &self.packages[pkg_id];
1620-
for (_, &iface_id) in pkg.interfaces.iter() {
1621-
self.visit_interface_topo(iface_id, pkg_id, &mut visited, &mut order);
1622-
}
1623-
}
1624-
1625-
// Also include interfaces that don't belong to any package (shouldn't
1626-
// normally happen, but be safe).
1627-
for (id, _) in self.interfaces.iter() {
1628-
if !visited[id.index()] {
1629-
order.push(id);
1630-
}
1631-
}
1632-
1633-
// Check if already in order — if so, skip the rebuild.
1634-
let already_sorted = order
1635-
.iter()
1636-
.zip(order.iter().skip(1))
1637-
.all(|(a, b)| a.index() < b.index());
1638-
if already_sorted {
1639-
return;
1640-
}
1641-
1642-
// Build old-to-new mapping.
1643-
let mut old_to_new: Vec<Option<InterfaceId>> = vec![None; self.interfaces.len()];
1644-
1645-
// Consume the old arena and put items into a vec for random access.
1646-
let old_arena = mem::take(&mut self.interfaces);
1647-
let mut items: Vec<Option<Interface>> = old_arena
1648-
.into_iter()
1649-
.map(|(_, iface)| Some(iface))
1650-
.collect();
1651-
1652-
// Rebuild the arena in topological order.
1653-
for &old_id in &order {
1654-
let iface = items[old_id.index()].take().unwrap();
1655-
let new_id = self.interfaces.alloc(iface);
1656-
old_to_new[old_id.index()] = Some(new_id);
1657-
}
1658-
1659-
// Helper closure to map an old InterfaceId to the new one.
1660-
let map_iface = |id: InterfaceId| -> InterfaceId { old_to_new[id.index()].unwrap() };
1661-
1662-
// Update all InterfaceId references throughout the Resolve.
1663-
1664-
// 1. Package::interfaces
1665-
for (_, pkg) in self.packages.iter_mut() {
1666-
for (_, id) in pkg.interfaces.iter_mut() {
1667-
*id = map_iface(*id);
1668-
}
1669-
}
1670-
1671-
// 2. Types: TypeOwner::Interface
1672-
for (_, ty) in self.types.iter_mut() {
1673-
if let TypeOwner::Interface(id) = &mut ty.owner {
1674-
*id = map_iface(*id);
1675-
}
1676-
}
1677-
1678-
// 3. Worlds: imports/exports with WorldKey::Interface and WorldItem::Interface
1679-
for (_, world) in self.worlds.iter_mut() {
1680-
let imports = mem::take(&mut world.imports);
1681-
for (key, mut item) in imports {
1682-
let new_key = match key {
1683-
WorldKey::Interface(id) => WorldKey::Interface(map_iface(id)),
1684-
other => other,
1685-
};
1686-
if let WorldItem::Interface { id, .. } = &mut item {
1687-
*id = map_iface(*id);
1688-
}
1689-
world.imports.insert(new_key, item);
1690-
}
1691-
let exports = mem::take(&mut world.exports);
1692-
for (key, mut item) in exports {
1693-
let new_key = match key {
1694-
WorldKey::Interface(id) => WorldKey::Interface(map_iface(id)),
1695-
other => other,
1696-
};
1697-
if let WorldItem::Interface { id, .. } = &mut item {
1698-
*id = map_iface(*id);
1699-
}
1700-
world.exports.insert(new_key, item);
1701-
}
1702-
}
1703-
1704-
// 4. Interface::clone_of
1705-
for (_, iface) in self.interfaces.iter_mut() {
1706-
if let Some(id) = &mut iface.clone_of {
1707-
*id = map_iface(*id);
1708-
}
1709-
}
1710-
1711-
// 5. Update the Remap if provided.
1712-
if let Some(remap) = remap {
1713-
for entry in remap.interfaces.iter_mut() {
1714-
if let Some(id) = entry {
1715-
*id = map_iface(*id);
1716-
}
1717-
}
1718-
}
1719-
}
1720-
1721-
/// Depth-first visit for topological sorting of interfaces within a package.
1722-
fn visit_interface_topo(
1723-
&self,
1724-
id: InterfaceId,
1725-
pkg_id: PackageId,
1726-
visited: &mut Vec<bool>,
1727-
order: &mut Vec<InterfaceId>,
1728-
) {
1729-
if visited[id.index()] {
1730-
return;
1731-
}
1732-
visited[id.index()] = true;
1733-
1734-
// Visit same-package dependencies first.
1735-
for dep in self.interface_direct_deps(id) {
1736-
if self.interfaces[dep].package == Some(pkg_id) {
1737-
self.visit_interface_topo(dep, pkg_id, visited, order);
1738-
}
1739-
}
1740-
1741-
order.push(id);
1742-
}
1743-
17441596
#[doc(hidden)]
17451597
pub fn assert_valid(&self) {
17461598
let mut package_interfaces = Vec::new();
@@ -1906,14 +1758,7 @@ package {name} is defined in two different locations:\n\
19061758
let my_package_pos = positions.get_index_of(&my_package).unwrap();
19071759
let other_package_pos = positions.get_index_of(&other_package).unwrap();
19081760

1909-
if my_package_pos == other_package_pos {
1910-
let interfaces = &positions[&my_package];
1911-
let my_interface_pos = interfaces.get_index_of(&my_interface).unwrap();
1912-
let other_interface_pos = interfaces.get_index_of(&other_interface).unwrap();
1913-
assert!(other_interface_pos <= my_interface_pos);
1914-
} else {
1915-
assert!(other_package_pos < my_package_pos);
1916-
}
1761+
assert!(other_package_pos <= my_package_pos);
19171762
}
19181763
}
19191764

0 commit comments

Comments
 (0)