Merge remote-tracking branch 'upstream/master' into rustup

This commit is contained in:
Philipp Krones 2025-04-03 21:31:02 +02:00
commit ab7e525929
No known key found for this signature in database
GPG key ID: 1CA0DF2AF59D68A5
377 changed files with 6426 additions and 3724 deletions

View file

@ -347,11 +347,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
safety: rs,
define_opaque: _,
}),
) => eq_id(*li, *ri)
&& lm == rm
&& ls == rs
&& eq_ty(lt, rt)
&& eq_expr_opt(le.as_ref(), re.as_ref()),
) => eq_id(*li, *ri) && lm == rm && ls == rs && eq_ty(lt, rt) && eq_expr_opt(le.as_ref(), re.as_ref()),
(
Const(box ConstItem {
defaultness: ld,
@ -369,11 +365,13 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
expr: re,
define_opaque: _,
}),
) => eq_defaultness(*ld, *rd)
) => {
eq_defaultness(*ld, *rd)
&& eq_id(*li, *ri)
&& eq_generics(lg, rg)
&& eq_ty(lt, rt)
&& eq_expr_opt(le.as_ref(), re.as_ref()),
&& eq_expr_opt(le.as_ref(), re.as_ref())
},
(
Fn(box ast::Fn {
defaultness: ld,
@ -439,7 +437,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
},
(Enum(li, le, lg), Enum(ri, re, rg)) => {
eq_id(*li, *ri) && over(&le.variants, &re.variants, eq_variant) && eq_generics(lg, rg)
}
},
(Struct(li, lv, lg), Struct(ri, rv, rg)) | (Union(li, lv, lg), Union(ri, rv, rg)) => {
eq_id(*li, *ri) && eq_variant_data(lv, rv) && eq_generics(lg, rg)
},
@ -470,7 +468,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
},
(TraitAlias(li, lg, lb), TraitAlias(ri, rg, rb)) => {
eq_id(*li, *ri) && eq_generics(lg, rg) && over(lb, rb, eq_generic_bound)
}
},
(
Impl(box ast::Impl {
safety: lu,
@ -505,7 +503,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
(MacCall(l), MacCall(r)) => eq_mac_call(l, r),
(MacroDef(li, ld), MacroDef(ri, rd)) => {
eq_id(*li, *ri) && ld.macro_rules == rd.macro_rules && eq_delim_args(&ld.body, &rd.body)
}
},
_ => false,
}
}
@ -530,13 +528,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
safety: rs,
define_opaque: _,
}),
) => {
eq_id(*li, *ri)
&& eq_ty(lt, rt)
&& lm == rm
&& eq_expr_opt(le.as_ref(), re.as_ref())
&& ls == rs
}
) => eq_id(*li, *ri) && eq_ty(lt, rt) && lm == rm && eq_expr_opt(le.as_ref(), re.as_ref()) && ls == rs,
(
Fn(box ast::Fn {
defaultness: ld,
@ -619,7 +611,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
&& eq_generics(lg, rg)
&& eq_ty(lt, rt)
&& eq_expr_opt(le.as_ref(), re.as_ref())
}
},
(
Fn(box ast::Fn {
defaultness: ld,

View file

@ -43,14 +43,16 @@ pub enum Constant<'tcx> {
Char(char),
/// An integer's bit representation.
Int(u128),
/// An `f16`.
F16(f16),
/// An `f16` bitcast to a `u16`.
// FIXME(f16_f128): use `f16` once builtins are available on all host tools platforms.
F16(u16),
/// An `f32`.
F32(f32),
/// An `f64`.
F64(f64),
/// An `f128`.
F128(f128),
/// An `f128` bitcast to a `u128`.
// FIXME(f16_f128): use `f128` once builtins are available on all host tools platforms.
F128(u128),
/// `true` or `false`.
Bool(bool),
/// An array of constants.
@ -177,7 +179,7 @@ impl Hash for Constant<'_> {
},
Self::F16(f) => {
// FIXME(f16_f128): once conversions to/from `f128` are available on all platforms,
f.to_bits().hash(state);
f.hash(state);
},
Self::F32(f) => {
f64::from(f).to_bits().hash(state);
@ -186,7 +188,7 @@ impl Hash for Constant<'_> {
f.to_bits().hash(state);
},
Self::F128(f) => {
f.to_bits().hash(state);
f.hash(state);
},
Self::Bool(b) => {
b.hash(state);
@ -292,12 +294,12 @@ impl Constant<'_> {
fn parse_f16(s: &str) -> Self {
let f: Half = s.parse().unwrap();
Self::F16(f16::from_bits(f.to_bits().try_into().unwrap()))
Self::F16(f.to_bits().try_into().unwrap())
}
fn parse_f128(s: &str) -> Self {
let f: Quad = s.parse().unwrap();
Self::F128(f128::from_bits(f.to_bits()))
Self::F128(f.to_bits())
}
}
@ -868,10 +870,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option
ty::Adt(adt_def, _) if adt_def.is_struct() => Some(Constant::Adt(result)),
ty::Bool => Some(Constant::Bool(int == ScalarInt::TRUE)),
ty::Uint(_) | ty::Int(_) => Some(Constant::Int(int.to_bits(int.size()))),
ty::Float(FloatTy::F16) => Some(Constant::F16(f16::from_bits(int.into()))),
ty::Float(FloatTy::F16) => Some(Constant::F16(int.into())),
ty::Float(FloatTy::F32) => Some(Constant::F32(f32::from_bits(int.into()))),
ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits(int.into()))),
ty::Float(FloatTy::F128) => Some(Constant::F128(f128::from_bits(int.into()))),
ty::Float(FloatTy::F128) => Some(Constant::F128(int.into())),
ty::RawPtr(_, _) => Some(Constant::RawPtr(int.to_bits(int.size()))),
_ => None,
},
@ -892,10 +894,10 @@ pub fn mir_to_const<'tcx>(tcx: TyCtxt<'tcx>, result: mir::Const<'tcx>) -> Option
let range = alloc_range(offset + size * idx, size);
let val = alloc.read_scalar(&tcx, range, /* read_provenance */ false).ok()?;
res.push(match flt {
FloatTy::F16 => Constant::F16(f16::from_bits(val.to_u16().discard_err()?)),
FloatTy::F16 => Constant::F16(val.to_u16().discard_err()?),
FloatTy::F32 => Constant::F32(f32::from_bits(val.to_u32().discard_err()?)),
FloatTy::F64 => Constant::F64(f64::from_bits(val.to_u64().discard_err()?)),
FloatTy::F128 => Constant::F128(f128::from_bits(val.to_u128().discard_err()?)),
FloatTy::F128 => Constant::F128(val.to_u128().discard_err()?),
});
}
Some(Constant::Vec(res))

View file

@ -17,16 +17,16 @@ use rustc_span::Span;
use std::env;
fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() {
if let Some(lint) = lint.name_lower().strip_prefix("clippy::") {
diag.help(format!(
"for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
&option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
// extract just major + minor version and ignore patch versions
format!("rust-{}", n.rsplit_once('.').unwrap().1)
})
));
}
if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err()
&& let Some(lint) = lint.name_lower().strip_prefix("clippy::")
{
diag.help(format!(
"for further information visit https://rust-lang.github.io/rust-clippy/{}/index.html#{lint}",
&option_env!("RUST_RELEASE_NUM").map_or("master".to_string(), |n| {
// extract just major + minor version and ignore patch versions
format!("rust-{}", n.rsplit_once('.').unwrap().1)
})
));
}
}

View file

@ -118,18 +118,17 @@ impl<'hir> IfLet<'hir> {
) = expr.kind
{
let mut iter = cx.tcx.hir_parent_iter(expr.hir_id);
if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next() {
if let Some((
if let Some((_, Node::Block(Block { stmts: [], .. }))) = iter.next()
&& let Some((
_,
Node::Expr(Expr {
kind: ExprKind::Loop(_, _, LoopSource::While, _),
..
}),
)) = iter.next()
{
// while loop desugar
return None;
}
{
// while loop desugar
return None;
}
return Some(Self {
let_pat,
@ -176,6 +175,12 @@ impl<'hir> IfLetOrMatch<'hir> {
),
}
}
pub fn scrutinee(&self) -> &'hir Expr<'hir> {
match self {
Self::Match(scrutinee, _, _) | Self::IfLet(scrutinee, _, _, _, _) => scrutinee,
}
}
}
/// An `if` or `if let` expression

View file

@ -148,7 +148,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> {
impl HirEqInterExpr<'_, '_, '_> {
pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool {
match (&left.kind, &right.kind) {
(&StmtKind::Let(l), &StmtKind::Let(r)) => {
(StmtKind::Let(l), StmtKind::Let(r)) => {
// This additional check ensures that the type of the locals are equivalent even if the init
// expression or type have some inferred parts.
if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results {
@ -166,7 +166,7 @@ impl HirEqInterExpr<'_, '_, '_> {
&& both(l.els.as_ref(), r.els.as_ref(), |l, r| self.eq_block(l, r))
&& self.eq_pat(l.pat, r.pat)
},
(&StmtKind::Expr(l), &StmtKind::Expr(r)) | (&StmtKind::Semi(l), &StmtKind::Semi(r)) => self.eq_expr(l, r),
(StmtKind::Expr(l), StmtKind::Expr(r)) | (StmtKind::Semi(l), StmtKind::Semi(r)) => self.eq_expr(l, r),
_ => false,
}
}
@ -260,7 +260,7 @@ impl HirEqInterExpr<'_, '_, '_> {
fn should_ignore(&mut self, expr: &Expr<'_>) -> bool {
macro_backtrace(expr.span).last().is_some_and(|macro_call| {
matches!(
&self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
self.inner.cx.tcx.get_diagnostic_name(macro_call.def_id),
Some(sym::todo_macro | sym::unimplemented_macro)
)
})
@ -301,58 +301,58 @@ impl HirEqInterExpr<'_, '_, '_> {
reduce_exprkind(self.inner.cx, &left.kind),
reduce_exprkind(self.inner.cx, &right.kind),
) {
(&ExprKind::AddrOf(lb, l_mut, le), &ExprKind::AddrOf(rb, r_mut, re)) => {
(ExprKind::AddrOf(lb, l_mut, le), ExprKind::AddrOf(rb, r_mut, re)) => {
lb == rb && l_mut == r_mut && self.eq_expr(le, re)
},
(&ExprKind::Array(l), &ExprKind::Array(r)) => self.eq_exprs(l, r),
(&ExprKind::Assign(ll, lr, _), &ExprKind::Assign(rl, rr, _)) => {
(ExprKind::Array(l), ExprKind::Array(r)) => self.eq_exprs(l, r),
(ExprKind::Assign(ll, lr, _), ExprKind::Assign(rl, rr, _)) => {
self.inner.allow_side_effects && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
},
(&ExprKind::AssignOp(ref lo, ll, lr), &ExprKind::AssignOp(ref ro, rl, rr)) => {
(ExprKind::AssignOp(lo, ll, lr), ExprKind::AssignOp(ro, rl, rr)) => {
self.inner.allow_side_effects && lo.node == ro.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
},
(&ExprKind::Block(l, _), &ExprKind::Block(r, _)) => self.eq_block(l, r),
(&ExprKind::Binary(l_op, ll, lr), &ExprKind::Binary(r_op, rl, rr)) => {
(ExprKind::Block(l, _), ExprKind::Block(r, _)) => self.eq_block(l, r),
(ExprKind::Binary(l_op, ll, lr), ExprKind::Binary(r_op, rl, rr)) => {
l_op.node == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
|| swap_binop(l_op.node, ll, lr).is_some_and(|(l_op, ll, lr)| {
l_op == r_op.node && self.eq_expr(ll, rl) && self.eq_expr(lr, rr)
})
},
(&ExprKind::Break(li, ref le), &ExprKind::Break(ri, ref re)) => {
(ExprKind::Break(li, le), ExprKind::Break(ri, re)) => {
both(li.label.as_ref(), ri.label.as_ref(), |l, r| l.ident.name == r.ident.name)
&& both(le.as_ref(), re.as_ref(), |l, r| self.eq_expr(l, r))
},
(&ExprKind::Call(l_fun, l_args), &ExprKind::Call(r_fun, r_args)) => {
(ExprKind::Call(l_fun, l_args), ExprKind::Call(r_fun, r_args)) => {
self.inner.allow_side_effects && self.eq_expr(l_fun, r_fun) && self.eq_exprs(l_args, r_args)
},
(&ExprKind::Cast(lx, lt), &ExprKind::Cast(rx, rt)) => {
(ExprKind::Cast(lx, lt), ExprKind::Cast(rx, rt)) => {
self.eq_expr(lx, rx) && self.eq_ty(lt, rt)
},
(&ExprKind::Closure(_l), &ExprKind::Closure(_r)) => false,
(&ExprKind::ConstBlock(lb), &ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
(&ExprKind::Continue(li), &ExprKind::Continue(ri)) => {
(ExprKind::Closure(_l), ExprKind::Closure(_r)) => false,
(ExprKind::ConstBlock(lb), ExprKind::ConstBlock(rb)) => self.eq_body(lb.body, rb.body),
(ExprKind::Continue(li), ExprKind::Continue(ri)) => {
both(li.label.as_ref(), ri.label.as_ref(), |l, r| l.ident.name == r.ident.name)
},
(&ExprKind::DropTemps(le), &ExprKind::DropTemps(re)) => self.eq_expr(le, re),
(&ExprKind::Field(l_f_exp, ref l_f_ident), &ExprKind::Field(r_f_exp, ref r_f_ident)) => {
(ExprKind::DropTemps(le), ExprKind::DropTemps(re)) => self.eq_expr(le, re),
(ExprKind::Field(l_f_exp, l_f_ident), ExprKind::Field(r_f_exp, r_f_ident)) => {
l_f_ident.name == r_f_ident.name && self.eq_expr(l_f_exp, r_f_exp)
},
(&ExprKind::Index(la, li, _), &ExprKind::Index(ra, ri, _)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
(&ExprKind::If(lc, lt, ref le), &ExprKind::If(rc, rt, ref re)) => {
(ExprKind::Index(la, li, _), ExprKind::Index(ra, ri, _)) => self.eq_expr(la, ra) && self.eq_expr(li, ri),
(ExprKind::If(lc, lt, le), ExprKind::If(rc, rt, re)) => {
self.eq_expr(lc, rc) && self.eq_expr(lt, rt)
&& both(le.as_ref(), re.as_ref(), |l, r| self.eq_expr(l, r))
},
(&ExprKind::Let(l), &ExprKind::Let(r)) => {
(ExprKind::Let(l), ExprKind::Let(r)) => {
self.eq_pat(l.pat, r.pat)
&& both(l.ty.as_ref(), r.ty.as_ref(), |l, r| self.eq_ty(l, r))
&& self.eq_expr(l.init, r.init)
},
(ExprKind::Lit(l), ExprKind::Lit(r)) => l.node == r.node,
(&ExprKind::Loop(lb, ref ll, ref lls, _), &ExprKind::Loop(rb, ref rl, ref rls, _)) => {
(ExprKind::Loop(lb, ll, lls, _), ExprKind::Loop(rb, rl, rls, _)) => {
lls == rls && self.eq_block(lb, rb)
&& both(ll.as_ref(), rl.as_ref(), |l, r| l.ident.name == r.ident.name)
},
(&ExprKind::Match(le, la, ref ls), &ExprKind::Match(re, ra, ref rs)) => {
(ExprKind::Match(le, la, ls), ExprKind::Match(re, ra, rs)) => {
(ls == rs || (matches!((ls, rs), (TryDesugar(_), TryDesugar(_)))))
&& self.eq_expr(le, re)
&& over(la, ra, |l, r| {
@ -362,27 +362,27 @@ impl HirEqInterExpr<'_, '_, '_> {
})
},
(
&ExprKind::MethodCall(l_path, l_receiver, l_args, _),
&ExprKind::MethodCall(r_path, r_receiver, r_args, _),
ExprKind::MethodCall(l_path, l_receiver, l_args, _),
ExprKind::MethodCall(r_path, r_receiver, r_args, _),
) => {
self.inner.allow_side_effects
&& self.eq_path_segment(l_path, r_path)
&& self.eq_expr(l_receiver, r_receiver)
&& self.eq_exprs(l_args, r_args)
},
(&ExprKind::UnsafeBinderCast(lkind, le, None), &ExprKind::UnsafeBinderCast(rkind, re, None)) =>
(ExprKind::UnsafeBinderCast(lkind, le, None), ExprKind::UnsafeBinderCast(rkind, re, None)) =>
lkind == rkind && self.eq_expr(le, re),
(&ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), &ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) =>
(ExprKind::UnsafeBinderCast(lkind, le, Some(lt)), ExprKind::UnsafeBinderCast(rkind, re, Some(rt))) =>
lkind == rkind && self.eq_expr(le, re) && self.eq_ty(lt, rt),
(&ExprKind::OffsetOf(l_container, l_fields), &ExprKind::OffsetOf(r_container, r_fields)) => {
(ExprKind::OffsetOf(l_container, l_fields), ExprKind::OffsetOf(r_container, r_fields)) => {
self.eq_ty(l_container, r_container) && over(l_fields, r_fields, |l, r| l.name == r.name)
},
(ExprKind::Path(l), ExprKind::Path(r)) => self.eq_qpath(l, r),
(&ExprKind::Repeat(le, ll), &ExprKind::Repeat(re, rl)) => {
(ExprKind::Repeat(le, ll), ExprKind::Repeat(re, rl)) => {
self.eq_expr(le, re) && self.eq_const_arg(ll, rl)
},
(ExprKind::Ret(l), ExprKind::Ret(r)) => both(l.as_ref(), r.as_ref(), |l, r| self.eq_expr(l, r)),
(&ExprKind::Struct(l_path, lf, ref lo), &ExprKind::Struct(r_path, rf, ref ro)) => {
(ExprKind::Struct(l_path, lf, lo), ExprKind::Struct(r_path, rf, ro)) => {
self.eq_qpath(l_path, r_path)
&& match (lo, ro) {
(StructTailExpr::Base(l),StructTailExpr::Base(r)) => self.eq_expr(l, r),
@ -392,58 +392,58 @@ impl HirEqInterExpr<'_, '_, '_> {
}
&& over(lf, rf, |l, r| self.eq_expr_field(l, r))
},
(&ExprKind::Tup(l_tup), &ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
(&ExprKind::Use(l_expr, _), &ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr),
(&ExprKind::Type(le, lt), &ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
(&ExprKind::Unary(l_op, le), &ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
(&ExprKind::Yield(le, _), &ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
(ExprKind::Tup(l_tup), ExprKind::Tup(r_tup)) => self.eq_exprs(l_tup, r_tup),
(ExprKind::Use(l_expr, _), ExprKind::Use(r_expr, _)) => self.eq_expr(l_expr, r_expr),
(ExprKind::Type(le, lt), ExprKind::Type(re, rt)) => self.eq_expr(le, re) && self.eq_ty(lt, rt),
(ExprKind::Unary(l_op, le), ExprKind::Unary(r_op, re)) => l_op == r_op && self.eq_expr(le, re),
(ExprKind::Yield(le, _), ExprKind::Yield(re, _)) => return self.eq_expr(le, re),
(
// Else branches for branches above, grouped as per `match_same_arms`.
| &ExprKind::AddrOf(..)
| &ExprKind::Array(..)
| &ExprKind::Assign(..)
| &ExprKind::AssignOp(..)
| &ExprKind::Binary(..)
| &ExprKind::Become(..)
| &ExprKind::Block(..)
| &ExprKind::Break(..)
| &ExprKind::Call(..)
| &ExprKind::Cast(..)
| &ExprKind::ConstBlock(..)
| &ExprKind::Continue(..)
| &ExprKind::DropTemps(..)
| &ExprKind::Field(..)
| &ExprKind::Index(..)
| &ExprKind::If(..)
| &ExprKind::Let(..)
| &ExprKind::Lit(..)
| &ExprKind::Loop(..)
| &ExprKind::Match(..)
| &ExprKind::MethodCall(..)
| &ExprKind::OffsetOf(..)
| &ExprKind::Path(..)
| &ExprKind::Repeat(..)
| &ExprKind::Ret(..)
| &ExprKind::Struct(..)
| &ExprKind::Tup(..)
| &ExprKind::Use(..)
| &ExprKind::Type(..)
| &ExprKind::Unary(..)
| &ExprKind::Yield(..)
| &ExprKind::UnsafeBinderCast(..)
| ExprKind::AddrOf(..)
| ExprKind::Array(..)
| ExprKind::Assign(..)
| ExprKind::AssignOp(..)
| ExprKind::Binary(..)
| ExprKind::Become(..)
| ExprKind::Block(..)
| ExprKind::Break(..)
| ExprKind::Call(..)
| ExprKind::Cast(..)
| ExprKind::ConstBlock(..)
| ExprKind::Continue(..)
| ExprKind::DropTemps(..)
| ExprKind::Field(..)
| ExprKind::Index(..)
| ExprKind::If(..)
| ExprKind::Let(..)
| ExprKind::Lit(..)
| ExprKind::Loop(..)
| ExprKind::Match(..)
| ExprKind::MethodCall(..)
| ExprKind::OffsetOf(..)
| ExprKind::Path(..)
| ExprKind::Repeat(..)
| ExprKind::Ret(..)
| ExprKind::Struct(..)
| ExprKind::Tup(..)
| ExprKind::Use(..)
| ExprKind::Type(..)
| ExprKind::Unary(..)
| ExprKind::Yield(..)
| ExprKind::UnsafeBinderCast(..)
// --- Special cases that do not have a positive branch.
// `Err` represents an invalid expression, so let's never assume that
// an invalid expressions is equal to anything.
| &ExprKind::Err(..)
| ExprKind::Err(..)
// For the time being, we always consider that two closures are unequal.
// This behavior may change in the future.
| &ExprKind::Closure(..)
| ExprKind::Closure(..)
// For the time being, we always consider that two instances of InlineAsm are different.
// This behavior may change in the future.
| &ExprKind::InlineAsm(_)
| ExprKind::InlineAsm(_)
, _
) => false,
};
@ -494,11 +494,11 @@ impl HirEqInterExpr<'_, '_, '_> {
fn eq_pat_expr(&mut self, left: &PatExpr<'_>, right: &PatExpr<'_>) -> bool {
match (&left.kind, &right.kind) {
(
&PatExprKind::Lit {
PatExprKind::Lit {
lit: left,
negated: left_neg,
},
&PatExprKind::Lit {
PatExprKind::Lit {
lit: right,
negated: right_neg,
},
@ -512,47 +512,47 @@ impl HirEqInterExpr<'_, '_, '_> {
/// Checks whether two patterns are the same.
fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
match (&left.kind, &right.kind) {
(&PatKind::Box(l), &PatKind::Box(r)) => self.eq_pat(l, r),
(&PatKind::Struct(ref lp, la, ..), &PatKind::Struct(ref rp, ra, ..)) => {
(PatKind::Box(l), PatKind::Box(r)) => self.eq_pat(l, r),
(PatKind::Struct(lp, la, ..), PatKind::Struct(rp, ra, ..)) => {
self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat_field(l, r))
},
(&PatKind::TupleStruct(ref lp, la, ls), &PatKind::TupleStruct(ref rp, ra, rs)) => {
(PatKind::TupleStruct(lp, la, ls), PatKind::TupleStruct(rp, ra, rs)) => {
self.eq_qpath(lp, rp) && over(la, ra, |l, r| self.eq_pat(l, r)) && ls == rs
},
(&PatKind::Binding(lb, li, _, ref lp), &PatKind::Binding(rb, ri, _, ref rp)) => {
(PatKind::Binding(lb, li, _, lp), PatKind::Binding(rb, ri, _, rp)) => {
let eq = lb == rb && both(lp.as_ref(), rp.as_ref(), |l, r| self.eq_pat(l, r));
if eq {
self.locals.insert(li, ri);
self.locals.insert(*li, *ri);
}
eq
},
(&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r),
(&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
(&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
(PatKind::Expr(l), PatKind::Expr(r)) => self.eq_pat_expr(l, r),
(PatKind::Tuple(l, ls), PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
(PatKind::Range(ls, le, li), PatKind::Range(rs, re, ri)) => {
both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_expr(a, b))
&& both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_expr(a, b))
&& (li == ri)
},
(&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
(&PatKind::Slice(ls, ref li, le), &PatKind::Slice(rs, ref ri, re)) => {
(PatKind::Ref(le, lm), PatKind::Ref(re, rm)) => lm == rm && self.eq_pat(le, re),
(PatKind::Slice(ls, li, le), PatKind::Slice(rs, ri, re)) => {
over(ls, rs, |l, r| self.eq_pat(l, r))
&& over(le, re, |l, r| self.eq_pat(l, r))
&& both(li.as_ref(), ri.as_ref(), |l, r| self.eq_pat(l, r))
},
(&PatKind::Wild, &PatKind::Wild) => true,
(PatKind::Wild, PatKind::Wild) => true,
_ => false,
}
}
fn eq_qpath(&mut self, left: &QPath<'_>, right: &QPath<'_>) -> bool {
match (left, right) {
(&QPath::Resolved(ref lty, lpath), &QPath::Resolved(ref rty, rpath)) => {
(QPath::Resolved(lty, lpath), QPath::Resolved(rty, rpath)) => {
both(lty.as_ref(), rty.as_ref(), |l, r| self.eq_ty(l, r)) && self.eq_path(lpath, rpath)
},
(&QPath::TypeRelative(lty, lseg), &QPath::TypeRelative(rty, rseg)) => {
(QPath::TypeRelative(lty, lseg), QPath::TypeRelative(rty, rseg)) => {
self.eq_ty(lty, rty) && self.eq_path_segment(lseg, rseg)
},
(&QPath::LangItem(llang_item, ..), &QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item,
(QPath::LangItem(llang_item, ..), QPath::LangItem(rlang_item, ..)) => llang_item == rlang_item,
_ => false,
}
}
@ -611,15 +611,15 @@ impl HirEqInterExpr<'_, '_, '_> {
pub fn eq_ty(&mut self, left: &Ty<'_>, right: &Ty<'_>) -> bool {
match (&left.kind, &right.kind) {
(&TyKind::Slice(l_vec), &TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
(&TyKind::Array(lt, ll), &TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl),
(TyKind::Slice(l_vec), TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec),
(TyKind::Array(lt, ll), TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl),
(TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty),
(TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => {
l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty)
},
(TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r),
(&TyKind::Tup(l), &TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
(&TyKind::Infer(()), &TyKind::Infer(())) => true,
(TyKind::Tup(l), TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)),
(TyKind::Infer(()), TyKind::Infer(())) => true,
_ => false,
}
}
@ -853,9 +853,9 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
std::mem::discriminant(&e.kind).hash(&mut self.s);
match e.kind {
match &e.kind {
ExprKind::AddrOf(kind, m, e) => {
std::mem::discriminant(&kind).hash(&mut self.s);
std::mem::discriminant(kind).hash(&mut self.s);
m.hash(&mut self.s);
self.hash_expr(e);
},
@ -871,7 +871,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(l);
self.hash_expr(r);
},
ExprKind::AssignOp(ref o, l, r) => {
ExprKind::AssignOp(o, l, r) => {
std::mem::discriminant(&o.node).hash(&mut self.s);
self.hash_expr(l);
self.hash_expr(r);
@ -887,11 +887,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(l);
self.hash_expr(r);
},
ExprKind::Break(i, ref j) => {
ExprKind::Break(i, j) => {
if let Some(i) = i.label {
self.hash_name(i.ident.name);
}
if let Some(j) = *j {
if let Some(j) = j {
self.hash_expr(j);
}
},
@ -903,20 +903,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(e);
self.hash_ty(ty);
},
ExprKind::Closure(&Closure {
ExprKind::Closure(Closure {
capture_clause, body, ..
}) => {
std::mem::discriminant(&capture_clause).hash(&mut self.s);
std::mem::discriminant(capture_clause).hash(&mut self.s);
// closures inherit TypeckResults
self.hash_expr(self.cx.tcx.hir_body(body).value);
self.hash_expr(self.cx.tcx.hir_body(*body).value);
},
ExprKind::ConstBlock(ref l_id) => {
ExprKind::ConstBlock(l_id) => {
self.hash_body(l_id.body);
},
ExprKind::DropTemps(e) | ExprKind::Yield(e, _) => {
self.hash_expr(e);
},
ExprKind::Field(e, ref f) => {
ExprKind::Field(e, f) => {
self.hash_expr(e);
self.hash_name(f.name);
},
@ -991,23 +991,23 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
ExprKind::Lit(l) => {
l.node.hash(&mut self.s);
},
ExprKind::Loop(b, ref i, ..) => {
ExprKind::Loop(b, i, ..) => {
self.hash_block(b);
if let Some(i) = *i {
if let Some(i) = i {
self.hash_name(i.ident.name);
}
},
ExprKind::If(cond, then, ref else_opt) => {
ExprKind::If(cond, then, else_opt) => {
self.hash_expr(cond);
self.hash_expr(then);
if let Some(e) = *else_opt {
if let Some(e) = else_opt {
self.hash_expr(e);
}
},
ExprKind::Match(e, arms, ref s) => {
ExprKind::Match(e, arms, s) => {
self.hash_expr(e);
for arm in arms {
for arm in *arms {
self.hash_pat(arm.pat);
if let Some(e) = arm.guard {
self.hash_expr(e);
@ -1017,38 +1017,38 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
s.hash(&mut self.s);
},
ExprKind::MethodCall(path, receiver, args, ref _fn_span) => {
ExprKind::MethodCall(path, receiver, args, _fn_span) => {
self.hash_name(path.ident.name);
self.hash_expr(receiver);
self.hash_exprs(args);
},
ExprKind::OffsetOf(container, fields) => {
self.hash_ty(container);
for field in fields {
for field in *fields {
self.hash_name(field.name);
}
},
ExprKind::Path(ref qpath) => {
ExprKind::Path(qpath) => {
self.hash_qpath(qpath);
},
ExprKind::Repeat(e, len) => {
self.hash_expr(e);
self.hash_const_arg(len);
},
ExprKind::Ret(ref e) => {
if let Some(e) = *e {
ExprKind::Ret(e) => {
if let Some(e) = e {
self.hash_expr(e);
}
},
ExprKind::Struct(path, fields, ref expr) => {
ExprKind::Struct(path, fields, expr) => {
self.hash_qpath(path);
for f in fields {
for f in *fields {
self.hash_name(f.ident.name);
self.hash_expr(f.expr);
}
if let StructTailExpr::Base(e) = *expr {
if let StructTailExpr::Base(e) = expr {
self.hash_expr(e);
}
},
@ -1059,11 +1059,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_expr(expr);
},
ExprKind::Unary(lop, le) => {
std::mem::discriminant(&lop).hash(&mut self.s);
std::mem::discriminant(lop).hash(&mut self.s);
self.hash_expr(le);
},
ExprKind::UnsafeBinderCast(kind, expr, ty) => {
std::mem::discriminant(&kind).hash(&mut self.s);
std::mem::discriminant(kind).hash(&mut self.s);
self.hash_expr(expr);
if let Some(ty) = ty {
self.hash_ty(ty);
@ -1084,7 +1084,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
}
pub fn hash_qpath(&mut self, p: &QPath<'_>) {
match *p {
match p {
QPath::Resolved(_, path) => {
self.hash_path(path);
},
@ -1092,7 +1092,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_name(path.ident.name);
},
QPath::LangItem(lang_item, ..) => {
std::mem::discriminant(&lang_item).hash(&mut self.s);
std::mem::discriminant(lang_item).hash(&mut self.s);
},
}
// self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
@ -1123,10 +1123,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
pub fn hash_pat(&mut self, pat: &Pat<'_>) {
std::mem::discriminant(&pat.kind).hash(&mut self.s);
match pat.kind {
match &pat.kind {
PatKind::Binding(BindingMode(by_ref, mutability), _, _, pat) => {
std::mem::discriminant(&by_ref).hash(&mut self.s);
std::mem::discriminant(&mutability).hash(&mut self.s);
std::mem::discriminant(by_ref).hash(&mut self.s);
std::mem::discriminant(mutability).hash(&mut self.s);
if let Some(pat) = pat {
self.hash_pat(pat);
}
@ -1134,7 +1134,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
PatKind::Expr(expr) => self.hash_pat_expr(expr),
PatKind::Or(pats) => {
for pat in pats {
for pat in *pats {
self.hash_pat(pat);
}
},
@ -1145,44 +1145,44 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
if let Some(e) = e {
self.hash_pat_expr(e);
}
std::mem::discriminant(&i).hash(&mut self.s);
std::mem::discriminant(i).hash(&mut self.s);
},
PatKind::Ref(pat, mu) => {
self.hash_pat(pat);
std::mem::discriminant(&mu).hash(&mut self.s);
std::mem::discriminant(mu).hash(&mut self.s);
},
PatKind::Guard(pat, guard) => {
self.hash_pat(pat);
self.hash_expr(guard);
},
PatKind::Slice(l, m, r) => {
for pat in l {
for pat in *l {
self.hash_pat(pat);
}
if let Some(pat) = m {
self.hash_pat(pat);
}
for pat in r {
for pat in *r {
self.hash_pat(pat);
}
},
PatKind::Struct(ref qpath, fields, e) => {
PatKind::Struct(qpath, fields, e) => {
self.hash_qpath(qpath);
for f in fields {
for f in *fields {
self.hash_name(f.ident.name);
self.hash_pat(f.pat);
}
e.hash(&mut self.s);
},
PatKind::Tuple(pats, e) => {
for pat in pats {
for pat in *pats {
self.hash_pat(pat);
}
e.hash(&mut self.s);
},
PatKind::TupleStruct(ref qpath, pats, e) => {
PatKind::TupleStruct(qpath, pats, e) => {
self.hash_qpath(qpath);
for pat in pats {
for pat in *pats {
self.hash_pat(pat);
}
e.hash(&mut self.s);
@ -1260,7 +1260,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
TyKind::Slice(ty) => {
self.hash_ty(ty);
},
&TyKind::Array(ty, len) => {
TyKind::Array(ty, len) => {
self.hash_ty(ty);
self.hash_const_arg(len);
},
@ -1333,11 +1333,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
fn hash_generic_args(&mut self, arg_list: &[GenericArg<'_>]) {
for arg in arg_list {
match *arg {
match arg {
GenericArg::Lifetime(l) => self.hash_lifetime(l),
GenericArg::Type(ty) => self.hash_ty(ty.as_unambig_ty()),
GenericArg::Const(ca) => self.hash_const_arg(ca.as_unambig_ct()),
GenericArg::Infer(ref inf) => self.hash_ty(&inf.to_ty()),
GenericArg::Infer(inf) => self.hash_ty(&inf.to_ty()),
}
}
}

View file

@ -1,7 +1,5 @@
#![feature(array_chunks)]
#![feature(box_patterns)]
#![feature(f128)]
#![feature(f16)]
#![feature(if_let_guard)]
#![feature(macro_metavar_expr_concat)]
#![feature(let_chains)]
@ -367,10 +365,10 @@ pub fn is_inherent_method_call(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// Checks if a method is defined in an impl of a diagnostic item
pub fn is_diag_item_method(cx: &LateContext<'_>, def_id: DefId, diag_item: Symbol) -> bool {
if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() {
return cx.tcx.is_diagnostic_item(diag_item, adt.did());
}
if let Some(impl_did) = cx.tcx.impl_of_method(def_id)
&& let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
{
return cx.tcx.is_diagnostic_item(diag_item, adt.did());
}
false
}
@ -457,10 +455,10 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
QPath::Resolved(_, path) => match_path(path, segments),
QPath::TypeRelative(ty, segment) => match ty.kind {
TyKind::Path(ref inner_path) => {
if let [prefix @ .., end] = segments {
if match_qpath(inner_path, prefix) {
return segment.ident.name.as_str() == *end;
}
if let [prefix @ .., end] = segments
&& match_qpath(inner_path, prefix)
{
return segment.ident.name.as_str() == *end;
}
false
},
@ -523,10 +521,10 @@ pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool {
/// If the expression is a path to a local, returns the canonical `HirId` of the local.
pub fn path_to_local(expr: &Expr<'_>) -> Option<HirId> {
if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
if let Res::Local(id) = path.res {
return Some(id);
}
if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind
&& let Res::Local(id) = path.res
{
return Some(id);
}
None
}
@ -893,16 +891,14 @@ fn is_default_equivalent_ctor(cx: &LateContext<'_>, def_id: DefId, path: &QPath<
sym::BinaryHeap,
];
if let QPath::TypeRelative(_, method) = path {
if method.ident.name == sym::new {
if let Some(impl_did) = cx.tcx.impl_of_method(def_id) {
if let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def() {
return std_types_symbols.iter().any(|&symbol| {
cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
});
}
}
}
if let QPath::TypeRelative(_, method) = path
&& method.ident.name == sym::new
&& let Some(impl_did) = cx.tcx.impl_of_method(def_id)
&& let Some(adt) = cx.tcx.type_of(impl_did).instantiate_identity().ty_adt_def()
{
return std_types_symbols.iter().any(|&symbol| {
cx.tcx.is_diagnostic_item(symbol, adt.did()) || Some(adt.did()) == cx.tcx.lang_items().string()
});
}
false
}
@ -1027,6 +1023,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
ExprKind::Call(from_func, [arg]) => is_default_equivalent_from(cx, from_func, arg),
ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
ExprKind::Block(Block { stmts: [], expr, .. }, _) => expr.is_some_and(|e| is_default_equivalent(cx, e)),
_ => false,
}
}
@ -1203,12 +1200,10 @@ pub fn capture_local_usage(cx: &LateContext<'_>, e: &Expr<'_>) -> CaptureKind {
.adjustments()
.get(child_id)
.map_or(&[][..], |x| &**x)
{
if let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) =
&& let rustc_ty::RawPtr(_, mutability) | rustc_ty::Ref(_, _, mutability) =
*adjust.last().map_or(target, |a| a.target).kind()
{
return CaptureKind::Ref(mutability);
}
{
return CaptureKind::Ref(mutability);
}
match parent {
@ -1736,10 +1731,10 @@ pub fn is_integer_const(cx: &LateContext<'_>, e: &Expr<'_>, value: u128) -> bool
/// Checks whether the given expression is a constant literal of the given value.
pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool {
// FIXME: use constant folding
if let ExprKind::Lit(spanned) = expr.kind {
if let LitKind::Int(v, _) = spanned.node {
return v == value;
}
if let ExprKind::Lit(spanned) = expr.kind
&& let LitKind::Int(v, _) = spanned.node
{
return v == value;
}
false
}
@ -1776,10 +1771,10 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
let data = span.ctxt().outer_expn_data();
let new_span = data.call_site;
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
if mac_name.as_str() == name {
return Some(new_span);
}
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind
&& mac_name.as_str() == name
{
return Some(new_span);
}
span = new_span;
@ -1805,10 +1800,10 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
let data = span.ctxt().outer_expn_data();
let new_span = data.call_site;
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind {
if mac_name.as_str() == name {
return Some(new_span);
}
if let ExpnKind::Macro(MacroKind::Bang, mac_name) = data.kind
&& mac_name.as_str() == name
{
return Some(new_span);
}
}
@ -1829,15 +1824,15 @@ pub fn nth_arg<'tcx>(cx: &LateContext<'tcx>, fn_def_id: OwnerId, nth: usize) ->
/// Checks if an expression is constructing a tuple-like enum variant or struct
pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
if let ExprKind::Call(fun, _) = expr.kind {
if let ExprKind::Path(ref qp) = fun.kind {
let res = cx.qpath_res(qp, fun.hir_id);
return match res {
Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
_ => false,
};
}
if let ExprKind::Call(fun, _) = expr.kind
&& let ExprKind::Path(ref qp) = fun.kind
{
let res = cx.qpath_res(qp, fun.hir_id);
return match res {
Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
_ => false,
};
}
false
}
@ -1910,10 +1905,10 @@ pub fn is_self(slf: &Param<'_>) -> bool {
}
pub fn is_self_ty(slf: &hir::Ty<'_>) -> bool {
if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind {
if let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res {
return true;
}
if let TyKind::Path(QPath::Resolved(None, path)) = slf.kind
&& let Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } = path.res
{
return true;
}
false
}
@ -2118,10 +2113,10 @@ pub fn if_sequence<'tcx>(mut expr: &'tcx Expr<'tcx>) -> (Vec<&'tcx Expr<'tcx>>,
}
// final `else {..}`
if !blocks.is_empty() {
if let ExprKind::Block(block, _) = expr.kind {
blocks.push(block);
}
if !blocks.is_empty()
&& let ExprKind::Block(block, _) = expr.kind
{
blocks.push(block);
}
(conds, blocks)
@ -2138,8 +2133,8 @@ pub fn is_async_fn(kind: FnKind<'_>) -> bool {
/// Peels away all the compiler generated code surrounding the body of an async function,
pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'tcx Expr<'tcx>> {
if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind {
if let ExprKind::Block(
if let ExprKind::Closure(&Closure { body, .. }) = body.value.kind
&& let ExprKind::Block(
Block {
stmts: [],
expr:
@ -2151,9 +2146,8 @@ pub fn get_async_fn_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Option<&'t
},
_,
) = tcx.hir_body(body).value.kind
{
return Some(expr);
}
{
return Some(expr);
}
None
}
@ -2627,10 +2621,10 @@ pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>
}
pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
if let Res::Def(_, def_id) = path.res {
return cx.tcx.has_attr(def_id, sym::cfg_trace) || cx.tcx.has_attr(def_id, sym::cfg_attr);
}
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
&& let Res::Def(_, def_id) = path.res
{
return cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr);
}
false
}
@ -2649,18 +2643,16 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl Fn(&[Sym
if matches!(tcx.def_kind(id.owner_id), DefKind::Const)
&& let item = tcx.hir_item(id)
&& let ItemKind::Const(ident, ty, _generics, _body) = item.kind
{
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind {
&& let TyKind::Path(QPath::Resolved(_, path)) = ty.kind
// We could also check for the type name `test::TestDescAndFn`
if let Res::Def(DefKind::Struct, _) = path.res {
let has_test_marker = tcx
.hir_attrs(item.hir_id())
.iter()
.any(|a| a.has_name(sym::rustc_test_marker));
if has_test_marker {
names.push(ident.name);
}
}
&& let Res::Def(DefKind::Struct, _) = path.res
{
let has_test_marker = tcx
.hir_attrs(item.hir_id())
.iter()
.any(|a| a.has_name(sym::rustc_test_marker));
if has_test_marker {
names.push(ident.name);
}
}
}
@ -2681,12 +2673,12 @@ pub fn is_in_test_function(tcx: TyCtxt<'_>, id: HirId) -> bool {
// Since you can nest functions we need to collect all until we leave
// function scope
.any(|(_id, node)| {
if let Node::Item(item) = node {
if let ItemKind::Fn { ident, .. } = item.kind {
// Note that we have sorted the item names in the visitor,
// so the binary_search gets the same as `contains`, but faster.
return names.binary_search(&ident.name).is_ok();
}
if let Node::Item(item) = node
&& let ItemKind::Fn { ident, .. } = item.kind
{
// Note that we have sorted the item names in the visitor,
// so the binary_search gets the same as `contains`, but faster.
return names.binary_search(&ident.name).is_ok();
}
false
})

View file

@ -76,7 +76,7 @@ impl<'tcx> Visitor<'tcx> for V<'_> {
}
if matches!(
ctx,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move)
PlaceContext::NonMutatingUse(NonMutatingUseContext::Move | NonMutatingUseContext::Inspect)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow)
) {
self.results[i].local_consume_or_mutate_locs.push(loc);

View file

@ -24,7 +24,7 @@ macro_rules! msrv_aliases {
msrv_aliases! {
1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT }
1,85,0 { UINT_FLOAT_MIDPOINT }
1,84,0 { CONST_OPTION_AS_SLICE }
1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR }
1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP }
1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP }
1,81,0 { LINT_REASONS_STABILIZATION, ERROR_IN_CORE, EXPLICIT_SELF_TYPE_ELISION }

View file

@ -30,6 +30,7 @@ pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"]
pub const CHAR_IS_ASCII: [&str; 5] = ["core", "char", "methods", "<impl char>", "is_ascii"];
pub const IO_ERROR_NEW: [&str; 5] = ["std", "io", "error", "Error", "new"];
pub const IO_ERRORKIND_OTHER: [&str; 5] = ["std", "io", "error", "ErrorKind", "Other"];
pub const ALIGN_OF: [&str; 3] = ["core", "mem", "align_of"];
// Paths in clippy itself
pub const MSRV_STACK: [&str; 3] = ["clippy_utils", "msrvs", "MsrvStack"];

View file

@ -142,7 +142,19 @@ pub trait SpanRangeExt: SpanRange {
map_range(cx.sess().source_map(), self.into_range(), f)
}
/// Extends the range to include all preceding whitespace characters.
/// Extends the range to include all preceding whitespace characters, unless there
/// are non-whitespace characters left on the same line after `self`.
///
/// This extra condition prevents a problem when removing the '}' in:
/// ```ignore
/// ( // There was an opening bracket after the parenthesis, which has been removed
/// // This is a comment
/// })
/// ```
/// Removing the whitespaces, including the linefeed, before the '}', would put the
/// closing parenthesis at the end of the `// This is a comment` line, which would
/// make it part of the comment as well. In this case, it is best to keep the span
/// on the '}' alone.
fn with_leading_whitespace(self, cx: &impl HasSession) -> Range<BytePos> {
with_leading_whitespace(cx.sess().source_map(), self.into_range())
}
@ -263,10 +275,15 @@ fn map_range(
}
fn with_leading_whitespace(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
map_range(sm, sp.clone(), |src, range| {
Some(src.get(..range.start)?.trim_end().len()..range.end)
map_range(sm, sp, |src, range| {
let non_blank_after = src.len() - src.get(range.end..)?.trim_start().len();
if src.get(range.end..non_blank_after)?.contains(['\r', '\n']) {
Some(src.get(..range.start)?.trim_end().len()..range.end)
} else {
Some(range)
}
})
.unwrap_or(sp)
.unwrap()
}
fn trim_start(sm: &SourceMap, sp: Range<BytePos>) -> Range<BytePos> {
@ -384,10 +401,10 @@ pub fn snippet_indent(sess: &impl HasSession, span: Span) -> Option<String> {
// For some reason these attributes don't have any expansion info on them, so
// we have to check it this way until there is a better way.
pub fn is_present_in_source(sess: &impl HasSession, span: Span) -> bool {
if let Some(snippet) = snippet_opt(sess, span) {
if snippet.is_empty() {
return false;
}
if let Some(snippet) = snippet_opt(sess, span)
&& snippet.is_empty()
{
return false;
}
true
}
@ -408,11 +425,11 @@ pub fn position_before_rarrow(s: &str) -> Option<usize> {
let mut rpos = rpos;
let chars: Vec<char> = s.chars().collect();
while rpos > 1 {
if let Some(c) = chars.get(rpos - 1) {
if c.is_whitespace() {
rpos -= 1;
continue;
}
if let Some(c) = chars.get(rpos - 1)
&& c.is_whitespace()
{
rpos -= 1;
continue;
}
break;
}

View file

@ -1,4 +1,4 @@
/// Dealing with sting indices can be hard, this struct ensures that both the
/// Dealing with string indices can be hard, this struct ensures that both the
/// character and byte index are provided for correct indexing.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct StrIndex {
@ -165,7 +165,7 @@ pub fn camel_case_split(s: &str) -> Vec<&str> {
offsets.windows(2).map(|w| &s[w[0]..w[1]]).collect()
}
/// Dealing with sting comparison can be complicated, this struct ensures that both the
/// Dealing with string comparison can be complicated, this struct ensures that both the
/// character and byte count are provided for correct indexing.
#[derive(Debug, Default, PartialEq, Eq)]
pub struct StrCount {

View file

@ -326,7 +326,7 @@ impl<'a> Sugg<'a> {
/// `self` argument of a method call
/// (e.g., to build `bar.foo()` or `(1 + 2).foo()`).
#[must_use]
pub fn maybe_par(self) -> Self {
pub fn maybe_paren(self) -> Self {
match self {
Sugg::NonParen(..) => self,
// `(x)` and `(x).y()` both don't need additional parens.
@ -494,7 +494,7 @@ impl<T: Display> Display for ParenHelper<T> {
/// operators have the same
/// precedence.
pub fn make_unop(op: &str, expr: Sugg<'_>) -> Sugg<'static> {
Sugg::MaybeParen(format!("{op}{}", expr.maybe_par()).into())
Sugg::MaybeParen(format!("{op}{}", expr.maybe_paren()).into())
}
/// Builds the string for `<lhs> <op> <rhs>` adding parenthesis when necessary.
@ -946,10 +946,9 @@ impl<'tcx> Delegate<'tcx> for DerefDelegate<'_, 'tcx> {
// some items do not need explicit deref, such as array accesses,
// so we mark them as already processed
// i.e.: don't suggest `*sub[1..4].len()` for `|sub| sub[1..4].len() == 3`
if let ty::Ref(_, inner, _) = cmt.place.ty_before_projection(i).kind() {
if matches!(inner.kind(), ty::Ref(_, innermost, _) if innermost.is_array()) {
projections_handled = true;
}
if let ty::Ref(_, inner, _) = cmt.place.ty_before_projection(i).kind()
&& matches!(inner.kind(), ty::Ref(_, innermost, _) if innermost.is_array()) {
projections_handled = true;
}
},
}
@ -1008,12 +1007,12 @@ mod test {
}
#[test]
fn binop_maybe_par() {
fn binop_maybe_paren() {
let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "1".into(), "1".into());
assert_eq!("(1 + 1)", sugg.maybe_par().to_string());
assert_eq!("(1 + 1)", sugg.maybe_paren().to_string());
let sugg = Sugg::BinOp(AssocOp::Binary(ast::BinOpKind::Add), "(1 + 1)".into(), "(1 + 1)".into());
assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_par().to_string());
assert_eq!("((1 + 1) + (1 + 1))", sugg.maybe_paren().to_string());
}
#[test]
fn not_op() {

View file

@ -128,10 +128,10 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'
// For `impl Trait<Assoc=U>`, it will register a predicate of `<T as Trait>::Assoc = U`,
// so we check the term for `U`.
ty::ClauseKind::Projection(projection_predicate) => {
if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack() {
if contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen) {
return true;
}
if let ty::TermKind::Ty(ty) = projection_predicate.term.unpack()
&& contains_ty_adt_constructor_opaque_inner(cx, ty, needle, seen)
{
return true;
}
},
_ => (),
@ -337,20 +337,20 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
ty::Tuple(args) => args.iter().any(|ty| is_must_use_ty(cx, ty)),
ty::Alias(ty::Opaque, AliasTy { def_id, .. }) => {
for (predicate, _) in cx.tcx.explicit_item_self_bounds(def_id).skip_binder() {
if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() {
if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) {
return true;
}
if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder()
&& cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use)
{
return true;
}
}
false
},
ty::Dynamic(binder, _, _) => {
for predicate in *binder {
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() {
if cx.tcx.has_attr(trait_ref.def_id, sym::must_use) {
return true;
}
if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder()
&& cx.tcx.has_attr(trait_ref.def_id, sym::must_use)
{
return true;
}
}
false
@ -1352,7 +1352,7 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n
}
}
/// Get's the type of a field by name.
/// Gets the type of a field by name.
pub fn get_field_by_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> Option<Ty<'tcx>> {
match *ty.kind() {
ty::Adt(def, args) if def.is_union() || def.is_struct() => def

View file

@ -126,10 +126,10 @@ impl<'tcx> Visitor<'tcx> for BindingUsageFinder<'_, 'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: HirId) -> Self::Result {
if let Res::Local(id) = path.res {
if self.binding_ids.contains(&id) {
return ControlFlow::Break(());
}
if let Res::Local(id) = path.res
&& self.binding_ids.contains(&id)
{
return ControlFlow::Break(());
}
ControlFlow::Continue(())

View file

@ -297,10 +297,10 @@ where
/// Checks if the given resolved path is used in the given body.
pub fn is_res_used(cx: &LateContext<'_>, res: Res, body: BodyId) -> bool {
for_each_expr(cx, cx.tcx.hir_body(body).value, |e| {
if let ExprKind::Path(p) = &e.kind {
if cx.qpath_res(p, e.hir_id) == res {
return ControlFlow::Break(());
}
if let ExprKind::Path(p) = &e.kind
&& cx.qpath_res(p, e.hir_id) == res
{
return ControlFlow::Break(());
}
ControlFlow::Continue(())
})