Skip to content

Commit 610cb4d

Browse files
committed
Simplify predicate handling
1 parent c9766de commit 610cb4d

File tree

2 files changed

+31
-67
lines changed

2 files changed

+31
-67
lines changed

compiler/rustc_lint/src/internal.rs

Lines changed: 27 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44
use rustc_hir::def::Res;
55
use rustc_hir::def_id::DefId;
66
use 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};
109
use rustc_session::{declare_lint_pass, declare_tool_lint};
1110
use rustc_span::hygiene::{ExpnKind, MacroKind};
1211
use 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-
217181
declare_tool_lint! {
218182
/// The `usage_of_ty_tykind` lint detects usages of `ty::TyKind::<kind>`,
219183
/// where `ty::<kind>` would suffice.

tests/ui-fulldeps/internal-lints/query_stability.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,18 @@ LL | for val in x.values_mut() {
6060
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
6161

6262
error: using `into_iter` can result in unstable query results
63-
--> $DIR/query_stability.rs:38:45
63+
--> $DIR/query_stability.rs:38:38
6464
|
6565
LL | FxHashMap::<u32, i32>::default().extend(x);
66-
| ^
66+
| ^^^^^^^^^
6767
|
6868
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
6969

7070
error: using `into_iter` can result in unstable query results
71-
--> $DIR/query_stability.rs:47:24
71+
--> $DIR/query_stability.rs:47:9
7272
|
7373
LL | _ = hide_into_iter(map);
74-
| ^^^
74+
| ^^^^^^^^^^^^^^^^^^^
7575
|
7676
= note: if you believe this case to be fine, allow this lint and add a comment explaining your rationale
7777

0 commit comments

Comments
 (0)