@@ -169,14 +169,14 @@ fn get_or_create_closure_declaration<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
169
169
} ) ) ;
170
170
let llfn = declare:: declare_fn ( ccx, & symbol, function_type) ;
171
171
172
- // set an inline hint for all closures
173
- attributes:: inline ( llfn, attributes:: InlineAttr :: Hint ) ;
174
172
attributes:: set_frame_pointer_elimination ( ccx, llfn) ;
175
173
176
174
debug ! ( "get_or_create_declaration_if_closure(): inserting new \
177
175
closure {:?}: {:?}",
178
176
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.
180
180
181
181
llfn
182
182
}
@@ -197,8 +197,8 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
197
197
// (*) Note that in the case of inlined functions, the `closure_def_id` will be the
198
198
// defid of the closure in its original crate, whereas `id` will be the id of the local
199
199
// 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) ;
202
202
203
203
let ccx = match dest {
204
204
Dest :: SaveIn ( bcx, _) => bcx. ccx ( ) ,
@@ -207,41 +207,49 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
207
207
let tcx = ccx. tcx ( ) ;
208
208
let _icx = push_ctxt ( "closure::trans_closure_expr" ) ;
209
209
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
+ }
245
253
246
254
// Don't hoist this to the top of the function. It's perfectly legitimate
247
255
// to have a zero-size closure (in which case dest will be `Ignore`) and
0 commit comments