@@ -1721,14 +1721,49 @@ fn lint_expect_fun_call(
1721
1721
if match_type ( cx, arg_ty, & paths:: STRING ) {
1722
1722
return false ;
1723
1723
}
1724
- if let ty:: Ref ( ty :: ReStatic , ty, ..) = arg_ty. kind {
1725
- if ty. kind == ty:: Str {
1724
+ if let ty:: Ref ( _ , ty, ..) = arg_ty. kind {
1725
+ if ty. kind == ty:: Str && can_be_static_str ( cx , arg ) {
1726
1726
return false ;
1727
1727
}
1728
1728
} ;
1729
1729
true
1730
1730
}
1731
1731
1732
+ // Check if an expression could have type `&'static str`, knowing that it
1733
+ // has type `&str` for some lifetime.
1734
+ fn can_be_static_str ( cx : & LateContext < ' _ , ' _ > , arg : & hir:: Expr < ' _ > ) -> bool {
1735
+ match arg. kind {
1736
+ hir:: ExprKind :: Lit ( _) => true ,
1737
+ hir:: ExprKind :: Call ( fun, _) => {
1738
+ if let hir:: ExprKind :: Path ( ref p) = fun. kind {
1739
+ match cx. tables . qpath_res ( p, fun. hir_id ) {
1740
+ hir:: def:: Res :: Def ( hir:: def:: DefKind :: Fn , def_id)
1741
+ | hir:: def:: Res :: Def ( hir:: def:: DefKind :: Method , def_id) => matches ! (
1742
+ cx. tcx. fn_sig( def_id) . output( ) . skip_binder( ) . kind,
1743
+ ty:: Ref ( ty:: ReStatic , ..)
1744
+ ) ,
1745
+ _ => false ,
1746
+ }
1747
+ } else {
1748
+ false
1749
+ }
1750
+ } ,
1751
+ hir:: ExprKind :: MethodCall ( ..) => cx. tables . type_dependent_def_id ( arg. hir_id ) . map_or ( false , |method_id| {
1752
+ matches ! (
1753
+ cx. tcx. fn_sig( method_id) . output( ) . skip_binder( ) . kind,
1754
+ ty:: Ref ( ty:: ReStatic , ..)
1755
+ )
1756
+ } ) ,
1757
+ hir:: ExprKind :: Path ( ref p) => match cx. tables . qpath_res ( p, arg. hir_id ) {
1758
+ hir:: def:: Res :: Def ( hir:: def:: DefKind :: Const , _) | hir:: def:: Res :: Def ( hir:: def:: DefKind :: Static , _) => {
1759
+ true
1760
+ } ,
1761
+ _ => false ,
1762
+ } ,
1763
+ _ => false ,
1764
+ }
1765
+ }
1766
+
1732
1767
fn generate_format_arg_snippet (
1733
1768
cx : & LateContext < ' _ , ' _ > ,
1734
1769
a : & hir:: Expr < ' _ > ,
0 commit comments