@@ -12,7 +12,7 @@ use crate::rustc::infer::InferCtxt;
12
12
use crate :: rustc:: lint:: { LateContext , LateLintPass , LintArray , LintPass } ;
13
13
use crate :: rustc:: traits;
14
14
use crate :: rustc:: ty:: adjustment:: Adjust ;
15
- use crate :: rustc:: ty:: { self , ToPolyTraitRef , Ty } ;
15
+ use crate :: rustc:: ty:: { self , ToPolyTraitRef , Ty , TyCtxt } ;
16
16
use crate :: rustc:: { declare_tool_lint, lint_array} ;
17
17
use crate :: syntax_pos:: symbol:: Ident ;
18
18
use crate :: utils:: { match_def_path, paths, span_lint_and_then} ;
@@ -96,21 +96,27 @@ fn check_unsize_coercion<'tcx>(
96
96
// redo the typechecking for this coercion to see if it required unsizing something to `dyn Any`
97
97
// see https://github.com/rust-lang/rust/blob/cae6efc37d70ab7d353e6ab9ce229d59a65ed643/src/librustc_typeck/check/coercion.rs#L454-L611
98
98
let tcx = infcx. tcx ;
99
+ let coerce_unsized_trait_did = tcx. lang_items ( ) . coerce_unsized_trait ( ) . unwrap ( ) ;
100
+ let unsize_trait_did = tcx. lang_items ( ) . unsize_trait ( ) . unwrap ( ) ;
101
+
99
102
// don't report overflow errors
100
103
let mut selcx = traits:: SelectionContext :: with_query_mode ( & infcx, traits:: TraitQueryMode :: Canonical ) ;
101
104
let mut queue = VecDeque :: new ( ) ;
102
105
queue. push_back (
103
106
ty:: TraitRef :: new (
104
- tcx . lang_items ( ) . coerce_unsized_trait ( ) . unwrap ( ) ,
107
+ coerce_unsized_trait_did ,
105
108
tcx. mk_substs_trait ( src_ty, & [ tgt_ty. into ( ) ] ) ,
106
109
)
107
110
. to_poly_trait_ref ( ) ,
108
111
) ;
109
112
while let Some ( trait_ref) = queue. pop_front ( ) {
110
- if match_def_path ( tcx, trait_ref. def_id ( ) , & paths:: ANY_TRAIT ) {
113
+ if_chain ! {
114
+ if trait_ref. def_id( ) == unsize_trait_did;
115
+ if is_type_dyn_any( tcx, trait_ref. skip_binder( ) . input_types( ) . nth( 1 ) . unwrap( ) ) ;
111
116
// found something unsizing to `dyn Any`
112
117
let coerced_to_any = trait_ref. self_ty( ) ;
113
- if type_contains_any ( & mut selcx, param_env, coerced_to_any) {
118
+ if type_contains_any( & mut selcx, param_env, coerced_to_any) ;
119
+ then {
114
120
return Some ( LintData { coerced_to_any } ) ;
115
121
}
116
122
}
@@ -120,12 +126,14 @@ fn check_unsize_coercion<'tcx>(
120
126
trait_ref. to_poly_trait_predicate ( ) ,
121
127
) ) ;
122
128
if let Ok ( Some ( vtable) ) = select_result {
123
- // we only care about trait predicates
129
+ // we only care about trait predicates for these traits
130
+ let traits = [ coerce_unsized_trait_did, unsize_trait_did] ;
124
131
queue. extend (
125
132
vtable
126
133
. nested_obligations ( )
127
134
. into_iter ( )
128
- . filter_map ( |oblig| oblig. predicate . to_opt_poly_trait_ref ( ) ) ,
135
+ . filter_map ( |oblig| oblig. predicate . to_opt_poly_trait_ref ( ) )
136
+ . filter ( |tr| traits. contains ( & tr. def_id ( ) ) ) ,
129
137
) ;
130
138
}
131
139
}
@@ -140,8 +148,7 @@ fn type_contains_any<'tcx>(
140
148
// check if it derefs to `dyn Any`
141
149
if_chain ! {
142
150
if let Some ( ( any_src_deref_ty, _deref_count) ) = fully_deref_type( selcx, param_env, ty) ;
143
- if let ty:: TyKind :: Dynamic ( trait_list, _) = any_src_deref_ty. sty;
144
- if match_def_path( selcx. tcx( ) , trait_list. skip_binder( ) . principal( ) . def_id, & paths:: ANY_TRAIT ) ;
151
+ if is_type_dyn_any( selcx. tcx( ) , any_src_deref_ty) ;
145
152
then {
146
153
// TODO: use deref_count to make a suggestion
147
154
return true ;
@@ -151,6 +158,20 @@ fn type_contains_any<'tcx>(
151
158
false
152
159
}
153
160
161
+ fn is_type_dyn_any < ' tcx > (
162
+ tcx : TyCtxt < ' _ , ' _ , ' tcx > ,
163
+ ty : Ty < ' tcx > ,
164
+ ) -> bool {
165
+ if_chain ! {
166
+ if let ty:: TyKind :: Dynamic ( trait_list, _) = ty. sty;
167
+ if match_def_path( tcx, trait_list. skip_binder( ) . principal( ) . def_id, & paths:: ANY_TRAIT ) ;
168
+ then {
169
+ return true ;
170
+ }
171
+ }
172
+ false
173
+ }
174
+
154
175
/// Calls [deref_type] repeatedly
155
176
fn fully_deref_type < ' tcx > (
156
177
selcx : & mut traits:: SelectionContext < ' _ , ' _ , ' tcx > ,
0 commit comments