@@ -15,13 +15,17 @@ use rustc_hir::{
15
15
ImplItemKind , ItemKind , Lifetime , LifetimeName , Mutability , Node , Param , ParamName , PatKind , QPath , TraitFn ,
16
16
TraitItem , TraitItemKind , TyKind , Unsafety ,
17
17
} ;
18
+ use rustc_infer:: infer:: TyCtxtInferExt ;
19
+ use rustc_infer:: traits:: { Obligation , ObligationCause } ;
18
20
use rustc_lint:: { LateContext , LateLintPass } ;
19
21
use rustc_middle:: hir:: nested_filter;
20
- use rustc_middle:: ty:: { self , Ty } ;
22
+ use rustc_middle:: ty:: { self , Binder , ExistentialPredicate , List , PredicateKind , Ty } ;
21
23
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
22
24
use rustc_span:: source_map:: Span ;
23
25
use rustc_span:: sym;
24
26
use rustc_span:: symbol:: Symbol ;
27
+ use rustc_trait_selection:: infer:: InferCtxtExt as _;
28
+ use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
25
29
use std:: fmt;
26
30
use std:: iter;
27
31
@@ -384,6 +388,17 @@ enum DerefTy<'tcx> {
384
388
Slice ( Option < Span > , Ty < ' tcx > ) ,
385
389
}
386
390
impl < ' tcx > DerefTy < ' tcx > {
391
+ fn ty ( & self , cx : & LateContext < ' tcx > ) -> Ty < ' tcx > {
392
+ match * self {
393
+ Self :: Str => cx. tcx . types . str_ ,
394
+ Self :: Path => cx. tcx . mk_adt (
395
+ cx. tcx . adt_def ( cx. tcx . get_diagnostic_item ( sym:: Path ) . unwrap ( ) ) ,
396
+ List :: empty ( ) ,
397
+ ) ,
398
+ Self :: Slice ( _, ty) => cx. tcx . mk_slice ( ty) ,
399
+ }
400
+ }
401
+
387
402
fn argless_str ( & self ) -> & ' static str {
388
403
match * self {
389
404
Self :: Str => "str" ,
@@ -581,6 +596,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
581
596
let i = expr_args. iter ( ) . position ( |arg| arg. hir_id == child_id) . unwrap_or ( 0 ) ;
582
597
if expr_sig ( self . cx , f) . and_then ( |sig| sig. input ( i) ) . map_or ( true , |ty| {
583
598
match * ty. skip_binder ( ) . peel_refs ( ) . kind ( ) {
599
+ ty:: Dynamic ( preds, _, _) => !matches_preds ( self . cx , args. deref_ty . ty ( self . cx ) , preds) ,
584
600
ty:: Param ( _) => true ,
585
601
ty:: Adt ( def, _) => def. did ( ) == args. ty_did ,
586
602
_ => false ,
@@ -614,6 +630,9 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
614
630
} ;
615
631
616
632
match * self . cx . tcx . fn_sig ( id) . skip_binder ( ) . inputs ( ) [ i] . peel_refs ( ) . kind ( ) {
633
+ ty:: Dynamic ( preds, _, _) if !matches_preds ( self . cx , args. deref_ty . ty ( self . cx ) , preds) => {
634
+ set_skip_flag ( ) ;
635
+ } ,
617
636
ty:: Param ( _) => {
618
637
set_skip_flag ( ) ;
619
638
} ,
@@ -665,6 +684,31 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
665
684
v. results
666
685
}
667
686
687
+ fn matches_preds < ' tcx > (
688
+ cx : & LateContext < ' tcx > ,
689
+ ty : Ty < ' tcx > ,
690
+ preds : & ' tcx [ Binder < ' tcx , ExistentialPredicate < ' tcx > > ] ,
691
+ ) -> bool {
692
+ cx. tcx . infer_ctxt ( ) . enter ( |infcx| {
693
+ preds. iter ( ) . all ( |& p| match cx. tcx . erase_late_bound_regions ( p) {
694
+ ExistentialPredicate :: Trait ( p) => infcx
695
+ . type_implements_trait ( p. def_id , ty, p. substs , cx. param_env )
696
+ . must_apply_modulo_regions ( ) ,
697
+ ExistentialPredicate :: Projection ( p) => infcx. predicate_must_hold_modulo_regions ( & Obligation :: new (
698
+ ObligationCause :: dummy ( ) ,
699
+ cx. param_env ,
700
+ cx. tcx . mk_predicate ( Binder :: bind_with_vars (
701
+ PredicateKind :: Projection ( p. with_self_ty ( cx. tcx , ty) ) ,
702
+ List :: empty ( ) ,
703
+ ) ) ,
704
+ ) ) ,
705
+ ExistentialPredicate :: AutoTrait ( p) => infcx
706
+ . type_implements_trait ( p, ty, List :: empty ( ) , cx. param_env )
707
+ . must_apply_modulo_regions ( ) ,
708
+ } )
709
+ } )
710
+ }
711
+
668
712
fn get_rptr_lm < ' tcx > ( ty : & ' tcx hir:: Ty < ' tcx > ) -> Option < ( & ' tcx Lifetime , Mutability , Span ) > {
669
713
if let TyKind :: Rptr ( lt, ref m) = ty. kind {
670
714
Some ( ( lt, m. mutbl , ty. span ) )
0 commit comments