@@ -82,6 +82,42 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
8282 }
8383 }
8484
85+ /// Generate a fresh name that does not appear in `self.local_names`
86+ fn gen_fresh_name ( & mut self ) -> StringId {
87+ fn to_str ( x : u32 ) -> String {
88+ let base = x / 26 ;
89+ let letter = x % 26 ;
90+ let letter = ( letter as u8 + b'a' ) as char ;
91+ if base == 0 {
92+ format ! ( "{letter}" )
93+ } else {
94+ format ! ( "{letter}{base}" )
95+ }
96+ }
97+
98+ let mut counter = 0 ;
99+ loop {
100+ let name = to_str ( counter) ;
101+ let name = self . interner . borrow_mut ( ) . get_or_intern ( name) ;
102+ match self . local_names . iter ( ) . any ( |symbol| * symbol == Some ( name) ) {
103+ true => { }
104+ false => return name,
105+ }
106+ counter += 1 ;
107+ }
108+ }
109+
110+ /// Replace `name` with a fresh name if it is `_` and occurs in `body`
111+ fn freshen_name ( & mut self , name : Option < StringId > , body : & core:: Term < ' _ > ) -> Option < StringId > {
112+ match name {
113+ Some ( name) => Some ( name) ,
114+ None => match body. binds_local ( Index :: last ( ) ) {
115+ false => None ,
116+ true => Some ( self . gen_fresh_name ( ) ) ,
117+ } ,
118+ }
119+ }
120+
85121 fn check_number_literal_styled < T : core:: UIntStyled < N > , const N : usize > (
86122 & mut self ,
87123 number : T ,
@@ -224,7 +260,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
224260 let def_type = self . check ( def_type) ;
225261 let def_expr = self . check ( def_expr) ;
226262
227- let def_name = self . push_local ( * def_name) ;
263+ let def_name = self . freshen_name ( * def_name, body_expr) ;
264+ let def_name = self . push_local ( def_name) ;
228265 let body_expr = self . check ( body_expr) ;
229266 self . pop_local ( ) ;
230267
@@ -236,11 +273,14 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
236273 self . scope . to_scope ( body_expr) ,
237274 )
238275 }
239- core:: Term :: FunLit ( _ , param_name , mut body_expr ) => {
276+ core:: Term :: FunLit ( .. ) => {
240277 let initial_local_len = self . local_len ( ) ;
241- let mut param_names = vec ! [ self . push_local( * param_name) ] ;
278+ let mut param_names = Vec :: new ( ) ;
279+ let mut body_expr = core_term;
280+
242281 while let core:: Term :: FunLit ( _, param_name, next_body_expr) = body_expr {
243- param_names. push ( self . push_local ( * param_name) ) ;
282+ let param_name = self . freshen_name ( * param_name, next_body_expr) ;
283+ param_names. push ( self . push_local ( param_name) ) ;
244284 body_expr = next_body_expr;
245285 }
246286
@@ -323,7 +363,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
323363 match default_branch {
324364 Some ( ( default_name, default_expr) ) => {
325365 let default_branch = {
326- let name = self . push_local ( * default_name) ;
366+ let name = self . freshen_name ( * default_name, default_expr) ;
367+ let name = self . push_local ( name) ;
327368 let default_expr = self . check ( default_expr) ;
328369 self . pop_local ( ) ;
329370
@@ -414,7 +455,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
414455 let def_type = self . check ( def_type) ;
415456 let def_expr = self . check ( def_expr) ;
416457
417- let def_name = self . push_local ( * def_name) ;
458+ let def_name = self . freshen_name ( * def_name, body_expr) ;
459+ let def_name = self . push_local ( def_name) ;
418460 let body_expr = self . synth ( body_expr) ;
419461 self . pop_local ( ) ;
420462
@@ -441,7 +483,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
441483 if next_body_type. binds_local ( Index :: last ( ) ) =>
442484 {
443485 let param_type = self . check ( param_type) ;
444- let param_name = self . push_local ( * param_name) ;
486+ let param_name = self . freshen_name ( * param_name, next_body_type) ;
487+ let param_name = self . push_local ( param_name) ;
445488 patterns. push ( (
446489 Pattern :: Name ( ( ) , param_name) ,
447490 Some ( self . scope . to_scope ( param_type) as & _ ) ,
@@ -485,7 +528,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
485528 let mut body_expr = core_term;
486529
487530 while let core:: Term :: FunLit ( _, param_name, next_body_expr) = body_expr {
488- param_names. push ( self . push_local ( * param_name) ) ;
531+ let param_name = self . freshen_name ( * param_name, next_body_expr) ;
532+ param_names. push ( self . push_local ( param_name) ) ;
489533 body_expr = next_body_expr;
490534 }
491535
@@ -654,7 +698,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
654698 match default_expr {
655699 Some ( ( default_name, default_expr) ) => {
656700 let default_branch = {
657- let name = self . push_local ( * default_name) ;
701+ let name = self . freshen_name ( * default_name, default_expr) ;
702+ let name = self . push_local ( name) ;
658703 let default_expr = self . synth ( default_expr) ;
659704 self . pop_local ( ) ;
660705
0 commit comments