@@ -11,10 +11,11 @@ use rustc_lint::{LateContext, LateLintPass, LintStore};
1111use rustc_middle:: ty:: TyKind ;
1212use rustc_session:: impl_lint_pass;
1313use rustc_span:: BytePos ;
14- use std:: collections:: HashMap ;
14+ use std:: collections:: { HashMap , HashSet } ;
1515use std:: sync:: Mutex ;
1616
1717use super :: no_allocation:: detect_allocation_in_mir;
18+ use super :: no_panic:: { PanicCategory , detect_panic_in_mir} ;
1819
1920// Helper: retrieve the concrete Self type of the impl the method belongs to, if any
2021fn get_self_type < ' tcx > (
@@ -60,7 +61,33 @@ impl FunctionLint {
6061 evaluate_function_match ( & self . matches , ctx, module_path, function_name, fn_def_id)
6162 }
6263
63- // Evaluates the complex matcher structure to determine if a function matches
64+ /// Helper method to check a single panic category and emit a lint if found
65+ fn check_panic_category (
66+ & self ,
67+ ctx : & LateContext < ' _ > ,
68+ fn_def_id : rustc_hir:: def_id:: DefId ,
69+ severity : cargo_pup_lint_config:: Severity ,
70+ category : PanicCategory ,
71+ rule_name : & str ,
72+ ) {
73+ if ctx. tcx . is_mir_available ( fn_def_id) {
74+ let mir = ctx. tcx . optimized_mir ( fn_def_id) ;
75+ let mut categories = HashSet :: new ( ) ;
76+ categories. insert ( category) ;
77+
78+ if let Some ( violation) = detect_panic_in_mir ( ctx. tcx , mir, & categories) {
79+ span_lint_and_help (
80+ ctx,
81+ FUNCTION_LINT :: get_by_severity ( severity) ,
82+ self . name ( ) . as_str ( ) ,
83+ violation. span ,
84+ format ! ( "Function may panic: {}" , violation. reason) ,
85+ None ,
86+ format ! ( "Remove panic paths to satisfy the {} rule" , rule_name) ,
87+ ) ;
88+ }
89+ }
90+ }
6491}
6592
6693fn evaluate_function_match (
@@ -204,6 +231,40 @@ fn evaluate_function_match(
204231 }
205232 false
206233 }
234+ FunctionMatch :: IsUnsafe => {
235+ // Check if the function is unsafe by examining the HIR
236+ if let Some ( local_def_id) = fn_def_id. as_local ( ) {
237+ let node = ctx. tcx . hir_node_by_def_id ( local_def_id) ;
238+ match node {
239+ rustc_hir:: Node :: Item ( item) => {
240+ if let rustc_hir:: ItemKind :: Fn { sig, .. } = & item. kind {
241+ return matches ! (
242+ sig. header. safety,
243+ rustc_hir:: HeaderSafety :: Normal ( rustc_hir:: Safety :: Unsafe )
244+ ) ;
245+ }
246+ }
247+ rustc_hir:: Node :: TraitItem ( trait_item) => {
248+ if let rustc_hir:: TraitItemKind :: Fn ( sig, _) = & trait_item. kind {
249+ return matches ! (
250+ sig. header. safety,
251+ rustc_hir:: HeaderSafety :: Normal ( rustc_hir:: Safety :: Unsafe )
252+ ) ;
253+ }
254+ }
255+ rustc_hir:: Node :: ImplItem ( impl_item) => {
256+ if let rustc_hir:: ImplItemKind :: Fn ( sig, _) = & impl_item. kind {
257+ return matches ! (
258+ sig. header. safety,
259+ rustc_hir:: HeaderSafety :: Normal ( rustc_hir:: Safety :: Unsafe )
260+ ) ;
261+ }
262+ }
263+ _ => { }
264+ }
265+ }
266+ false
267+ }
207268 FunctionMatch :: AndMatches ( left, right) => {
208269 evaluate_function_match ( left, ctx, module_path, function_name, fn_def_id)
209270 && evaluate_function_match ( right, ctx, module_path, function_name, fn_def_id)
@@ -381,6 +442,33 @@ impl<'tcx> LateLintPass<'tcx> for FunctionLint {
381442 }
382443 }
383444 }
445+ FunctionRule :: NoUnwrap ( severity) => {
446+ self . check_panic_category (
447+ ctx,
448+ fn_def_id,
449+ * severity,
450+ PanicCategory :: Unwrap ,
451+ "NoUnwrap" ,
452+ ) ;
453+ }
454+ FunctionRule :: NoPanic ( severity) => {
455+ self . check_panic_category (
456+ ctx,
457+ fn_def_id,
458+ * severity,
459+ PanicCategory :: ExplicitPanic ,
460+ "NoPanic" ,
461+ ) ;
462+ }
463+ FunctionRule :: NoIndexPanic ( severity) => {
464+ self . check_panic_category (
465+ ctx,
466+ fn_def_id,
467+ * severity,
468+ PanicCategory :: IndexBounds ,
469+ "NoIndexPanic" ,
470+ ) ;
471+ }
384472 }
385473 }
386474 }
@@ -506,6 +594,33 @@ impl<'tcx> LateLintPass<'tcx> for FunctionLint {
506594 }
507595 }
508596 }
597+ FunctionRule :: NoUnwrap ( severity) => {
598+ self . check_panic_category (
599+ ctx,
600+ fn_def_id,
601+ * severity,
602+ PanicCategory :: Unwrap ,
603+ "NoUnwrap" ,
604+ ) ;
605+ }
606+ FunctionRule :: NoPanic ( severity) => {
607+ self . check_panic_category (
608+ ctx,
609+ fn_def_id,
610+ * severity,
611+ PanicCategory :: ExplicitPanic ,
612+ "NoPanic" ,
613+ ) ;
614+ }
615+ FunctionRule :: NoIndexPanic ( severity) => {
616+ self . check_panic_category (
617+ ctx,
618+ fn_def_id,
619+ * severity,
620+ PanicCategory :: IndexBounds ,
621+ "NoIndexPanic" ,
622+ ) ;
623+ }
509624 }
510625 }
511626 }
0 commit comments