mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
Fix ICE in match_same_arms (#16685)
The wrong `TypeckResults` was used in the fallback equality function passed by the `match_same_arms` and `filter_map` lints. Previously, those fallback functions had no way of using the proper `TypeckResults`. Those (one per expression being compared) are now passed to the registered fallback function. changelog: [`match_same_arms`]: fix internal compiler error Fixes rust-lang/rust-clippy#16678 Fixes rust-lang/rust-clippy#16686 <!-- TRIAGEBOT_START --> <!-- TRIAGEBOT_SUMMARY_START --> ### Summary Notes - [Beta nomination](https://github.com/rust-lang/rust-clippy/pull/16685#issuecomment-4017155418) by [samueltardieu](https://github.com/samueltardieu) *Managed by `@rustbot`—see [help](https://forge.rust-lang.org/triagebot/note.html) for details* <!-- TRIAGEBOT_SUMMARY_END --> <!-- TRIAGEBOT_END -->
This commit is contained in:
committed by
Josh Stone
parent
6ae56934ab
commit
0c9d5f0d25
@@ -12,7 +12,7 @@
|
||||
use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExpr, PatExprKind, PatKind, RangeEnd};
|
||||
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::{self, TypeckResults};
|
||||
use rustc_span::{ByteSymbol, ErrorGuaranteed, Span, Symbol};
|
||||
|
||||
use super::MATCH_SAME_ARMS;
|
||||
@@ -61,7 +61,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
||||
|
||||
let check_eq_with_pat = |expr_a: &Expr<'_>, expr_b: &Expr<'_>| {
|
||||
let mut local_map: HirIdMap<HirId> = HirIdMap::default();
|
||||
let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| {
|
||||
let eq_fallback = |a_typeck_results: &TypeckResults<'tcx>,
|
||||
a: &Expr<'_>,
|
||||
b_typeck_results: &TypeckResults<'tcx>,
|
||||
b: &Expr<'_>| {
|
||||
if let Some(a_id) = a.res_local_id()
|
||||
&& let Some(b_id) = b.res_local_id()
|
||||
&& let entry = match local_map.entry(a_id) {
|
||||
@@ -71,7 +74,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
|
||||
}
|
||||
// the names technically don't have to match; this makes the lint more conservative
|
||||
&& cx.tcx.hir_name(a_id) == cx.tcx.hir_name(b_id)
|
||||
&& cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b)
|
||||
&& a_typeck_results.expr_ty(a) == b_typeck_results.expr_ty(b)
|
||||
&& pat_contains_local(lhs.pat, a_id)
|
||||
&& pat_contains_local(rhs.pat, b_id)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
use rustc_hir::def::Res;
|
||||
use rustc_hir::{Closure, Expr, ExprKind, PatKind, PathSegment, QPath, UnOp};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::TypeckResults;
|
||||
use rustc_middle::ty::adjustment::Adjust;
|
||||
use rustc_span::Span;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
@@ -136,7 +137,9 @@ pub fn check_map_call(
|
||||
// .map(|y| y[.acceptable_method()].unwrap())
|
||||
&& let simple_equal = (receiver.res_local_id() == Some(filter_param_id)
|
||||
&& map_arg_peeled.res_local_id() == Some(map_param_id))
|
||||
&& let eq_fallback = (|a: &Expr<'_>, b: &Expr<'_>| {
|
||||
&& let eq_fallback =
|
||||
(|a_typeck_results: &TypeckResults<'tcx>, a: &Expr<'_>,
|
||||
b_typeck_results: &TypeckResults<'tcx>, b: &Expr<'_>| {
|
||||
// in `filter(|x| ..)`, replace `*x` with `x`
|
||||
let a_path = if !is_filter_param_ref
|
||||
&& let ExprKind::Unary(UnOp::Deref, expr_path) = a.kind
|
||||
@@ -144,7 +147,7 @@ pub fn check_map_call(
|
||||
// let the filter closure arg and the map closure arg be equal
|
||||
a_path.res_local_id() == Some(filter_param_id)
|
||||
&& b.res_local_id() == Some(map_param_id)
|
||||
&& cx.typeck_results().expr_ty_adjusted(a) == cx.typeck_results().expr_ty_adjusted(b)
|
||||
&& a_typeck_results.expr_ty_adjusted(a) == b_typeck_results.expr_ty_adjusted(b)
|
||||
})
|
||||
&& (simple_equal
|
||||
|| SpanlessEq::new(cx).expr_fallback(eq_fallback).eq_expr(receiver, map_arg_peeled))
|
||||
|
||||
@@ -26,7 +26,8 @@
|
||||
|
||||
/// Callback that is called when two expressions are not equal in the sense of `SpanlessEq`, but
|
||||
/// other conditions would make them equal.
|
||||
type SpanlessEqCallback<'a> = dyn FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a;
|
||||
type SpanlessEqCallback<'a, 'tcx> =
|
||||
dyn FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a;
|
||||
|
||||
/// Determines how paths are hashed and compared for equality.
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
@@ -59,7 +60,7 @@ pub struct SpanlessEq<'a, 'tcx> {
|
||||
cx: &'a LateContext<'tcx>,
|
||||
maybe_typeck_results: Option<(&'tcx TypeckResults<'tcx>, &'tcx TypeckResults<'tcx>)>,
|
||||
allow_side_effects: bool,
|
||||
expr_fallback: Option<Box<SpanlessEqCallback<'a>>>,
|
||||
expr_fallback: Option<Box<SpanlessEqCallback<'a, 'tcx>>>,
|
||||
path_check: PathCheck,
|
||||
}
|
||||
|
||||
@@ -94,7 +95,10 @@ pub fn paths_by_resolution(self) -> Self {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn expr_fallback(self, expr_fallback: impl FnMut(&Expr<'_>, &Expr<'_>) -> bool + 'a) -> Self {
|
||||
pub fn expr_fallback(
|
||||
self,
|
||||
expr_fallback: impl FnMut(&TypeckResults<'tcx>, &Expr<'_>, &TypeckResults<'tcx>, &Expr<'_>) -> bool + 'a,
|
||||
) -> Self {
|
||||
Self {
|
||||
expr_fallback: Some(Box::new(expr_fallback)),
|
||||
..self
|
||||
@@ -639,7 +643,15 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
|
||||
) => false,
|
||||
};
|
||||
(is_eq && (!self.should_ignore(left) || !self.should_ignore(right)))
|
||||
|| self.inner.expr_fallback.as_mut().is_some_and(|f| f(left, right))
|
||||
|| self
|
||||
.inner
|
||||
.maybe_typeck_results
|
||||
.is_some_and(|(left_typeck_results, right_typeck_results)| {
|
||||
self.inner
|
||||
.expr_fallback
|
||||
.as_mut()
|
||||
.is_some_and(|f| f(left_typeck_results, left, right_typeck_results, right))
|
||||
})
|
||||
}
|
||||
|
||||
fn eq_exprs(&mut self, left: &[Expr<'_>], right: &[Expr<'_>]) -> bool {
|
||||
|
||||
@@ -140,3 +140,19 @@ fn main() {
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue16678() {
|
||||
// ICE in Rust 1.94.0
|
||||
match true {
|
||||
true => {
|
||||
fn wrapper(_arg: ()) {
|
||||
_arg;
|
||||
}
|
||||
},
|
||||
false => {
|
||||
fn wrapper(_arg: ()) {
|
||||
_arg;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,3 +149,19 @@ fn main() {
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
fn issue16678() {
|
||||
// ICE in Rust 1.94.0
|
||||
match true {
|
||||
true => {
|
||||
fn wrapper(_arg: ()) {
|
||||
_arg;
|
||||
}
|
||||
},
|
||||
false => {
|
||||
fn wrapper(_arg: ()) {
|
||||
_arg;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user