diff --git a/Cargo.toml b/Cargo.toml index 3a38838..ca8cf7f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "naga_oil" -version = "0.12.0" +version = "0.13.0" edition = "2021" license = "MIT OR Apache-2.0" description = "a crate for combining and manipulating shaders using naga IR" diff --git a/src/compose/mod.rs b/src/compose/mod.rs index 0926766..483a751 100644 --- a/src/compose/mod.rs +++ b/src/compose/mod.rs @@ -1,3 +1,4 @@ +use indexmap::IndexMap; /// the compose module allows construction of shaders from modules (which are themselves shaders). /// /// it does this by treating shaders as modules, and @@ -235,7 +236,7 @@ pub struct ComposableModule { pub virtual_functions: HashSet, // overriding functions defined in this module // target function -> Vec - pub override_functions: HashMap>, + pub override_functions: IndexMap>, // naga module, built against headers for any imports module_ir: naga::Module, // headers in different shader languages, used for building modules/shaders that import this module @@ -397,7 +398,7 @@ const DECORATION_OVERRIDE_PRE: &str = "X_naga_oil_vrt_X"; struct IrBuildResult { module: naga::Module, start_offset: usize, - override_functions: HashMap>, + override_functions: IndexMap>, } impl Composer { @@ -583,7 +584,7 @@ impl Composer { ShaderLanguage::Glsl => String::from("#version 450\n"), }; - let mut override_functions: HashMap> = HashMap::default(); + let mut override_functions: IndexMap> = IndexMap::default(); let mut added_imports: HashSet = HashSet::new(); let mut header_module = DerivedModule::default(); @@ -611,7 +612,7 @@ impl Composer { if !module.override_functions.is_empty() { for (original, replacements) in &module.override_functions { match override_functions.entry(original.clone()) { - Entry::Occupied(o) => { + indexmap::map::Entry::Occupied(o) => { let existing = o.into_mut(); let new_replacements: Vec<_> = replacements .iter() @@ -620,7 +621,7 @@ impl Composer { .collect(); existing.extend(new_replacements); } - Entry::Vacant(v) => { + indexmap::map::Entry::Vacant(v) => { v.insert(replacements.clone()); } } @@ -723,7 +724,7 @@ impl Composer { })?, }; - let recompiled_types: HashMap<_, _> = recompiled + let recompiled_types: IndexMap<_, _> = recompiled .types .iter() .flat_map(|(h, ty)| ty.name.as_deref().map(|name| (name, h))) @@ -869,7 +870,7 @@ impl Composer { }); // record and rename override functions - let mut local_override_functions: HashMap = Default::default(); + let mut local_override_functions: IndexMap = Default::default(); #[cfg(not(feature = "override_any"))] let mut override_error = None; @@ -992,7 +993,7 @@ impl Composer { } // rename and record owned items (except types which can't be mutably accessed) - let mut owned_constants = HashMap::new(); + let mut owned_constants = IndexMap::new(); for (h, c) in source_ir.constants.iter_mut() { if let Some(name) = c.name.as_mut() { if !name.contains(DECORATION_PRE) { @@ -1002,7 +1003,7 @@ impl Composer { } } - let mut owned_vars = HashMap::new(); + let mut owned_vars = IndexMap::new(); for (h, gv) in source_ir.global_variables.iter_mut() { if let Some(name) = gv.name.as_mut() { if !name.contains(DECORATION_PRE) { @@ -1013,7 +1014,7 @@ impl Composer { } } - let mut owned_functions = HashMap::new(); + let mut owned_functions = IndexMap::new(); for (h_f, f) in source_ir.functions.iter_mut() { if let Some(name) = f.name.as_mut() { if !name.contains(DECORATION_PRE) { diff --git a/src/compose/parse_imports.rs b/src/compose/parse_imports.rs index 50d9384..9531504 100644 --- a/src/compose/parse_imports.rs +++ b/src/compose/parse_imports.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use indexmap::IndexMap; use super::{ tokenizer::{Token, Tokenizer}, @@ -7,7 +7,7 @@ use super::{ pub fn parse_imports<'a>( input: &'a str, - declared_imports: &mut HashMap>, + declared_imports: &mut IndexMap>, ) -> Result<(), (&'a str, usize)> { let mut tokens = Tokenizer::new(input, false).peekable(); @@ -116,8 +116,8 @@ pub fn parse_imports<'a>( pub fn substitute_identifiers( input: &str, offset: usize, - declared_imports: &HashMap>, - used_imports: &mut HashMap, + declared_imports: &IndexMap>, + used_imports: &mut IndexMap, allow_ambiguous: bool, ) -> Result { let tokens = Tokenizer::new(input, true); @@ -193,8 +193,8 @@ pub fn substitute_identifiers( } #[cfg(test)] -fn test_parse(input: &str) -> Result>, (&str, usize)> { - let mut declared_imports = HashMap::default(); +fn test_parse(input: &str) -> Result>, (&str, usize)> { + let mut declared_imports = IndexMap::default(); parse_imports(input, &mut declared_imports)?; Ok(declared_imports) } @@ -206,7 +206,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([( + Ok(IndexMap::from_iter([( "b".to_owned(), vec!("a::b".to_owned()) )])) @@ -217,7 +217,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("b".to_owned(), vec!("a::b".to_owned())), ("c".to_owned(), vec!("a::c".to_owned())), ])) @@ -228,7 +228,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("d".to_owned(), vec!("a::b".to_owned())), ("c".to_owned(), vec!("a::c".to_owned())), ])) @@ -239,7 +239,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("c".to_owned(), vec!("a::b::c".to_owned())), ("d".to_owned(), vec!("a::b::d".to_owned())), ("e".to_owned(), vec!("a::e".to_owned())), @@ -251,7 +251,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("c".to_owned(), vec!("a::b::c".to_owned())), ("d".to_owned(), vec!("a::b::d".to_owned())), ("e".to_owned(), vec!("e".to_owned())), @@ -263,7 +263,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("a".to_owned(), vec!("a".to_owned())), ("b".to_owned(), vec!("b".to_owned())), ])) @@ -274,7 +274,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("c".to_owned(), vec!("a::b::c".to_owned())), ("d".to_owned(), vec!("a::b::d".to_owned())), ])) @@ -285,7 +285,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([( + Ok(IndexMap::from_iter([( "c".to_owned(), vec!("a::b::c".to_owned()) ),])) @@ -296,7 +296,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("d".to_owned(), vec!("a::b::c::d".to_owned())), ("e".to_owned(), vec!("a::b::c::e".to_owned())), ("f".to_owned(), vec!("a::b::f".to_owned())), @@ -317,7 +317,7 @@ fn import_tokens() { "; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ("d".to_owned(), vec!("a::b::c::d".to_owned())), ("e".to_owned(), vec!("a::b::c::e".to_owned())), ("f".to_owned(), vec!("a::b::f".to_owned())), @@ -331,7 +331,7 @@ fn import_tokens() { "#; assert_eq!( test_parse(input), - Ok(HashMap::from_iter([ + Ok(IndexMap::from_iter([ ( "a".to_owned(), vec!(r#""path//with\ all sorts of .stuff"::a"#.to_owned()) diff --git a/src/compose/preprocess.rs b/src/compose/preprocess.rs index 869a8cb..45c3759 100644 --- a/src/compose/preprocess.rs +++ b/src/compose/preprocess.rs @@ -1,5 +1,6 @@ use std::collections::{HashMap, HashSet}; +use indexmap::IndexMap; use regex::Regex; use super::{ @@ -234,8 +235,8 @@ impl Preprocessor { shader_defs: &HashMap, validate_len: bool, ) -> Result { - let mut declared_imports = HashMap::new(); - let mut used_imports = HashMap::new(); + let mut declared_imports = IndexMap::new(); + let mut used_imports = IndexMap::new(); let mut scope = Scope::new(); let mut final_string = String::new(); let mut offset = 0; @@ -390,8 +391,8 @@ impl Preprocessor { shader_str: &str, allow_defines: bool, ) -> Result { - let mut declared_imports = HashMap::default(); - let mut used_imports = HashMap::default(); + let mut declared_imports = IndexMap::default(); + let mut used_imports = IndexMap::default(); let mut name = None; let mut offset = 0; let mut defines = HashMap::default(); diff --git a/src/compose/test.rs b/src/compose/test.rs index 2968812..846ac71 100644 --- a/src/compose/test.rs +++ b/src/compose/test.rs @@ -156,9 +156,6 @@ mod test { naga::back::wgsl::WriterFlags::EXPLICIT_TYPES, ) .unwrap(); - let mut wgsl: Vec<_> = wgsl.lines().collect(); - wgsl.sort(); - let wgsl = wgsl.join("\n"); // println!("{}", wgsl); // let mut f = std::fs::File::create("dup_import.txt").unwrap(); @@ -338,21 +335,11 @@ mod test { ) .unwrap(); - // unfortunately glsl variables are emitted in random order... - // so this is better than nothing - let mut wgsl: Vec<_> = wgsl.lines().collect(); - wgsl.sort(); - let wgsl = wgsl.join("\n"); - // let mut f = std::fs::File::create("wgsl_call_glsl.txt").unwrap(); // f.write_all(wgsl.as_bytes()).unwrap(); // drop(f); - // assert_eq!(wgsl, include_str!("tests/expected/wgsl_call_glsl.txt")); - - // actually it's worse than that ... glsl output seems volatile over struct names - // i suppose at least we are testing that it doesn't throw any errors ..? - let _ = wgsl; + output_eq!(wgsl, "tests/expected/wgsl_call_glsl.txt"); } #[cfg(feature = "glsl")] @@ -852,11 +839,6 @@ mod test { ) .unwrap(); - // println!("{}", wgsl); - let mut wgsl = wgsl.lines().collect::>(); - wgsl.sort(); - let wgsl = wgsl.join("\n"); - // let mut f = std::fs::File::create("item_import_test.txt").unwrap(); // f.write_all(wgsl.as_bytes()).unwrap(); // drop(f); @@ -923,9 +905,6 @@ mod test { naga::back::wgsl::WriterFlags::EXPLICIT_TYPES, ) .unwrap(); - let mut wgsl: Vec<_> = wgsl.lines().collect(); - wgsl.sort(); - let wgsl = wgsl.join("\n"); // let mut f = std::fs::File::create("bad_identifiers.txt").unwrap(); // f.write_all(wgsl.as_bytes()).unwrap(); @@ -992,9 +971,6 @@ mod test { naga::back::wgsl::WriterFlags::EXPLICIT_TYPES, ) .unwrap(); - let mut wgsl: Vec<_> = wgsl.lines().collect(); - wgsl.sort(); - let wgsl = wgsl.join("\n"); // let mut f = std::fs::File::create("dup_struct_import.txt").unwrap(); // f.write_all(wgsl.as_bytes()).unwrap(); diff --git a/src/compose/tests/expected/bad_identifiers.txt b/src/compose/tests/expected/bad_identifiers.txt index a5ed4aa..7cd10bd 100644 --- a/src/compose/tests/expected/bad_identifiers.txt +++ b/src/compose/tests/expected/bad_identifiers.txt @@ -1,39 +1,39 @@ +struct IsFineX_naga_oil_mod_XON2HE5LDORZQX { + fine: f32, +} +struct Isbad_X_naga_oil_mod_XON2HE5LDORZQX { + fine_member: f32, +} +const fineX_naga_oil_mod_XMNXW443UOMX: f32 = 1f; +const bad_X_naga_oil_mod_XMNXW443UOMX: f32 = 1f; +var fineX_naga_oil_mod_XM5WG6YTBNRZQX: f32 = 1f; +var bad_X_naga_oil_mod_XM5WG6YTBNRZQX: f32 = 1f; +fn fineX_naga_oil_mod_XMZXHGX(in: f32) -> f32 { + return in; +} +fn bad_X_naga_oil_mod_XMZXHGX(in_1: f32) -> f32 { + return in_1; +} +fn main() -> f32 { + var d: IsFineX_naga_oil_mod_XON2HE5LDORZQX; + var e: Isbad_X_naga_oil_mod_XON2HE5LDORZQX; - - d.fine = 3f; - e.fine_member = 4f; - fine: f32, - fine_member: f32, let _e1: f32 = fineX_naga_oil_mod_XMZXHGX(1f); - let _e20: f32 = d.fine; - let _e23: f32 = e.fine_member; let _e3: f32 = bad_X_naga_oil_mod_XMZXHGX(2f); + let b: f32 = (_e1 + _e3); let _e6: f32 = fineX_naga_oil_mod_XM5WG6YTBNRZQX; let _e8: f32 = bad_X_naga_oil_mod_XM5WG6YTBNRZQX; - let b: f32 = (_e1 + _e3); let c: f32 = (_e6 + _e8); + d.fine = 3f; + e.fine_member = 4f; + let _e20: f32 = d.fine; + let _e23: f32 = e.fine_member; return ((((2f + b) + c) + _e20) + _e23); - return in; - return in_1; - var d: IsFineX_naga_oil_mod_XON2HE5LDORZQX; - var e: Isbad_X_naga_oil_mod_XON2HE5LDORZQX; -const bad_X_naga_oil_mod_XMNXW443UOMX: f32 = 1f; -const fineX_naga_oil_mod_XMNXW443UOMX: f32 = 1f; -fn bad_X_naga_oil_mod_XMZXHGX(in_1: f32) -> f32 { -fn fineX_naga_oil_mod_XMZXHGX(in: f32) -> f32 { -fn main() -> f32 { -struct IsFineX_naga_oil_mod_XON2HE5LDORZQX { -struct Isbad_X_naga_oil_mod_XON2HE5LDORZQX { -var bad_X_naga_oil_mod_XM5WG6YTBNRZQX: f32 = 1f; -var fineX_naga_oil_mod_XM5WG6YTBNRZQX: f32 = 1f; -} } -} -} -} \ No newline at end of file + diff --git a/src/compose/tests/expected/dup_import.txt b/src/compose/tests/expected/dup_import.txt index be799a3..b0144db 100644 --- a/src/compose/tests/expected/dup_import.txt +++ b/src/compose/tests/expected/dup_import.txt @@ -1,16 +1,16 @@ +const PIX_naga_oil_mod_XMNXW443UOMX: f32 = 3.1f; +fn fX_naga_oil_mod_XMEX() -> f32 { + return 3.1f; +} +fn fX_naga_oil_mod_XMIX() -> f32 { + return 6.2f; +} - +fn main() -> f32 { let _e0: f32 = fX_naga_oil_mod_XMEX(); let _e1: f32 = fX_naga_oil_mod_XMIX(); return (_e0 * _e1); - return 3.1f; - return 6.2f; -const PIX_naga_oil_mod_XMNXW443UOMX: f32 = 3.1f; -fn fX_naga_oil_mod_XMEX() -> f32 { -fn fX_naga_oil_mod_XMIX() -> f32 { -fn main() -> f32 { } -} -} \ No newline at end of file + diff --git a/src/compose/tests/expected/dup_struct_import.txt b/src/compose/tests/expected/dup_struct_import.txt index 0f2611c..6827504 100644 --- a/src/compose/tests/expected/dup_struct_import.txt +++ b/src/compose/tests/expected/dup_struct_import.txt @@ -1,26 +1,26 @@ +struct MyStructX_naga_oil_mod_XON2HE5LDOQX { + value: f32, +} +fn aX_naga_oil_mod_XMEX() -> MyStructX_naga_oil_mod_XON2HE5LDOQX { + var s_a: MyStructX_naga_oil_mod_XON2HE5LDOQX; + s_a.value = 1f; + let _e3: MyStructX_naga_oil_mod_XON2HE5LDOQX = s_a; + return _e3; +} +fn bX_naga_oil_mod_XMIX() -> MyStructX_naga_oil_mod_XON2HE5LDOQX { + var s_b: MyStructX_naga_oil_mod_XON2HE5LDOQX; + s_b.value = 2f; + let _e3: MyStructX_naga_oil_mod_XON2HE5LDOQX = s_b; + return _e3; +} - +fn main() -> f32 { let _e0: MyStructX_naga_oil_mod_XON2HE5LDOQX = aX_naga_oil_mod_XMEX(); let _e1: MyStructX_naga_oil_mod_XON2HE5LDOQX = bX_naga_oil_mod_XMIX(); - let _e3: MyStructX_naga_oil_mod_XON2HE5LDOQX = s_a; - let _e3: MyStructX_naga_oil_mod_XON2HE5LDOQX = s_b; return (_e0.value / _e1.value); - return _e3; - return _e3; - s_a.value = 1f; - s_b.value = 2f; - value: f32, - var s_a: MyStructX_naga_oil_mod_XON2HE5LDOQX; - var s_b: MyStructX_naga_oil_mod_XON2HE5LDOQX; -fn aX_naga_oil_mod_XMEX() -> MyStructX_naga_oil_mod_XON2HE5LDOQX { -fn bX_naga_oil_mod_XMIX() -> MyStructX_naga_oil_mod_XON2HE5LDOQX { -fn main() -> f32 { -struct MyStructX_naga_oil_mod_XON2HE5LDOQX { -} } -} -} \ No newline at end of file + diff --git a/src/compose/tests/expected/item_import_test.txt b/src/compose/tests/expected/item_import_test.txt index 2f0600e..7d5306f 100644 --- a/src/compose/tests/expected/item_import_test.txt +++ b/src/compose/tests/expected/item_import_test.txt @@ -1,17 +1,17 @@ - - - - - let _e1: u32 = doubleX_naga_oil_mod_XMNXW443UOMX(XX_naga_oil_mod_XMNXW443UOMX); - let _e1: u32 = doubleX_naga_oil_mod_XMNXW443UOMX(YX_naga_oil_mod_XMNXW443UOMX); - return (in * 2u); - return _e1; - return _e1; const XX_naga_oil_mod_XMNXW443UOMX: u32 = 1u; const YX_naga_oil_mod_XMNXW443UOMX: u32 = 2u; + fn doubleX_naga_oil_mod_XMNXW443UOMX(in: u32) -> u32 { + return (in * 2u); +} + fn main() -> u32 { -fn other() -> u32 { + let _e1: u32 = doubleX_naga_oil_mod_XMNXW443UOMX(XX_naga_oil_mod_XMNXW443UOMX); + return _e1; } + +fn other() -> u32 { + let _e1: u32 = doubleX_naga_oil_mod_XMNXW443UOMX(YX_naga_oil_mod_XMNXW443UOMX); + return _e1; } -} \ No newline at end of file + diff --git a/src/compose/tests/expected/wgsl_call_glsl.txt b/src/compose/tests/expected/wgsl_call_glsl.txt index d5bec80..c70f907 100644 --- a/src/compose/tests/expected/wgsl_call_glsl.txt +++ b/src/compose/tests/expected/wgsl_call_glsl.txt @@ -1,48 +1,16 @@ +struct CustomMaterialX_naga_oil_mod_XM5WHG3C7NVXWI5LMMUX { + Color: vec4, +} +@group(1) @binding(0) +var global: CustomMaterialX_naga_oil_mod_XM5WHG3C7NVXWI5LMMUX; +fn glsl_funcX_naga_oil_mod_XM5WHG3C7NVXWI5LMMUX() -> f32 { + return 3f; +} - - - - - - @location(0) o_Target: vec4, - @location(0) o_Target: vec4, - Color: vec4, - _ = (&global.Color); - _ = (&global.Color); - _ = _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberv_Uv; - _naga_oil_mod_M5WHG3C7NVXWI5LMMU_membermain(); - _naga_oil_mod_M5WHG3C7NVXWI5LMMU_membero_Target = (_e6 * _e9); - _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberv_Uv = v_Uv; - let _e13: vec4 = _naga_oil_mod_M5WHG3C7NVXWI5LMMU_membero_Target; - let _e4: f32 = _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberglsl_func(); - let _e6: vec4 = global.Color; - let _e8: vec2 = _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberv_Uv; - let _e9: vec4 = textureSample(_naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberCustomMaterial_texture, _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberCustomMaterial_sampler, _e8); - return 3.0; - return _e4; - return type_5(_e13); - return; -@group(1) @binding(0) -@group(1) @binding(1) -@group(1) @binding(2) -fn _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberglsl_func() -> f32 { -fn _naga_oil_mod_M5WHG3C7NVXWI5LMMU_membermain() { -fn _naga_oil_mod_M5WHG3C7NVXWI5LMMU_membermain_1(@location(0) v_Uv: vec2) -> type_5 { fn fraggo() -> f32 { -struct _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberCustomMaterial { -struct type_5 { -struct type_5_ { -var _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberCustomMaterial_sampler: sampler; -var _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberCustomMaterial_texture: texture_2d; -var _naga_oil_mod_M5WHG3C7NVXWI5LMMU_membero_Target: vec4; -var _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberv_Uv: vec2; -var global: _naga_oil_mod_M5WHG3C7NVXWI5LMMU_memberCustomMaterial; -} -} + let _e0: f32 = glsl_funcX_naga_oil_mod_XM5WHG3C7NVXWI5LMMUX(); + return _e0; } -} -} -} -} \ No newline at end of file + diff --git a/src/derive.rs b/src/derive.rs index 5336915..42b79f1 100644 --- a/src/derive.rs +++ b/src/derive.rs @@ -4,7 +4,7 @@ use naga::{ FunctionResult, GlobalVariable, Handle, ImageQuery, LocalVariable, Module, SampleLevel, Span, Statement, StructMember, SwitchCase, Type, TypeInner, UniqueArena, }; -use std::{cell::RefCell, collections::HashMap, rc::Rc}; +use std::{cell::RefCell, rc::Rc}; use crate::compose::util::expression_eq; @@ -13,11 +13,11 @@ pub struct DerivedModule<'a> { shader: Option<&'a Module>, span_offset: usize, - type_map: HashMap, Handle>, - const_map: HashMap, Handle>, - const_expression_map: Rc, Handle>>>, - global_map: HashMap, Handle>, - function_map: HashMap>, + type_map: IndexMap, Handle>, + const_map: IndexMap, Handle>, + const_expression_map: Rc, Handle>>>, + global_map: IndexMap, Handle>, + function_map: IndexMap>, types: UniqueArena, constants: Arena, @@ -201,7 +201,7 @@ impl<'a> DerivedModule<'a> { &mut self, block: &Block, old_expressions: &Arena, - already_imported: Rc, Handle>>>, + already_imported: Rc, Handle>>>, new_expressions: Rc>>, ) -> Block { macro_rules! map_expr { @@ -388,7 +388,7 @@ impl<'a> DerivedModule<'a> { &mut self, h_expr: Handle, old_expressions: &Arena, - already_imported: Rc, Handle>>>, + already_imported: Rc, Handle>>>, new_expressions: Rc>>, non_emitting_only: bool, // only brings items that should NOT be emitted into scope unique: bool, // ensure expressions are unique with custom comparison @@ -635,7 +635,7 @@ impl<'a> DerivedModule<'a> { }); let expressions = Rc::new(RefCell::new(Arena::new())); - let expr_map = Rc::new(RefCell::new(HashMap::new())); + let expr_map = Rc::new(RefCell::new(IndexMap::new())); let mut local_variables = Arena::new(); for (h_l, l) in func.local_variables.iter() {