Skip to content

Commit bd8deb1

Browse files
committed
build: fix another source of hyperapp nondeterminism
1 parent 6e26ffb commit bd8deb1

1 file changed

Lines changed: 18 additions & 6 deletions

File tree

src/build/wit_generator.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,7 +1392,9 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
13921392

13931393
// Iteratively collect type definitions and their dependencies
13941394
while !types_to_collect.is_empty() {
1395-
let current_batch = types_to_collect.clone();
1395+
// Convert to sorted Vec for deterministic iteration order
1396+
let mut current_batch: Vec<String> = types_to_collect.iter().cloned().collect();
1397+
current_batch.sort();
13961398
types_to_collect.clear();
13971399

13981400
for type_name in current_batch {
@@ -1466,7 +1468,8 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
14661468
.filter(|ty| !is_wit_primitive_or_builtin(ty))
14671469
.cloned()
14681470
.collect();
1469-
to_process.sort();
1471+
// Sort in descending order so pop() returns items in ascending alphabetical order
1472+
to_process.sort_by(|a, b| b.cmp(a));
14701473

14711474
// First pass: collect all needed types and their dependencies
14721475
while let Some(type_name) = to_process.pop() {
@@ -1490,6 +1493,8 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
14901493
&& !to_process.contains(other_type_name)
14911494
{
14921495
to_process.push(other_type_name.clone());
1496+
// Re-sort in descending order for deterministic output
1497+
to_process.sort_by(|a, b| b.cmp(a));
14931498
}
14941499
}
14951500
}
@@ -1503,8 +1508,10 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
15031508
let mut sorted_types = Vec::new();
15041509
let mut in_degree: HashMap<String, usize> = HashMap::new();
15051510

1506-
// Initialize in-degrees
1507-
for type_name in &needed_types {
1511+
// Initialize in-degrees (sort for deterministic order)
1512+
let mut needed_types_sorted: Vec<String> = needed_types.iter().cloned().collect();
1513+
needed_types_sorted.sort();
1514+
for type_name in &needed_types_sorted {
15081515
in_degree.insert(type_name.clone(), 0);
15091516
}
15101517

@@ -1523,7 +1530,8 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
15231530
.filter(|(_, &degree)| degree == 0)
15241531
.map(|(name, _)| name.clone())
15251532
.collect();
1526-
queue.sort();
1533+
// Sort in descending order so pop() returns items in ascending alphabetical order
1534+
queue.sort_by(|a, b| b.cmp(a));
15271535

15281536
// Process queue
15291537
while let Some(type_name) = queue.pop() {
@@ -1536,6 +1544,8 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
15361544
*degree -= 1;
15371545
if *degree == 0 {
15381546
queue.push(dep.clone());
1547+
// Re-sort in descending order for deterministic output
1548+
queue.sort_by(|a, b| b.cmp(a));
15391549
}
15401550
}
15411551
}
@@ -1544,11 +1554,13 @@ fn process_rust_project(project_path: &Path, api_dir: &Path) -> Result<Option<(S
15441554

15451555
// Check for cycles
15461556
if sorted_types.len() != needed_types.len() {
1547-
let missing: Vec<String> = needed_types
1557+
let mut missing: Vec<String> = needed_types
15481558
.iter()
15491559
.filter(|t| !sorted_types.contains(t))
15501560
.cloned()
15511561
.collect();
1562+
// Sort for deterministic output order
1563+
missing.sort();
15521564
warn!(missing = ?missing, "Circular dependency detected in type definitions");
15531565
// Add remaining types anyway (WIT might still work)
15541566
for t in missing {

0 commit comments

Comments
 (0)