@@ -74,7 +74,7 @@ pub fn should_run_pass_for_item<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> bool {
74
74
}
75
75
76
76
let codegen_fn_attrs = tcx. codegen_fn_attrs ( did) ;
77
- matches ! ( codegen_fn_attrs. inline, InlineAttr :: Required { .. } | InlineAttr :: Must { .. } )
77
+ codegen_fn_attrs. inline . required ( )
78
78
|| match tcx. sess . mir_opt_level ( ) {
79
79
0 | 1 => false ,
80
80
2 => {
@@ -219,8 +219,10 @@ impl<'tcx> Inliner<'tcx> {
219
219
// Intrinsic fallback bodies are automatically made cross-crate inlineable,
220
220
// but at this stage we don't know whether codegen knows the intrinsic,
221
221
// so just conservatively don't inline it.
222
- if self . tcx . has_attr ( callsite. callee . def_id ( ) , sym:: rustc_intrinsic) {
223
- return Err ( "Callee is an intrinsic, do not inline fallback bodies" ) ;
222
+ if self . tcx . has_attr ( callsite. callee . def_id ( ) , sym:: rustc_intrinsic)
223
+ && !callee_attrs. inline . required ( )
224
+ {
225
+ return Err ( "callee is an intrinsic" ) ;
224
226
}
225
227
226
228
let terminator = caller_body[ callsite. block ] . terminator . as_ref ( ) . unwrap ( ) ;
@@ -230,7 +232,7 @@ impl<'tcx> Inliner<'tcx> {
230
232
if !arg. node . ty ( & caller_body. local_decls , self . tcx ) . is_sized ( self . tcx , self . param_env ) {
231
233
// We do not allow inlining functions with unsized params. Inlining these functions
232
234
// could create unsized locals, which are unsound and being phased out.
233
- return Err ( "Call has unsized argument" ) ;
235
+ return Err ( "call has unsized argument" ) ;
234
236
}
235
237
}
236
238
@@ -239,7 +241,8 @@ impl<'tcx> Inliner<'tcx> {
239
241
240
242
if !self . tcx . consider_optimizing ( || {
241
243
format ! ( "Inline {:?} into {:?}" , callsite. callee, caller_body. source)
242
- } ) {
244
+ } ) && !callee_attrs. inline . required ( )
245
+ {
243
246
return Err ( "optimization fuel exhausted" ) ;
244
247
}
245
248
@@ -248,7 +251,8 @@ impl<'tcx> Inliner<'tcx> {
248
251
self . param_env ,
249
252
ty:: EarlyBinder :: bind ( callee_body. clone ( ) ) ,
250
253
) else {
251
- return Err ( "failed to normalize callee body" ) ;
254
+ debug ! ( "failed to normalize callee body" ) ;
255
+ return Err ( "implementation limitation" ) ;
252
256
} ;
253
257
254
258
// Normally, this shouldn't be required, but trait normalization failure can create a
@@ -262,7 +266,8 @@ impl<'tcx> Inliner<'tcx> {
262
266
)
263
267
. is_empty ( )
264
268
{
265
- return Err ( "failed to validate callee body" ) ;
269
+ debug ! ( "failed to validate callee body" ) ;
270
+ return Err ( "implementation limitation" ) ;
266
271
}
267
272
268
273
// Check call signature compatibility.
@@ -272,14 +277,15 @@ impl<'tcx> Inliner<'tcx> {
272
277
if !util:: relate_types ( self . tcx , self . param_env , ty:: Covariant , output_type, destination_ty)
273
278
{
274
279
trace ! ( ?output_type, ?destination_ty) ;
275
- return Err ( "failed to normalize return type" ) ;
280
+ debug ! ( "failed to normalize return type" ) ;
281
+ return Err ( "implementation limitation" ) ;
276
282
}
277
283
if callsite. fn_sig . abi ( ) == Abi :: RustCall {
278
284
// FIXME: Don't inline user-written `extern "rust-call"` functions,
279
285
// since this is generally perf-negative on rustc, and we hope that
280
286
// LLVM will inline these functions instead.
281
287
if callee_body. spread_arg . is_some ( ) {
282
- return Err ( "do not inline user-written rust-call functions" ) ;
288
+ return Err ( "user-written rust-call functions" ) ;
283
289
}
284
290
285
291
let ( self_arg, arg_tuple) = match & args[ ..] {
@@ -303,7 +309,8 @@ impl<'tcx> Inliner<'tcx> {
303
309
if !util:: relate_types ( self . tcx , self . param_env , ty:: Covariant , input_type, arg_ty)
304
310
{
305
311
trace ! ( ?arg_ty, ?input_type) ;
306
- return Err ( "failed to normalize tuple argument type" ) ;
312
+ debug ! ( "failed to normalize tuple argument type" ) ;
313
+ return Err ( "implementation limitation" ) ;
307
314
}
308
315
}
309
316
} else {
@@ -313,7 +320,8 @@ impl<'tcx> Inliner<'tcx> {
313
320
if !util:: relate_types ( self . tcx , self . param_env , ty:: Covariant , input_type, arg_ty)
314
321
{
315
322
trace ! ( ?arg_ty, ?input_type) ;
316
- return Err ( "failed to normalize argument type" ) ;
323
+ debug ! ( "failed to normalize argument type" ) ;
324
+ return Err ( "implementation limitation" ) ;
317
325
}
318
326
}
319
327
}
@@ -342,12 +350,14 @@ impl<'tcx> Inliner<'tcx> {
342
350
// because it has no MIR because it's an extern function), then the inliner
343
351
// won't cause cycles on this.
344
352
if !self . tcx . is_mir_available ( callee_def_id) {
345
- return Err ( "item MIR unavailable" ) ;
353
+ debug ! ( "item MIR unavailable" ) ;
354
+ return Err ( "implementation limitation" ) ;
346
355
}
347
356
}
348
357
// These have no own callable MIR.
349
358
InstanceKind :: Intrinsic ( _) | InstanceKind :: Virtual ( ..) => {
350
- return Err ( "instance without MIR (intrinsic / virtual)" ) ;
359
+ debug ! ( "instance without MIR (intrinsic / virtual)" ) ;
360
+ return Err ( "implementation limitation" ) ;
351
361
}
352
362
353
363
// FIXME(#127030): `ConstParamHasTy` has bad interactions with
@@ -356,7 +366,8 @@ impl<'tcx> Inliner<'tcx> {
356
366
// the MIR for this instance until all of its const params are
357
367
// substituted.
358
368
InstanceKind :: DropGlue ( _, Some ( ty) ) if ty. has_type_flags ( TypeFlags :: HAS_CT_PARAM ) => {
359
- return Err ( "still needs substitution" ) ;
369
+ debug ! ( "still needs substitution" ) ;
370
+ return Err ( "implementation limitation" ) ;
360
371
}
361
372
362
373
// This cannot result in an immediate cycle since the callee MIR is a shim, which does
@@ -385,7 +396,8 @@ impl<'tcx> Inliner<'tcx> {
385
396
// If we know for sure that the function we're calling will itself try to
386
397
// call us, then we avoid inlining that function.
387
398
if self . tcx . mir_callgraph_reachable ( ( callee, caller_def_id. expect_local ( ) ) ) {
388
- return Err ( "caller might be reachable from callee (query cycle avoidance)" ) ;
399
+ debug ! ( "query cycle avoidance" ) ;
400
+ return Err ( "caller might be reachable from callee" ) ;
389
401
}
390
402
391
403
Ok ( ( ) )
@@ -459,7 +471,7 @@ impl<'tcx> Inliner<'tcx> {
459
471
}
460
472
461
473
if let InlineAttr :: Never = callee_attrs. inline {
462
- return Err ( "never inline hint " ) ;
474
+ return Err ( "never inline attribute " ) ;
463
475
}
464
476
465
477
// FIXME(#127234): Coverage instrumentation currently doesn't handle inlined
@@ -528,12 +540,12 @@ impl<'tcx> Inliner<'tcx> {
528
540
let tcx = self . tcx ;
529
541
530
542
if let Some ( _) = callee_body. tainted_by_errors {
531
- return Err ( "Body is tainted " ) ;
543
+ return Err ( "body has errors " ) ;
532
544
}
533
545
534
546
// Callees which require inlining must be inlined to maintain security properties or
535
547
// for performance reasons, so skip any heuristics.
536
- if matches ! ( callee_attrs. inline, InlineAttr :: Required { .. } | InlineAttr :: Must { .. } ) {
548
+ if callee_attrs. inline . required ( ) {
537
549
debug ! ( "INLINING {:?} [required]" , callsite) ;
538
550
return Ok ( ( ) ) ;
539
551
}
@@ -594,7 +606,7 @@ impl<'tcx> Inliner<'tcx> {
594
606
// assign one. However, during this stage we require an exact match when any
595
607
// inline-asm is detected. LLVM will still possibly do an inline later on
596
608
// if the no-attribute function ends up with the same instruction set anyway.
597
- return Err ( "Cannot move inline-asm across instruction sets" ) ;
609
+ return Err ( "cannot move inline-asm across instruction sets" ) ;
598
610
} else if let TerminatorKind :: TailCall { .. } = term. kind {
599
611
// FIXME(explicit_tail_calls): figure out how exactly functions containing tail
600
612
// calls can be inlined (and if they even should)
0 commit comments