@@ -86,6 +86,42 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
8686 }
8787 }
8888
89+ /// Generate a fresh name that does not appear in `self.local_names`
90+ fn gen_fresh_name ( & mut self ) -> StringId {
91+ fn to_str ( x : u32 ) -> String {
92+ let base = x / 26 ;
93+ let letter = x % 26 ;
94+ let letter = ( letter as u8 + b'a' ) as char ;
95+ if base == 0 {
96+ format ! ( "{letter}" )
97+ } else {
98+ format ! ( "{letter}{base}" )
99+ }
100+ }
101+
102+ let mut counter = 0 ;
103+ loop {
104+ let name = to_str ( counter) ;
105+ let name = self . interner . borrow_mut ( ) . get_or_intern ( name) ;
106+ match self . local_names . iter ( ) . any ( |symbol| * symbol == Some ( name) ) {
107+ true => { }
108+ false => return name,
109+ }
110+ counter += 1 ;
111+ }
112+ }
113+
114+ /// Replace `name` with a fresh name if it is `_` and occurs in `body`
115+ fn freshen_name ( & mut self , name : Option < StringId > , body : & core:: Term < ' _ > ) -> Option < StringId > {
116+ match name {
117+ Some ( name) => Some ( name) ,
118+ None => match body. binds_local ( Index :: last ( ) ) {
119+ false => None ,
120+ true => Some ( self . gen_fresh_name ( ) ) ,
121+ } ,
122+ }
123+ }
124+
89125 fn check_number_literal_styled < T : core:: UIntStyled < N > , const N : usize > (
90126 & mut self ,
91127 number : T ,
@@ -229,7 +265,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
229265 let def_type = self . check ( def_type) ;
230266 let def_expr = self . check ( def_expr) ;
231267
232- let def_name = self . push_local ( * def_name) ;
268+ let def_name = self . freshen_name ( * def_name, body_expr) ;
269+ let def_name = self . push_local ( def_name) ;
233270 let body_expr = self . check ( body_expr) ;
234271 self . pop_local ( ) ;
235272
@@ -241,11 +278,14 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
241278 self . scope . to_scope ( body_expr) ,
242279 )
243280 }
244- core:: Term :: FunLit ( _ , param_name , mut body_expr ) => {
281+ core:: Term :: FunLit ( .. ) => {
245282 let initial_local_len = self . local_len ( ) ;
246- let mut param_names = vec ! [ self . push_local( * param_name) ] ;
283+ let mut param_names = Vec :: new ( ) ;
284+ let mut body_expr = core_term;
285+
247286 while let core:: Term :: FunLit ( _, param_name, next_body_expr) = body_expr {
248- param_names. push ( self . push_local ( * param_name) ) ;
287+ let param_name = self . freshen_name ( * param_name, next_body_expr) ;
288+ param_names. push ( self . push_local ( param_name) ) ;
249289 body_expr = next_body_expr;
250290 }
251291
@@ -328,7 +368,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
328368 match default_branch {
329369 Some ( ( default_name, default_expr) ) => {
330370 let default_branch = {
331- let name = self . push_local ( * default_name) ;
371+ let name = self . freshen_name ( * default_name, default_expr) ;
372+ let name = self . push_local ( name) ;
332373 let default_expr = self . check ( default_expr) ;
333374 self . pop_local ( ) ;
334375
@@ -419,7 +460,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
419460 let def_type = self . check ( def_type) ;
420461 let def_expr = self . check ( def_expr) ;
421462
422- let def_name = self . push_local ( * def_name) ;
463+ let def_name = self . freshen_name ( * def_name, body_expr) ;
464+ let def_name = self . push_local ( def_name) ;
423465 let body_expr = self . synth ( body_expr) ;
424466 self . pop_local ( ) ;
425467
@@ -446,7 +488,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
446488 if next_body_type. binds_local ( Index :: last ( ) ) =>
447489 {
448490 let param_type = self . check ( param_type) ;
449- let param_name = self . push_local ( * param_name) ;
491+ let param_name = self . freshen_name ( * param_name, next_body_type) ;
492+ let param_name = self . push_local ( param_name) ;
450493 patterns. push ( (
451494 Pattern :: Name ( ( ) , param_name) ,
452495 Some ( self . scope . to_scope ( param_type) as & _ ) ,
@@ -490,7 +533,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
490533 let mut body_expr = core_term;
491534
492535 while let core:: Term :: FunLit ( _, param_name, next_body_expr) = body_expr {
493- param_names. push ( self . push_local ( * param_name) ) ;
536+ let param_name = self . freshen_name ( * param_name, next_body_expr) ;
537+ param_names. push ( self . push_local ( param_name) ) ;
494538 body_expr = next_body_expr;
495539 }
496540
@@ -659,7 +703,8 @@ impl<'interner, 'arena, 'env> Context<'interner, 'arena, 'env> {
659703 match default_expr {
660704 Some ( ( default_name, default_expr) ) => {
661705 let default_branch = {
662- let name = self . push_local ( * default_name) ;
706+ let name = self . freshen_name ( * default_name, default_expr) ;
707+ let name = self . push_local ( name) ;
663708 let default_expr = self . synth ( default_expr) ;
664709 self . pop_local ( ) ;
665710
0 commit comments