@@ -3,7 +3,7 @@ use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exact
3
3
use clippy_utils:: msrvs:: { self , Msrv } ;
4
4
use clippy_utils:: source:: { snippet_with_applicability, snippet_with_context} ;
5
5
use clippy_utils:: sugg:: has_enclosing_paren;
6
- use clippy_utils:: ty:: { expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res } ;
6
+ use clippy_utils:: ty:: { adt_and_variant_of_res , expr_sig, is_copy, peel_mid_ty_refs, ty_sig} ;
7
7
use clippy_utils:: {
8
8
fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
9
9
} ;
@@ -26,8 +26,8 @@ use rustc_lint::{LateContext, LateLintPass};
26
26
use rustc_middle:: mir:: { Rvalue , StatementKind } ;
27
27
use rustc_middle:: ty:: adjustment:: { Adjust , Adjustment , AutoBorrow , AutoBorrowMutability } ;
28
28
use rustc_middle:: ty:: {
29
- self , Binder , BoundVariableKind , Clause , EarlyBinder , FnSig , GenericArgKind , List , ParamTy , PredicateKind ,
30
- ProjectionPredicate , Ty , TyCtxt , TypeVisitable , TypeckResults ,
29
+ self , Binder , BoundVariableKind , Clause , EarlyBinder , FnSig , GenericArgKind , List , ParamEnv , ParamTy ,
30
+ PredicateKind , ProjectionPredicate , Ty , TyCtxt , TypeVisitable , TypeckResults ,
31
31
} ;
32
32
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
33
33
use rustc_span:: { symbol:: sym, Span , Symbol } ;
@@ -736,7 +736,7 @@ fn walk_parents<'tcx>(
736
736
..
737
737
} ) if span. ctxt ( ) == ctxt => {
738
738
let ty = cx. tcx . type_of ( owner_id. def_id ) ;
739
- Some ( ty_auto_deref_stability ( cx, ty, precedence) . position_for_result ( cx) )
739
+ Some ( ty_auto_deref_stability ( cx. tcx , cx . param_env , ty, precedence) . position_for_result ( cx) )
740
740
} ,
741
741
742
742
Node :: Item ( & Item {
@@ -760,18 +760,31 @@ fn walk_parents<'tcx>(
760
760
let output = cx
761
761
. tcx
762
762
. erase_late_bound_regions ( cx. tcx . fn_sig ( owner_id) . subst_identity ( ) . output ( ) ) ;
763
- Some ( ty_auto_deref_stability ( cx, output, precedence) . position_for_result ( cx) )
763
+ Some ( ty_auto_deref_stability ( cx. tcx , cx . param_env , output, precedence) . position_for_result ( cx) )
764
764
} ,
765
765
766
766
Node :: ExprField ( field) if field. span . ctxt ( ) == ctxt => match get_parent_expr_for_hir ( cx, field. hir_id ) {
767
767
Some ( Expr {
768
768
hir_id,
769
769
kind : ExprKind :: Struct ( path, ..) ,
770
770
..
771
- } ) => variant_of_res ( cx, cx. qpath_res ( path, * hir_id) )
772
- . and_then ( |variant| variant. fields . iter ( ) . find ( |f| f. name == field. ident . name ) )
773
- . map ( |field_def| {
774
- ty_auto_deref_stability ( cx, cx. tcx . type_of ( field_def. did ) , precedence) . position_for_arg ( )
771
+ } ) => adt_and_variant_of_res ( cx, cx. qpath_res ( path, * hir_id) )
772
+ . and_then ( |( adt, variant) | {
773
+ variant
774
+ . fields
775
+ . iter ( )
776
+ . find ( |f| f. name == field. ident . name )
777
+ . map ( |f| ( adt, f) )
778
+ } )
779
+ . map ( |( adt, field_def) | {
780
+ ty_auto_deref_stability (
781
+ cx. tcx ,
782
+ // Use the param_env of the target type.
783
+ cx. tcx . param_env ( adt. did ( ) ) ,
784
+ cx. tcx . type_of ( field_def. did ) ,
785
+ precedence,
786
+ )
787
+ . position_for_arg ( )
775
788
} ) ,
776
789
_ => None ,
777
790
} ,
@@ -792,7 +805,7 @@ fn walk_parents<'tcx>(
792
805
let output = cx
793
806
. tcx
794
807
. erase_late_bound_regions ( cx. tcx . fn_sig ( owner_id) . subst_identity ( ) . output ( ) ) ;
795
- ty_auto_deref_stability ( cx, output, precedence) . position_for_result ( cx)
808
+ ty_auto_deref_stability ( cx. tcx , cx . param_env , output, precedence) . position_for_result ( cx)
796
809
} ,
797
810
)
798
811
} ,
@@ -835,15 +848,20 @@ fn walk_parents<'tcx>(
835
848
msrv,
836
849
)
837
850
} else {
838
- ty_auto_deref_stability ( cx, cx. tcx . erase_late_bound_regions ( ty) , precedence)
839
- . position_for_arg ( )
851
+ ty_auto_deref_stability (
852
+ cx. tcx ,
853
+ // Use the param_env of the target function.
854
+ sig. predicates_id ( ) . map_or ( ParamEnv :: empty ( ) , |id| cx. tcx . param_env ( id) ) ,
855
+ cx. tcx . erase_late_bound_regions ( ty) ,
856
+ precedence
857
+ ) . position_for_arg ( )
840
858
}
841
859
} ,
842
860
}
843
861
} )
844
862
} ) ,
845
863
ExprKind :: MethodCall ( method, receiver, args, _) => {
846
- let id = cx. typeck_results ( ) . type_dependent_def_id ( parent. hir_id ) . unwrap ( ) ;
864
+ let fn_id = cx. typeck_results ( ) . type_dependent_def_id ( parent. hir_id ) . unwrap ( ) ;
847
865
if receiver. hir_id == child_id {
848
866
// Check for calls to trait methods where the trait is implemented on a reference.
849
867
// Two cases need to be handled:
@@ -852,13 +870,17 @@ fn walk_parents<'tcx>(
852
870
// priority.
853
871
if e. hir_id != child_id {
854
872
return Some ( Position :: ReborrowStable ( precedence) )
855
- } else if let Some ( trait_id) = cx. tcx . trait_of_item ( id )
873
+ } else if let Some ( trait_id) = cx. tcx . trait_of_item ( fn_id )
856
874
&& let arg_ty = cx. tcx . erase_regions ( cx. typeck_results ( ) . expr_ty_adjusted ( e) )
857
875
&& let ty:: Ref ( _, sub_ty, _) = * arg_ty. kind ( )
858
876
&& let subs = cx
859
877
. typeck_results ( )
860
878
. node_substs_opt ( parent. hir_id ) . map ( |subs| & subs[ 1 ..] ) . unwrap_or_default ( )
861
- && let impl_ty = if cx. tcx . fn_sig ( id) . subst_identity ( ) . skip_binder ( ) . inputs ( ) [ 0 ] . is_ref ( ) {
879
+ && let impl_ty = if cx. tcx . fn_sig ( fn_id)
880
+ . subst_identity ( )
881
+ . skip_binder ( )
882
+ . inputs ( ) [ 0 ] . is_ref ( )
883
+ {
862
884
// Trait methods taking `&self`
863
885
sub_ty
864
886
} else {
@@ -879,10 +901,13 @@ fn walk_parents<'tcx>(
879
901
return Some ( Position :: MethodReceiver ) ;
880
902
}
881
903
args. iter ( ) . position ( |arg| arg. hir_id == child_id) . map ( |i| {
882
- let ty = cx. tcx . fn_sig ( id ) . subst_identity ( ) . skip_binder ( ) . inputs ( ) [ i + 1 ] ;
904
+ let ty = cx. tcx . fn_sig ( fn_id ) . subst_identity ( ) . input ( i + 1 ) ;
883
905
// `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
884
906
// `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
885
- if e. hir_id == child_id && method. args . is_none ( ) && let ty:: Param ( param_ty) = ty. kind ( ) {
907
+ if e. hir_id == child_id
908
+ && method. args . is_none ( )
909
+ && let ty:: Param ( param_ty) = ty. skip_binder ( ) . kind ( )
910
+ {
886
911
needless_borrow_impl_arg_position (
887
912
cx,
888
913
possible_borrowers,
@@ -895,8 +920,10 @@ fn walk_parents<'tcx>(
895
920
)
896
921
} else {
897
922
ty_auto_deref_stability (
898
- cx,
899
- cx. tcx . erase_late_bound_regions ( cx. tcx . fn_sig ( id) . subst_identity ( ) . input ( i + 1 ) ) ,
923
+ cx. tcx ,
924
+ // Use the param_env of the target function.
925
+ cx. tcx . param_env ( fn_id) ,
926
+ cx. tcx . erase_late_bound_regions ( ty) ,
900
927
precedence,
901
928
)
902
929
. position_for_arg ( )
@@ -1378,11 +1405,18 @@ impl<'tcx> TyPosition<'tcx> {
1378
1405
}
1379
1406
1380
1407
// Checks whether a type is stable when switching to auto dereferencing,
1381
- fn ty_auto_deref_stability < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , precedence : i8 ) -> TyPosition < ' tcx > {
1408
+ fn ty_auto_deref_stability < ' tcx > (
1409
+ tcx : TyCtxt < ' tcx > ,
1410
+ param_env : ParamEnv < ' tcx > ,
1411
+ ty : Ty < ' tcx > ,
1412
+ precedence : i8 ,
1413
+ ) -> TyPosition < ' tcx > {
1382
1414
let ty:: Ref ( _, mut ty, _) = * ty. kind ( ) else {
1383
1415
return Position :: Other ( precedence) . into ( ) ;
1384
1416
} ;
1385
1417
1418
+ ty = tcx. try_normalize_erasing_regions ( param_env, ty) . unwrap_or ( ty) ;
1419
+
1386
1420
loop {
1387
1421
break match * ty. kind ( ) {
1388
1422
ty:: Ref ( _, ref_ty, _) => {
@@ -1423,9 +1457,7 @@ fn ty_auto_deref_stability<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, precedenc
1423
1457
| ty:: Closure ( ..)
1424
1458
| ty:: Never
1425
1459
| ty:: Tuple ( _)
1426
- | ty:: Alias ( ty:: Projection , _) => {
1427
- Position :: DerefStable ( precedence, ty. is_sized ( cx. tcx , cx. param_env . without_caller_bounds ( ) ) ) . into ( )
1428
- } ,
1460
+ | ty:: Alias ( ty:: Projection , _) => Position :: DerefStable ( precedence, ty. is_sized ( tcx, param_env) ) . into ( ) ,
1429
1461
} ;
1430
1462
}
1431
1463
}
0 commit comments