@@ -169,14 +169,14 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
169169 } ) ) ;
170170 let llfn = declare:: declare_fn ( ccx, & symbol, function_type) ;
171171
172- // set an inline hint for all closures
173- attributes:: inline ( llfn, attributes:: InlineAttr :: Hint ) ;
174172 attributes:: set_frame_pointer_elimination ( ccx, llfn) ;
175173
176174 debug ! ( "get_or_create_declaration_if_closure(): inserting new \
177175 closure {:?}: {:?}",
178176 instance, Value ( llfn) ) ;
179- ccx. instances ( ) . borrow_mut ( ) . insert ( instance, llfn) ;
177+
178+ // NOTE: We do *not* store llfn in the ccx.instances() map here,
179+ // that is only done, when the closures body is translated.
180180
181181 llfn
182182}
@@ -197,8 +197,8 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
197197 // (*) Note that in the case of inlined functions, the `closure_def_id` will be the
198198 // defid of the closure in its original crate, whereas `id` will be the id of the local
199199 // inlined copy.
200-
201- let param_substs = closure_substs. func_substs ;
200+ debug ! ( "trans_closure_expr(id={:?}, closure_def_id={:?}, closure_substs={:?})" ,
201+ id , closure_def_id , closure_substs) ;
202202
203203 let ccx = match dest {
204204 Dest :: SaveIn ( bcx, _) => bcx. ccx ( ) ,
@@ -207,41 +207,49 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
207207 let tcx = ccx. tcx ( ) ;
208208 let _icx = push_ctxt ( "closure::trans_closure_expr" ) ;
209209
210- debug ! ( "trans_closure_expr(id={:?}, closure_def_id={:?}, closure_substs={:?})" ,
211- id, closure_def_id, closure_substs) ;
212-
213- let llfn = get_or_create_closure_declaration ( ccx, closure_def_id, closure_substs) ;
214- llvm:: SetLinkage ( llfn, llvm:: WeakODRLinkage ) ;
215- llvm:: SetUniqueComdat ( ccx. llmod ( ) , llfn) ;
216-
217- // Get the type of this closure. Use the current `param_substs` as
218- // the closure substitutions. This makes sense because the closure
219- // takes the same set of type arguments as the enclosing fn, and
220- // this function (`trans_closure`) is invoked at the point
221- // of the closure expression.
222-
223- let sig = & tcx. closure_type ( closure_def_id, closure_substs) . sig ;
224- let sig = tcx. erase_late_bound_regions ( sig) ;
225- let sig = tcx. normalize_associated_type ( & sig) ;
226-
227- let closure_type = tcx. mk_closure_from_closure_substs ( closure_def_id,
228- closure_substs) ;
229- let sig = ty:: FnSig {
230- inputs : Some ( get_self_type ( tcx, closure_def_id, closure_type) )
231- . into_iter ( ) . chain ( sig. inputs ) . collect ( ) ,
232- output : sig. output ,
233- variadic : false
234- } ;
235-
236- trans_closure ( ccx,
237- decl,
238- body,
239- llfn,
240- Instance :: new ( closure_def_id, param_substs) ,
241- id,
242- & sig,
243- Abi :: RustCall ,
244- ClosureEnv :: Closure ( closure_def_id, id) ) ;
210+ let param_substs = closure_substs. func_substs ;
211+ let instance = Instance :: new ( closure_def_id, param_substs) ;
212+
213+ // If we have not done so yet, translate this closure's body
214+ if !ccx. instances ( ) . borrow ( ) . contains_key ( & instance) {
215+ let llfn = get_or_create_closure_declaration ( ccx, closure_def_id, closure_substs) ;
216+ llvm:: SetLinkage ( llfn, llvm:: WeakODRLinkage ) ;
217+ llvm:: SetUniqueComdat ( ccx. llmod ( ) , llfn) ;
218+
219+ // set an inline hint for all closures
220+ attributes:: inline ( llfn, attributes:: InlineAttr :: Hint ) ;
221+
222+ // Get the type of this closure. Use the current `param_substs` as
223+ // the closure substitutions. This makes sense because the closure
224+ // takes the same set of type arguments as the enclosing fn, and
225+ // this function (`trans_closure`) is invoked at the point
226+ // of the closure expression.
227+
228+ let sig = & tcx. closure_type ( closure_def_id, closure_substs) . sig ;
229+ let sig = tcx. erase_late_bound_regions ( sig) ;
230+ let sig = tcx. normalize_associated_type ( & sig) ;
231+
232+ let closure_type = tcx. mk_closure_from_closure_substs ( closure_def_id,
233+ closure_substs) ;
234+ let sig = ty:: FnSig {
235+ inputs : Some ( get_self_type ( tcx, closure_def_id, closure_type) )
236+ . into_iter ( ) . chain ( sig. inputs ) . collect ( ) ,
237+ output : sig. output ,
238+ variadic : false
239+ } ;
240+
241+ trans_closure ( ccx,
242+ decl,
243+ body,
244+ llfn,
245+ Instance :: new ( closure_def_id, param_substs) ,
246+ id,
247+ & sig,
248+ Abi :: RustCall ,
249+ ClosureEnv :: Closure ( closure_def_id, id) ) ;
250+
251+ ccx. instances ( ) . borrow_mut ( ) . insert ( instance, llfn) ;
252+ }
245253
246254 // Don't hoist this to the top of the function. It's perfectly legitimate
247255 // to have a zero-size closure (in which case dest will be `Ignore`) and
0 commit comments