@@ -21,6 +21,8 @@ use crate::{
2121#[ derive( Debug , Default ) ]
2222pub struct Instantiator {
2323 cache : BTreeMap < Rc < ConcreteGlobalReference < ModuleUUID > > , InstantiatorCacheElem > ,
24+ /// Some mangled names may map to the same mangled name: `MyMod#(STR: "%")` and `MyMod#(STR: "/")` map to `MyMod_STR`.
25+ mangled_name_deconflicter : HashSet < String > ,
2426 stack : Vec < Rc < ConcreteGlobalReference < ModuleUUID > > > ,
2527 pub tops : Vec < ConcreteGlobalReference < ModuleUUID > > ,
2628}
@@ -46,13 +48,55 @@ impl Instantiator {
4648 pub fn new ( ) -> Self {
4749 Self {
4850 cache : BTreeMap :: new ( ) ,
51+ mangled_name_deconflicter : HashSet :: new ( ) ,
4952 stack : Vec :: new ( ) ,
5053 tops : Vec :: new ( ) ,
5154 }
5255 }
5356
5457 pub fn clear_instances ( & mut self ) {
55- self . cache . clear ( )
58+ self . cache . clear ( ) ;
59+ self . mangled_name_deconflicter . clear ( ) ;
60+ }
61+
62+ /// Mangle the module name for use in code generation
63+ fn mangle_name ( & mut self , name : & str ) -> String {
64+ let mut result = String :: with_capacity ( name. len ( ) ) ;
65+
66+ let mut last_was_underscore = false ;
67+ for c in name. chars ( ) {
68+ if c. is_alphanumeric ( ) {
69+ result. push ( c) ;
70+ last_was_underscore = false ;
71+ } else if c == '-' {
72+ result. push ( 'N' ) ;
73+ last_was_underscore = false ;
74+ } else {
75+ // Max 1 underscore at a time, as some tools don't like it (#128)
76+ if !last_was_underscore {
77+ result. push ( '_' ) ;
78+ }
79+ last_was_underscore = true ;
80+ }
81+ }
82+ result = result. trim_matches ( '_' ) . to_owned ( ) ;
83+
84+ if self . mangled_name_deconflicter . insert ( result. clone ( ) ) {
85+ // Try the non-deduplicated version first
86+ result
87+ } else {
88+ let mut dedup_idx = 2 ;
89+ loop {
90+ let deduplicated_name = format ! ( "{result}_Dedup_{dedup_idx}" ) ;
91+ if self
92+ . mangled_name_deconflicter
93+ . insert ( deduplicated_name. clone ( ) )
94+ {
95+ return deduplicated_name;
96+ } // Else, this deduplicated name is already taken. Try the next one
97+ dedup_idx += 1 ;
98+ }
99+ }
56100 }
57101
58102 pub fn display_cur_stack ( & self , globals : & LinkerGlobals ) -> impl Display {
@@ -109,7 +153,16 @@ impl Instantiator {
109153 let name = global_ref. display ( globals) . to_string ( ) ;
110154
111155 let result = crate :: debug:: debug_context ( "instantiating" , name, || {
112- match start_instantiation ( globals, linker_files, global_ref. clone ( ) ) {
156+ let name = global_ref. display ( globals) . to_string ( ) ;
157+ let mangled_name = self . mangle_name ( & name) ;
158+
159+ match start_instantiation (
160+ globals,
161+ linker_files,
162+ global_ref. clone ( ) ,
163+ name,
164+ mangled_name,
165+ ) {
113166 Ok ( mut context) => {
114167 loop {
115168 let submodules_to_instantiate = context. typecheck_step ( ) ;
@@ -208,6 +261,7 @@ impl Executed {
208261 md : & ' l Module ,
209262 global_ref : Rc < ConcreteGlobalReference < ModuleUUID > > ,
210263 name : String ,
264+ mangled_name : String ,
211265 ) -> ModuleTypingContext < ' l > {
212266 let errors = ErrorCollector :: new_empty ( md. link_info . span , linker_files) ;
213267 if let Err ( err) = self . execution_status {
@@ -222,7 +276,7 @@ impl Executed {
222276 & errors,
223277 ) ;
224278 ModuleTypingContext {
225- mangled_name : mangle_name ( & name ) ,
279+ mangled_name,
226280 name,
227281 global_ref,
228282 clocks,
@@ -237,39 +291,16 @@ impl Executed {
237291 }
238292}
239293
240- /// Mangle the module name for use in code generation
241- fn mangle_name ( str : & str ) -> String {
242- let mut result = String :: with_capacity ( str. len ( ) ) ;
243-
244- let mut last_was_underscore = false ;
245- for c in str. chars ( ) {
246- if c. is_alphanumeric ( ) {
247- result. push ( c) ;
248- last_was_underscore = false ;
249- } else if c == '-' {
250- result. push ( 'N' ) ;
251- last_was_underscore = false ;
252- } else {
253- // Max 1 underscore at a time, as some tools don't like it (#128)
254- if !last_was_underscore {
255- result. push ( '_' ) ;
256- }
257- last_was_underscore = true ;
258- }
259- }
260- result. trim_matches ( '_' ) . to_owned ( )
261- }
262-
263294#[ allow( clippy:: result_large_err) ]
264295fn start_instantiation < ' l > (
265296 linker_globals : & ' l LinkerGlobals ,
266297 linker_files : & ' l LinkerFiles ,
267298 global_ref : Rc < ConcreteGlobalReference < ModuleUUID > > ,
299+ name : String ,
300+ mangled_name : String ,
268301) -> Result < ModuleTypingSuperContext < ' l > , InstantiatedModule > {
269302 let md = & linker_globals. modules [ global_ref. id ] ;
270303
271- let name = global_ref. display ( linker_globals) . to_string ( ) ;
272-
273304 // Don't instantiate modules that already errored. Otherwise instantiator may crash
274305 if md. link_info . errors . did_error {
275306 let errors = ErrorCollector :: new_empty ( md. link_info . span , linker_files) ;
@@ -278,7 +309,7 @@ fn start_instantiation<'l>(
278309 errors. warn ( md. link_info . name_span , msg) ;
279310 return Err ( InstantiatedModule {
280311 global_ref,
281- mangled_name : mangle_name ( & name ) ,
312+ mangled_name,
282313 name,
283314 errors : errors. into_storage ( ) ,
284315 clocks : Default :: default ( ) ,
@@ -318,7 +349,7 @@ fn start_instantiation<'l>(
318349
319350 return Err ( InstantiatedModule {
320351 global_ref,
321- mangled_name : mangle_name ( & name ) ,
352+ mangled_name,
322353 name,
323354 errors : errors. into_storage ( ) ,
324355 clocks : Default :: default ( ) ,
@@ -335,7 +366,14 @@ fn start_instantiation<'l>(
335366 debug ! ( "Executing {name}" ) ;
336367 let exec = execute:: execute ( & md. link_info , linker_globals, & global_ref. template_args ) ;
337368
338- let typed = exec. into_module_typing_context ( linker_globals, linker_files, md, global_ref, name) ;
369+ let typed = exec. into_module_typing_context (
370+ linker_globals,
371+ linker_files,
372+ md,
373+ global_ref,
374+ name,
375+ mangled_name,
376+ ) ;
339377 let name = & typed. name ;
340378
341379 if typed. errors . did_error ( ) {
0 commit comments