-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
mir_build: check annotated functions w/out callers
- Loading branch information
Showing
16 changed files
with
223 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
use rustc_attr_parsing::InlineAttr; | ||
use rustc_hir::def_id::DefId; | ||
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; | ||
use rustc_middle::mir::{Body, TerminatorKind}; | ||
use rustc_middle::ty; | ||
use rustc_middle::ty::TyCtxt; | ||
use rustc_span::sym; | ||
|
||
/// Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its | ||
/// definition alone (irrespective of any specific caller). | ||
pub(crate) fn check_force_inline<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { | ||
let def_id = body.source.def_id(); | ||
if !tcx.hir().body_owner_kind(def_id).is_fn_or_closure() || !def_id.is_local() { | ||
return; | ||
} | ||
let InlineAttr::Force { attr_span, .. } = tcx.codegen_fn_attrs(def_id).inline else { | ||
return; | ||
}; | ||
|
||
if let Err(reason) = | ||
is_inline_valid_on_fn(tcx, def_id).and_then(|_| is_inline_valid_on_body(tcx, body)) | ||
{ | ||
tcx.dcx().emit_err(crate::errors::InvalidForceInline { | ||
attr_span, | ||
callee_span: tcx.def_span(def_id), | ||
callee: tcx.def_path_str(def_id), | ||
reason, | ||
}); | ||
} | ||
} | ||
|
||
pub fn is_inline_valid_on_fn<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Result<(), &'static str> { | ||
let codegen_attrs = tcx.codegen_fn_attrs(def_id); | ||
if tcx.has_attr(def_id, sym::rustc_no_mir_inline) { | ||
return Err("#[rustc_no_mir_inline]"); | ||
} | ||
|
||
// FIXME(#127234): Coverage instrumentation currently doesn't handle inlined | ||
// MIR correctly when Modified Condition/Decision Coverage is enabled. | ||
if tcx.sess.instrument_coverage_mcdc() { | ||
return Err("incompatible with MC/DC coverage"); | ||
} | ||
|
||
let ty = tcx.type_of(def_id); | ||
if match ty.instantiate_identity().kind() { | ||
ty::FnDef(..) => tcx.fn_sig(def_id).instantiate_identity().c_variadic(), | ||
ty::Closure(_, args) => args.as_closure().sig().c_variadic(), | ||
_ => false, | ||
} { | ||
return Err("C variadic"); | ||
} | ||
|
||
if codegen_attrs.flags.contains(CodegenFnAttrFlags::COLD) { | ||
return Err("cold"); | ||
} | ||
|
||
// Intrinsic fallback bodies are automatically made cross-crate inlineable, | ||
// but at this stage we don't know whether codegen knows the intrinsic, | ||
// so just conservatively don't inline it. This also ensures that we do not | ||
// accidentally inline the body of an intrinsic that *must* be overridden. | ||
if tcx.has_attr(def_id, sym::rustc_intrinsic) { | ||
return Err("callee is an intrinsic"); | ||
} | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn is_inline_valid_on_body<'tcx>( | ||
_: TyCtxt<'tcx>, | ||
body: &Body<'tcx>, | ||
) -> Result<(), &'static str> { | ||
if body | ||
.basic_blocks | ||
.iter() | ||
.any(|bb| matches!(bb.terminator().kind, TerminatorKind::TailCall { .. })) | ||
{ | ||
return Err("can't inline functions with tail calls"); | ||
} | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,24 @@ | ||
error: `callee` could not be inlined into `async_caller::{closure#0}` but is required to be inlined | ||
--> $DIR/deny-async.rs:20:5 | ||
error: `callee` is incompatible with `#[rustc_force_inline]` | ||
--> $DIR/deny-async.rs:10:1 | ||
| | ||
LL | callee(); | ||
| ^^^^^^^^ ...`callee` called here | ||
LL | #[rustc_force_inline] | ||
| ^^^^^^^^^^^^^^^^^^^^^ | ||
LL | | ||
LL | pub fn callee() { | ||
| --------------- `callee` defined here | ||
| | ||
= note: could not be inlined due to: #[rustc_no_mir_inline] | ||
= note: incompatible due to: #[rustc_no_mir_inline] | ||
|
||
error: `callee_justified` could not be inlined into `async_caller::{closure#0}` but is required to be inlined | ||
--> $DIR/deny-async.rs:23:5 | ||
error: `callee_justified` is incompatible with `#[rustc_force_inline]` | ||
--> $DIR/deny-async.rs:16:1 | ||
| | ||
LL | callee_justified(); | ||
| ^^^^^^^^^^^^^^^^^^ ...`callee_justified` called here | ||
LL | #[rustc_force_inline = "the test requires it"] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
LL | | ||
LL | pub fn callee_justified() { | ||
| ------------------------- `callee_justified` defined here | ||
| | ||
= note: could not be inlined due to: #[rustc_no_mir_inline] | ||
= note: `callee_justified` is required to be inlined to: the test requires it | ||
= note: incompatible due to: #[rustc_no_mir_inline] | ||
|
||
error: aborting due to 2 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.