@@ -15,13 +15,17 @@ use rustc_hir::{
1515 ImplItemKind , ItemKind , Lifetime , LifetimeName , Mutability , Node , Param , ParamName , PatKind , QPath , TraitFn ,
1616 TraitItem , TraitItemKind , TyKind , Unsafety ,
1717} ;
18+ use rustc_infer:: infer:: TyCtxtInferExt ;
19+ use rustc_infer:: traits:: { Obligation , ObligationCause } ;
1820use rustc_lint:: { LateContext , LateLintPass } ;
1921use rustc_middle:: hir:: nested_filter;
20- use rustc_middle:: ty:: { self , Ty } ;
22+ use rustc_middle:: ty:: { self , Binder , ExistentialPredicate , List , PredicateKind , Ty } ;
2123use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
2224use rustc_span:: source_map:: Span ;
2325use rustc_span:: sym;
2426use rustc_span:: symbol:: Symbol ;
27+ use rustc_trait_selection:: infer:: InferCtxtExt as _;
28+ use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
2529use std:: fmt;
2630use std:: iter;
2731
@@ -384,6 +388,17 @@ enum DerefTy<'tcx> {
384388 Slice ( Option < Span > , Ty < ' tcx > ) ,
385389}
386390impl < ' 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+
387402 fn argless_str ( & self ) -> & ' static str {
388403 match * self {
389404 Self :: Str => "str" ,
@@ -581,6 +596,7 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
581596 let i = expr_args. iter ( ) . position ( |arg| arg. hir_id == child_id) . unwrap_or ( 0 ) ;
582597 if expr_sig ( self . cx , f) . and_then ( |sig| sig. input ( i) ) . map_or ( true , |ty| {
583598 match * ty. skip_binder ( ) . peel_refs ( ) . kind ( ) {
599+ ty:: Dynamic ( preds, _, _) => !matches_preds ( self . cx , args. deref_ty . ty ( self . cx ) , preds) ,
584600 ty:: Param ( _) => true ,
585601 ty:: Adt ( def, _) => def. did ( ) == args. ty_did ,
586602 _ => false ,
@@ -614,6 +630,9 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
614630 } ;
615631
616632 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+ } ,
617636 ty:: Param ( _) => {
618637 set_skip_flag ( ) ;
619638 } ,
@@ -665,6 +684,31 @@ fn check_ptr_arg_usage<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, args:
665684 v. results
666685}
667686
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+
668712fn get_rptr_lm < ' tcx > ( ty : & ' tcx hir:: Ty < ' tcx > ) -> Option < ( & ' tcx Lifetime , Mutability , Span ) > {
669713 if let TyKind :: Rptr ( lt, ref m) = ty. kind {
670714 Some ( ( lt, m. mutbl , ty. span ) )
0 commit comments