-
-
Notifications
You must be signed in to change notification settings - Fork 14.6k
Implement immediate-abort by hooking #[rustc_panic_entrypoint] and lint for functions that look like a panic entrypoint #150497
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,11 +4,14 @@ | |
| use rustc_ast as ast; | ||
| use rustc_ast::{Pat, PatKind, Path}; | ||
| use rustc_hir as hir; | ||
| use rustc_hir::attrs::{AttributeKind, InlineAttr}; | ||
| use rustc_hir::def::Res; | ||
| use rustc_hir::def_id::DefId; | ||
| use rustc_hir::{Expr, ExprKind, HirId, find_attr}; | ||
| use rustc_hir::intravisit::FnKind; | ||
| use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, find_attr}; | ||
| use rustc_middle::ty::{self, GenericArgsRef, PredicatePolarity}; | ||
| use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
| use rustc_span::def_id::LocalDefId; | ||
| use rustc_span::hygiene::{ExpnKind, MacroKind}; | ||
| use rustc_span::{Span, sym}; | ||
|
|
||
|
|
@@ -713,3 +716,69 @@ impl EarlyLintPass for BadUseOfFindAttr { | |
| } | ||
| } | ||
| } | ||
|
|
||
| declare_tool_lint! { | ||
| /// The `missing_panic_entrypoint` lint detects forgotten use of #[rustc_panic_entrypoint]. | ||
| /// | ||
| /// This lint is intended to ensure that panic=immediate-abort can function as designed, | ||
| /// because it uses #[rustc_panic_entrypoint] to locate functions that should be outlined | ||
| /// for other panic modes, and be deleted entirely when immediate-abort is enabled. | ||
| /// | ||
| /// The current design of this lint is expected to have a lot of false positives outside of core | ||
| /// and alloc. | ||
| pub rustc::MISSING_PANIC_ENTRYPOINT, | ||
|
Comment on lines
+720
to
+729
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Doesn't this have massive amounts of false positives? A function could easily be diverging without being a panic entrypoint -- it could deliberately loop, or call
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, this has a significant number of false positives in general, that's why it is internal. But across core+alloc there is only one.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be good to mention that in the output and encourage people to
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've added a sentence to the doc comment. |
||
| Allow, | ||
| "detects missing #[rustc_panic_entrypoint]", | ||
| report_in_external_macro: true | ||
| } | ||
|
|
||
| declare_lint_pass!(MissingPanicEntrypoint => [MISSING_PANIC_ENTRYPOINT]); | ||
|
|
||
| fn has_panic_entrypoint(attrs: &[hir::Attribute]) -> bool { | ||
| attrs | ||
| .iter() | ||
| .any(|attr| matches!(attr, hir::Attribute::Parsed(AttributeKind::RustcPanicEntrypoint))) | ||
| } | ||
|
|
||
| fn has_inline_encouragement(attrs: &[hir::Attribute]) -> bool { | ||
| attrs.iter().any(|attr| { | ||
| matches!( | ||
| attr, | ||
| hir::Attribute::Parsed(hir::attrs::AttributeKind::Inline( | ||
| InlineAttr::Hint | InlineAttr::Always | InlineAttr::Force { .. }, | ||
| _ | ||
| )) | ||
| ) | ||
| }) | ||
| } | ||
|
|
||
| fn has_rustc_intrinsic(attrs: &[hir::Attribute]) -> bool { | ||
| attrs.iter().any(|attr| matches!(attr, hir::Attribute::Parsed(AttributeKind::RustcIntrinsic))) | ||
| } | ||
|
|
||
| impl<'tcx> LateLintPass<'tcx> for MissingPanicEntrypoint { | ||
| fn check_fn( | ||
| &mut self, | ||
| cx: &LateContext<'tcx>, | ||
| _: FnKind<'tcx>, | ||
| fn_decl: &'tcx FnDecl<'tcx>, | ||
| _: &'tcx Body<'tcx>, | ||
| span: Span, | ||
| def_id: LocalDefId, | ||
| ) { | ||
| if matches!(fn_decl.output, hir::FnRetTy::Return(hir::Ty { kind: hir::TyKind::Never, .. })) | ||
| { | ||
| let attrs = cx.tcx.hir_attrs(cx.tcx.local_def_id_to_hir_id(def_id)); | ||
| if has_rustc_intrinsic(attrs) { | ||
| return; | ||
| } | ||
| if !has_inline_encouragement(attrs) && !has_panic_entrypoint(attrs) { | ||
| cx.emit_span_lint( | ||
| MISSING_PANIC_ENTRYPOINT, | ||
| span, | ||
| crate::lints::MissingPanicEntrypoint, | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.