44use rustc_hir:: def:: Res ;
55use rustc_hir:: def_id:: DefId ;
66use rustc_hir:: { Expr , ExprKind , HirId } ;
7- use rustc_middle:: ty:: {
8- self , ClauseKind , GenericArgsRef , ParamTy , ProjectionPredicate , TraitPredicate , Ty ,
9- } ;
7+ use rustc_infer:: infer:: canonical:: ir:: TraitPredicate ;
8+ use rustc_middle:: ty:: { self , ClauseKind , GenericArgsRef , PredicatePolarity , Ty } ;
109use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1110use rustc_span:: hygiene:: { ExpnKind , MacroKind } ;
1211use rustc_span:: { Span , sym} ;
@@ -122,47 +121,38 @@ fn check_into_iter_stability<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx
122121 return ;
123122 } ;
124123 // Is `expr` a function or method call?
125- let Some ( ( callee_def_id, _span , generic_args, recv , args ) ) =
124+ let Some ( ( callee_def_id, span , generic_args, _recv , _args ) ) =
126125 get_callee_span_generic_args_and_args ( cx, expr)
127126 else {
128127 return ;
129128 } ;
130- let fn_sig = cx. tcx . fn_sig ( callee_def_id) . instantiate_identity ( ) . skip_binder ( ) ;
131- for ( arg_index, & input) in fn_sig. inputs ( ) . iter ( ) . enumerate ( ) {
132- let & ty:: Param ( ParamTy { index : param_index, .. } ) = input. kind ( ) else {
129+ let predicates = cx. tcx . predicates_of ( callee_def_id) . instantiate ( cx. tcx , generic_args) ;
130+ for ( predicate, _) in predicates {
131+ let ClauseKind :: Trait ( TraitPredicate { trait_ref, polarity : PredicatePolarity :: Positive } ) =
132+ predicate. kind ( ) . skip_binder ( )
133+ else {
133134 continue ;
134135 } ;
135- let ( trait_predicates, _) = get_input_traits_and_projections ( cx, callee_def_id, input) ;
136- for TraitPredicate { trait_ref, .. } in trait_predicates {
137- // Does the function or method require any of its arguments to implement `IntoIterator`?
138- if trait_ref. def_id != into_iterator_def_id {
139- continue ;
140- }
141- let self_ty_generic_arg = generic_args[ param_index as usize ] ;
142- let Ok ( Some ( instance) ) = ty:: Instance :: try_resolve (
143- cx. tcx ,
144- cx. typing_env ( ) ,
145- into_iter_fn_def_id,
146- cx. tcx . mk_args ( & [ self_ty_generic_arg] ) ,
147- ) else {
148- continue ;
149- } ;
150- // Does the input type's `IntoIterator` implementation have the
151- // `rustc_lint_query_instability` attribute on its `into_iter` method?
152- if !cx. tcx . has_attr ( instance. def_id ( ) , sym:: rustc_lint_query_instability) {
153- return ;
154- }
155- let span = if let Some ( recv) = recv {
156- if arg_index == 0 { recv. span } else { args[ arg_index - 1 ] . span }
157- } else {
158- args[ arg_index] . span
159- } ;
160- cx. emit_span_lint (
161- POTENTIAL_QUERY_INSTABILITY ,
162- span,
163- QueryInstability { query : cx. tcx . item_name ( instance. def_id ( ) ) } ,
164- ) ;
136+ // Does the function or method require any of its arguments to implement `IntoIterator`?
137+ if trait_ref. def_id != into_iterator_def_id {
138+ continue ;
139+ }
140+ let Ok ( Some ( instance) ) =
141+ ty:: Instance :: try_resolve ( cx. tcx , cx. typing_env ( ) , into_iter_fn_def_id, trait_ref. args )
142+ else {
143+ continue ;
144+ } ;
145+ // Does the input type's `IntoIterator` implementation have the
146+ // `rustc_lint_query_instability` attribute on its `into_iter` method?
147+ if !cx. tcx . has_attr ( instance. def_id ( ) , sym:: rustc_lint_query_instability) {
148+ return ;
165149 }
150+ let span = span. with_hi ( expr. span . hi ( ) ) ;
151+ cx. emit_span_lint (
152+ POTENTIAL_QUERY_INSTABILITY ,
153+ span,
154+ QueryInstability { query : cx. tcx . item_name ( instance. def_id ( ) ) } ,
155+ ) ;
166156 }
167157}
168158
@@ -188,32 +178,6 @@ fn get_callee_span_generic_args_and_args<'tcx>(
188178 None
189179}
190180
191- /// Returns the `TraitPredicate`s and `ProjectionPredicate`s for a function's input type.
192- fn get_input_traits_and_projections < ' tcx > (
193- cx : & LateContext < ' tcx > ,
194- callee_def_id : DefId ,
195- input : Ty < ' tcx > ,
196- ) -> ( Vec < TraitPredicate < ' tcx > > , Vec < ProjectionPredicate < ' tcx > > ) {
197- let mut trait_predicates = Vec :: new ( ) ;
198- let mut projection_predicates = Vec :: new ( ) ;
199- for predicate in cx. tcx . param_env ( callee_def_id) . caller_bounds ( ) {
200- match predicate. kind ( ) . skip_binder ( ) {
201- ClauseKind :: Trait ( trait_predicate) => {
202- if trait_predicate. trait_ref . self_ty ( ) == input {
203- trait_predicates. push ( trait_predicate) ;
204- }
205- }
206- ClauseKind :: Projection ( projection_predicate) => {
207- if projection_predicate. projection_term . self_ty ( ) == input {
208- projection_predicates. push ( projection_predicate) ;
209- }
210- }
211- _ => { }
212- }
213- }
214- ( trait_predicates, projection_predicates)
215- }
216-
217181declare_tool_lint ! {
218182 /// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,
219183 /// where `ty::<kind>` would suffice.
0 commit comments