@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
44use rustc_abi:: { BackendRepr , ExternAbi , TagEncoding , Variants , WrappingRange } ;
55use rustc_data_structures:: fx:: FxHashSet ;
66use rustc_errors:: DiagMessage ;
7- use rustc_hir:: { Expr , ExprKind } ;
7+ use rustc_hir:: { Expr , ExprKind , LangItem } ;
88use rustc_middle:: bug;
99use rustc_middle:: ty:: layout:: { LayoutOf , SizeSkeleton } ;
1010use rustc_middle:: ty:: {
@@ -445,7 +445,25 @@ fn lint_fn_pointer<'tcx>(
445445 let ( l_ty, l_ty_refs) = peel_refs ( l_ty) ;
446446 let ( r_ty, r_ty_refs) = peel_refs ( r_ty) ;
447447
448- if !l_ty. is_fn ( ) || !r_ty. is_fn ( ) {
448+ if l_ty. is_fn ( ) && r_ty. is_fn ( ) {
449+ // both operands are function pointers, fallthrough
450+ } else if let ty:: Adt ( l_def, l_args) = l_ty. kind ( )
451+ && let ty:: Adt ( r_def, r_args) = r_ty. kind ( )
452+ && cx. tcx . is_lang_item ( l_def. did ( ) , LangItem :: Option )
453+ && cx. tcx . is_lang_item ( r_def. did ( ) , LangItem :: Option )
454+ && let Some ( l_some_arg) = l_args. get ( 0 )
455+ && let Some ( r_some_arg) = r_args. get ( 0 )
456+ && l_some_arg. expect_ty ( ) . is_fn ( )
457+ && r_some_arg. expect_ty ( ) . is_fn ( )
458+ {
459+ // both operands are `Option<{function ptr}>`
460+ return cx. emit_span_lint (
461+ UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS ,
462+ e. span ,
463+ UnpredictableFunctionPointerComparisons :: Warn ,
464+ ) ;
465+ } else {
466+ // types are not function pointers, nothing to do
449467 return ;
450468 }
451469
0 commit comments