@@ -4,6 +4,7 @@ use clippy_utils::sym;
44use rustc_errors:: Applicability ;
55use rustc_hir:: { Expr , ExprKind } ;
66use rustc_lint:: { LateContext , LateLintPass } ;
7+ use rustc_middle:: ty:: adjustment:: { Adjust , PointerCoercion } ;
78use rustc_middle:: ty:: { self , ExistentialPredicate , Ty , TyCtxt } ;
89use rustc_session:: declare_lint_pass;
910
@@ -49,23 +50,18 @@ declare_lint_pass!(CoerceContainerToAny => [COERCE_CONTAINER_TO_ANY]);
4950
5051impl < ' tcx > LateLintPass < ' tcx > for CoerceContainerToAny {
5152 fn check_expr ( & mut self , cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' _ > ) {
52- // If this expression has an effective type of `&dyn Any` ...
53- {
54- let coerced_ty = cx. typeck_results ( ) . expr_ty_adjusted ( e) ;
55-
56- let ty:: Ref ( _, coerced_ref_ty, _) = * coerced_ty. kind ( ) else {
57- return ;
58- } ;
59- if !is_dyn_any ( cx. tcx , coerced_ref_ty) {
60- return ;
61- }
53+ // If this expression was coerced to `&dyn Any` ...
54+ if !cx. typeck_results ( ) . expr_adjustments ( e) . last ( ) . is_some_and ( |adj| {
55+ matches ! ( adj. kind, Adjust :: Pointer ( PointerCoercion :: Unsize ) ) && is_ref_dyn_any ( cx. tcx , adj. target )
56+ } ) {
57+ return ;
6258 }
6359
6460 let expr_ty = cx. typeck_results ( ) . expr_ty ( e) ;
6561 let ty:: Ref ( _, expr_ref_ty, _) = * expr_ty. kind ( ) else {
6662 return ;
6763 } ;
68- // ... but only due to coercion ...
64+ // ... but it's not actually `&dyn Any` ...
6965 if is_dyn_any ( cx. tcx , expr_ref_ty) {
7066 return ;
7167 }
@@ -89,12 +85,19 @@ impl<'tcx> LateLintPass<'tcx> for CoerceContainerToAny {
8985 e. span ,
9086 format ! ( "coercing `{expr_ty}` to `&dyn Any`" ) ,
9187 "consider dereferencing" ,
92- format ! ( "&{}{}" , str :: repeat( "*" , deref_count) , snippet( cx, span, "x " ) ) ,
88+ format ! ( "&{}{}" , str :: repeat( "*" , deref_count) , snippet( cx, span, ".. " ) ) ,
9389 Applicability :: MaybeIncorrect ,
9490 ) ;
9591 }
9692}
9793
94+ fn is_ref_dyn_any ( tcx : TyCtxt < ' _ > , ty : Ty < ' _ > ) -> bool {
95+ let ty:: Ref ( _, ref_ty, _) = * ty. kind ( ) else {
96+ return false ;
97+ } ;
98+ is_dyn_any ( tcx, ref_ty)
99+ }
100+
98101fn is_dyn_any ( tcx : TyCtxt < ' _ > , ty : Ty < ' _ > ) -> bool {
99102 let ty:: Dynamic ( traits, ..) = ty. kind ( ) else {
100103 return false ;
0 commit comments