Skip to content

Rollup of 5 pull requests #98703

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 11 commits into from
4 changes: 1 addition & 3 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
@@ -192,9 +192,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
}

fn visit_pat(&mut self, pat: &'hir Pat<'hir>) {
let node =
if let PatKind::Binding(..) = pat.kind { Node::Binding(pat) } else { Node::Pat(pat) };
self.insert(pat.span, pat.hir_id, node);
self.insert(pat.span, pat.hir_id, Node::Pat(pat));

self.with_parent(pat.hir_id, |this| {
intravisit::walk_pat(this, pat);
Original file line number Diff line number Diff line change
@@ -362,7 +362,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {

let upvar_hir_id = captured_place.get_root_variable();

if let Some(Node::Binding(pat)) = self.infcx.tcx.hir().find(upvar_hir_id)
if let Some(Node::Pat(pat)) = self.infcx.tcx.hir().find(upvar_hir_id)
&& let hir::PatKind::Binding(
hir::BindingAnnotation::Unannotated,
_,
2 changes: 1 addition & 1 deletion compiler/rustc_const_eval/src/interpret/validity.rs
Original file line number Diff line number Diff line change
@@ -244,7 +244,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
// for a generator).
let var_hir_id = captured_place.get_root_variable();
let node = self.ecx.tcx.hir().get(var_hir_id);
if let hir::Node::Binding(pat) = node {
if let hir::Node::Pat(pat) = node {
if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
name = Some(ident.name);
}
2 changes: 1 addition & 1 deletion compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1447,7 +1447,7 @@ impl HandlerInner {
self.flags.treat_err_as_bug.map(|c| c.get()).unwrap_or(0),
) {
(1, 1) => panic!("aborting due to `-Z treat-err-as-bug=1`"),
(0, _) | (1, _) => {}
(0 | 1, _) => {}
(count, as_bug) => panic!(
"aborting after {} errors due to `-Z treat-err-as-bug={}`",
count, as_bug,
2 changes: 0 additions & 2 deletions compiler/rustc_hir/src/hir.rs
Original file line number Diff line number Diff line change
@@ -3326,7 +3326,6 @@ pub enum Node<'hir> {
Ty(&'hir Ty<'hir>),
TypeBinding(&'hir TypeBinding<'hir>),
TraitRef(&'hir TraitRef<'hir>),
Binding(&'hir Pat<'hir>),
Pat(&'hir Pat<'hir>),
Arm(&'hir Arm<'hir>),
Block(&'hir Block<'hir>),
@@ -3378,7 +3377,6 @@ impl<'hir> Node<'hir> {
| Node::Block(..)
| Node::Ctor(..)
| Node::Pat(..)
| Node::Binding(..)
| Node::Arm(..)
| Node::Local(..)
| Node::Crate(..)
2 changes: 1 addition & 1 deletion compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
@@ -87,7 +87,7 @@ impl<'a> State<'a> {
Node::Ty(a) => self.print_type(&a),
Node::TypeBinding(a) => self.print_type_binding(&a),
Node::TraitRef(a) => self.print_trait_ref(&a),
Node::Binding(a) | Node::Pat(a) => self.print_pat(&a),
Node::Pat(a) => self.print_pat(&a),
Node::Arm(a) => self.print_arm(&a),
Node::Infer(_) => self.word("_"),
Node::Block(a) => {
5 changes: 1 addition & 4 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -302,7 +302,6 @@ impl<'hir> Map<'hir> {
| Node::Infer(_)
| Node::TraitRef(_)
| Node::Pat(_)
| Node::Binding(_)
| Node::Local(_)
| Node::Param(_)
| Node::Arm(_)
@@ -901,7 +900,7 @@ impl<'hir> Map<'hir> {
#[inline]
fn opt_ident(self, id: HirId) -> Option<Ident> {
match self.get(id) {
Node::Binding(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
Node::Pat(&Pat { kind: PatKind::Binding(_, _, ident, _), .. }) => Some(ident),
// A `Ctor` doesn't have an identifier itself, but its parent
// struct/variant does. Compare with `hir::Map::opt_span`.
Node::Ctor(..) => match self.find(self.get_parent_node(id))? {
@@ -969,7 +968,6 @@ impl<'hir> Map<'hir> {
Node::Ty(ty) => ty.span,
Node::TypeBinding(tb) => tb.span,
Node::TraitRef(tr) => tr.path.span,
Node::Binding(pat) => pat.span,
Node::Pat(pat) => pat.span,
Node::Arm(arm) => arm.span,
Node::Block(block) => block.span,
@@ -1203,7 +1201,6 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
Some(Node::Ty(_)) => node_str("type"),
Some(Node::TypeBinding(_)) => node_str("type binding"),
Some(Node::TraitRef(_)) => node_str("trait ref"),
Some(Node::Binding(_)) => node_str("local"),
Some(Node::Pat(_)) => node_str("pat"),
Some(Node::Param(_)) => node_str("param"),
Some(Node::Arm(_)) => node_str("arm"),
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/build/mod.rs
Original file line number Diff line number Diff line change
@@ -997,7 +997,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
continue;
};
let pat = match tcx.hir().get(arg.pat.hir_id) {
Node::Pat(pat) | Node::Binding(pat) => pat,
Node::Pat(pat) => pat,
node => bug!("pattern became {:?}", node),
};
let pattern = pat_from_hir(tcx, self.param_env, self.typeck_results, pat);
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/thir/cx/mod.rs
Original file line number Diff line number Diff line change
@@ -101,7 +101,7 @@ impl<'tcx> Cx<'tcx> {
#[tracing::instrument(level = "debug", skip(self))]
pub(crate) fn pattern_from_hir(&mut self, p: &hir::Pat<'_>) -> Pat<'tcx> {
let p = match self.tcx.hir().get(p.hir_id) {
Node::Pat(p) | Node::Binding(p) => p,
Node::Pat(p) => p,
node => bug!("pattern became {:?}", node),
};
pat_from_hir(self.tcx, self.param_env, self.typeck_results(), p)
6 changes: 3 additions & 3 deletions compiler/rustc_save_analysis/src/lib.rs
Original file line number Diff line number Diff line change
@@ -623,9 +623,9 @@ impl<'tcx> SaveContext<'tcx> {
}
},

Node::Binding(&hir::Pat {
kind: hir::PatKind::Binding(_, canonical_id, ..), ..
}) => Res::Local(canonical_id),
Node::Pat(&hir::Pat { kind: hir::PatKind::Binding(_, canonical_id, ..), .. }) => {
Res::Local(canonical_id)
}

_ => Res::Err,
}
2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/check/demand.rs
Original file line number Diff line number Diff line change
@@ -223,7 +223,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
None,
hir::Path { res: hir::def::Res::Local(hir_id), .. },
)) => {
if let Some(hir::Node::Binding(pat)) = self.tcx.hir().find(*hir_id) {
if let Some(hir::Node::Pat(pat)) = self.tcx.hir().find(*hir_id) {
let parent = self.tcx.hir().get_parent_node(pat.hir_id);
primary_span = pat.span;
secondary_span = pat.span;
Original file line number Diff line number Diff line change
@@ -251,7 +251,6 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> {
| hir::Node::Ty(..)
| hir::Node::TypeBinding(..)
| hir::Node::TraitRef(..)
| hir::Node::Binding(..)
| hir::Node::Pat(..)
| hir::Node::Arm(..)
| hir::Node::Local(..)
173 changes: 173 additions & 0 deletions library/core/src/sync/exclusive.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
//! Defines [`Exclusive`].
use core::fmt;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};

/// `Exclusive` provides only _mutable_ access, also referred to as _exclusive_
/// access to the underlying value. It provides no _immutable_, or _shared_
/// access to the underlying value.
///
/// While this may seem not very useful, it allows `Exclusive` to _unconditionally_
/// implement [`Sync`]. Indeed, the safety requirements of `Sync` state that for `Exclusive`
/// to be `Sync`, it must be sound to _share_ across threads, that is, it must be sound
/// for `&Exclusive` to cross thread boundaries. By design, a `&Exclusive` has no API
/// whatsoever, making it useless, thus harmless, thus memory safe.
///
/// Certain constructs like [`Future`]s can only be used with _exclusive_ access,
/// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the
/// rust compiler that something is `Sync` in practice.
///
/// ## Examples
/// Using a non-`Sync` future prevents the wrapping struct from being `Sync`
/// ```compile_fail
/// use core::cell::Cell;
///
/// async fn other() {}
/// fn assert_sync<T: Sync>(t: T) {}
/// struct State<F> {
/// future: F
/// }
///
/// assert_sync(State {
/// future: async {
/// let cell = Cell::new(1);
/// let cell_ref = &cell;
/// other().await;
/// let value = cell_ref.get();
/// }
/// });
/// ```
///
/// `Exclusive` ensures the struct is `Sync` without stripping the future of its
/// functionality.
/// ```
/// #![feature(exclusive_wrapper)]
/// use core::cell::Cell;
/// use core::sync::Exclusive;
///
/// async fn other() {}
/// fn assert_sync<T: Sync>(t: T) {}
/// struct State<F> {
/// future: Exclusive<F>
/// }
///
/// assert_sync(State {
/// future: Exclusive::new(async {
/// let cell = Cell::new(1);
/// let cell_ref = &cell;
/// other().await;
/// let value = cell_ref.get();
/// })
/// });
/// ```
///
/// ## Parallels with a mutex
/// In some sense, `Exclusive` can be thought of as a _compile-time_ version of
/// a mutex, as the borrow-checker guarantees that only one `&mut` can exist
/// for any value. This is a parallel with the fact that
/// `&` and `&mut` references together can be thought of as a _compile-time_
/// version of a read-write lock.
///
///
/// [`Sync`]: core::marker::Sync
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[doc(alias = "SyncWrapper")]
#[doc(alias = "SyncCell")]
#[doc(alias = "Unique")]
// `Exclusive` can't have `PartialOrd`, `Clone`, etc. impls as they would
// use `&` access to the inner value, violating the `Sync` impl's safety
// requirements.
#[derive(Default)]
#[repr(transparent)]
pub struct Exclusive<T: ?Sized> {
inner: T,
}

// See `Exclusive`'s docs for justification.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
unsafe impl<T: ?Sized> Sync for Exclusive<T> {}

#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T: ?Sized> fmt::Debug for Exclusive<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
f.debug_struct("Exclusive").finish_non_exhaustive()
}
}

impl<T: Sized> Exclusive<T> {
/// Wrap a value in an `Exclusive`
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn new(t: T) -> Self {
Self { inner: t }
}

/// Unwrap the value contained in the `Exclusive`
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn into_inner(self) -> T {
self.inner
}
}

impl<T: ?Sized> Exclusive<T> {
/// Get exclusive access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn get_mut(&mut self) -> &mut T {
&mut self.inner
}

/// Get pinned exclusive access to the underlying value.
///
/// `Exclusive` is considered to _structurally pin_ the underlying
/// value, which means _unpinned_ `Exclusive`s can produce _unpinned_
/// access to the underlying value, but _pinned_ `Exclusive`s only
/// produce _pinned_ access to the underlying value.
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
}

/// Build a _mutable_ references to an `Exclusive<T>` from
/// a _mutable_ reference to a `T`. This allows you to skip
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn from_mut(r: &'_ mut T) -> &'_ mut Exclusive<T> {
// SAFETY: repr is ≥ C, so refs have the same layout; and `Exclusive` properties are `&mut`-agnostic
unsafe { &mut *(r as *mut T as *mut Exclusive<T>) }
}

/// Build a _pinned mutable_ references to an `Exclusive<T>` from
/// a _pinned mutable_ reference to a `T`. This allows you to skip
/// building an `Exclusive` with [`Exclusive::new`].
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
#[must_use]
pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut Exclusive<T>> {
// SAFETY: `Exclusive` can only produce `&mut T` if itself is unpinned
// `Pin::map_unchecked_mut` is not const, so we do this conversion manually
unsafe { Pin::new_unchecked(Self::from_mut(r.get_unchecked_mut())) }
}
}

#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T> From<T> for Exclusive<T> {
fn from(t: T) -> Self {
Self::new(t)
}
}

#[unstable(feature = "exclusive_wrapper", issue = "98407")]
impl<T: Future + ?Sized> Future for Exclusive<T> {
type Output = T::Output;

fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.get_pin_mut().poll(cx)
}
}
3 changes: 3 additions & 0 deletions library/core/src/sync/mod.rs
Original file line number Diff line number Diff line change
@@ -3,3 +3,6 @@
#![stable(feature = "rust1", since = "1.0.0")]

pub mod atomic;
mod exclusive;
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
pub use exclusive::Exclusive;
1 change: 1 addition & 0 deletions library/std/src/lib.rs
Original file line number Diff line number Diff line change
@@ -270,6 +270,7 @@
#![feature(duration_checked_float)]
#![feature(duration_constants)]
#![feature(exact_size_is_empty)]
#![feature(exclusive_wrapper)]
#![feature(extend_one)]
#![feature(float_minimum_maximum)]
#![feature(hasher_prefixfree_extras)]
2 changes: 2 additions & 0 deletions library/std/src/sync/mod.rs
Original file line number Diff line number Diff line change
@@ -155,6 +155,8 @@
pub use alloc_crate::sync::{Arc, Weak};
#[stable(feature = "rust1", since = "1.0.0")]
pub use core::sync::atomic;
#[unstable(feature = "exclusive_wrapper", issue = "98407")]
pub use core::sync::Exclusive;

#[stable(feature = "rust1", since = "1.0.0")]
pub use self::barrier::{Barrier, BarrierWaitResult};
17 changes: 11 additions & 6 deletions library/std/src/thread/mod.rs
Original file line number Diff line number Diff line change
@@ -159,6 +159,7 @@ use crate::cell::UnsafeCell;
use crate::ffi::{CStr, CString};
use crate::fmt;
use crate::io;
use crate::marker::PhantomData;
use crate::mem;
use crate::num::NonZeroU64;
use crate::num::NonZeroUsize;
@@ -462,7 +463,7 @@ impl Builder {
unsafe fn spawn_unchecked_<'a, 'scope, F, T>(
self,
f: F,
scope_data: Option<&'scope scoped::ScopeData>,
scope_data: Option<Arc<scoped::ScopeData>>,
) -> io::Result<JoinInner<'scope, T>>
where
F: FnOnce() -> T,
@@ -479,8 +480,11 @@ impl Builder {
}));
let their_thread = my_thread.clone();

let my_packet: Arc<Packet<'scope, T>> =
Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None) });
let my_packet: Arc<Packet<'scope, T>> = Arc::new(Packet {
scope: scope_data,
result: UnsafeCell::new(None),
_marker: PhantomData,
});
let their_packet = my_packet.clone();

let output_capture = crate::io::set_output_capture(None);
@@ -507,7 +511,7 @@ impl Builder {
unsafe { *their_packet.result.get() = Some(try_result) };
};

if let Some(scope_data) = scope_data {
if let Some(scope_data) = &my_packet.scope {
scope_data.increment_num_running_threads();
}

@@ -1298,8 +1302,9 @@ pub type Result<T> = crate::result::Result<T, Box<dyn Any + Send + 'static>>;
// An Arc to the packet is stored into a `JoinInner` which in turns is placed
// in `JoinHandle`.
struct Packet<'scope, T> {
scope: Option<&'scope scoped::ScopeData>,
scope: Option<Arc<scoped::ScopeData>>,
result: UnsafeCell<Option<Result<T>>>,
_marker: PhantomData<Option<&'scope scoped::ScopeData>>,
}

// Due to the usage of `UnsafeCell` we need to manually implement Sync.
@@ -1330,7 +1335,7 @@ impl<'scope, T> Drop for Packet<'scope, T> {
rtabort!("thread result panicked on drop");
}
// Book-keeping so the scope knows when it's done.
if let Some(scope) = self.scope {
if let Some(scope) = &self.scope {
// Now that there will be no more user code running on this thread
// that can use 'scope, mark the thread as 'finished'.
// It's important we only do this after the `result` has been dropped,
10 changes: 6 additions & 4 deletions library/std/src/thread/scoped.rs
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ use crate::sync::Arc;
/// See [`scope`] for details.
#[stable(feature = "scoped_threads", since = "1.63.0")]
pub struct Scope<'scope, 'env: 'scope> {
data: ScopeData,
data: Arc<ScopeData>,
/// Invariance over 'scope, to make sure 'scope cannot shrink,
/// which is necessary for soundness.
///
@@ -130,12 +130,14 @@ pub fn scope<'env, F, T>(f: F) -> T
where
F: for<'scope> FnOnce(&'scope Scope<'scope, 'env>) -> T,
{
// We put the `ScopeData` into an `Arc` so that other threads can finish their
// `decrement_num_running_threads` even after this function returns.
let scope = Scope {
data: ScopeData {
data: Arc::new(ScopeData {
num_running_threads: AtomicUsize::new(0),
main_thread: current(),
a_thread_panicked: AtomicBool::new(false),
},
}),
env: PhantomData,
scope: PhantomData,
};
@@ -250,7 +252,7 @@ impl Builder {
F: FnOnce() -> T + Send + 'scope,
T: Send + 'scope,
{
Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(&scope.data)) }?))
Ok(ScopedJoinHandle(unsafe { self.spawn_unchecked_(f, Some(scope.data.clone())) }?))
}
}

25 changes: 25 additions & 0 deletions src/test/ui/type-alias-impl-trait/issue-72793.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// check-pass
// compile-flags: -Zmir-opt-level=3

#![feature(type_alias_impl_trait)]

trait T { type Item; }

type Alias<'a> = impl T<Item = &'a ()>;

struct S;
impl<'a> T for &'a S {
type Item = &'a ();
}

fn filter_positive<'a>() -> Alias<'a> {
&S
}

fn with_positive(fun: impl Fn(Alias<'_>)) {
fun(filter_positive());
}

fn main() {
with_positive(|_| ());
}
16 changes: 5 additions & 11 deletions src/tools/clippy/clippy_lints/src/escape.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::ty::contains_ty;
use rustc_hir::intravisit;
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node};
use rustc_hir::{self, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
use rustc_infer::infer::TyCtxtInferExt;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::mir::FakeReadCause;
@@ -131,7 +131,10 @@ impl<'tcx> LateLintPass<'tcx> for BoxedLocal {
// TODO: Replace with Map::is_argument(..) when it's fixed
fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool {
match map.find(id) {
Some(Node::Binding(_)) => (),
Some(Node::Pat(Pat {
kind: PatKind::Binding(..),
..
})) => (),
_ => return false,
}

@@ -143,15 +146,6 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> {
if cmt.place.projections.is_empty() {
if let PlaceBase::Local(lid) = cmt.place.base {
self.set.remove(&lid);
let map = &self.cx.tcx.hir();
if let Some(Node::Binding(_)) = map.find(cmt.hir_id) {
if self.set.contains(&lid) {
// let y = x where x is known
// remove x, insert y
self.set.insert(cmt.hir_id);
self.set.remove(&lid);
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/explicit_write.rs
Original file line number Diff line number Diff line change
@@ -125,7 +125,7 @@ fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>)
// Find id of the local that expr_end_of_block resolves to
if let ExprKind::Path(QPath::Resolved(None, expr_path)) = expr_end_of_block.kind;
if let Res::Local(expr_res) = expr_path.res;
if let Some(Node::Binding(res_pat)) = cx.tcx.hir().find(expr_res);
if let Some(Node::Pat(res_pat)) = cx.tcx.hir().find(expr_res);

// Find id of the local we found in the block
if let PatKind::Binding(BindingAnnotation::Unannotated, local_hir_id, _ident, None) = local.pat.kind;
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/loops/mut_range_bound.rs
Original file line number Diff line number Diff line change
@@ -43,7 +43,7 @@ fn mut_warn_with_span(cx: &LateContext<'_>, span: Option<Span>) {
fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId> {
if_chain! {
if let Some(hir_id) = path_to_local(bound);
if let Node::Binding(pat) = cx.tcx.hir().get(hir_id);
if let Node::Pat(pat) = cx.tcx.hir().get(hir_id);
if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind;
then {
return Some(hir_id);
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@ pub(super) fn check<'tcx>(
Res::Local(hir_id) => {
let node = cx.tcx.hir().get(hir_id);
if_chain! {
if let Node::Binding(pat) = node;
if let Node::Pat(pat) = node;
if let PatKind::Binding(bind_ann, ..) = pat.kind;
if !matches!(bind_ann, BindingAnnotation::RefMut | BindingAnnotation::Mutable);
let parent_node = cx.tcx.hir().get_parent_node(hir_id);
Original file line number Diff line number Diff line change
@@ -22,7 +22,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr
|diag| {
if_chain! {
if let Some(id) = path_to_local(recv);
if let Node::Binding(pat) = cx.tcx.hir().get(id);
if let Node::Pat(pat) = cx.tcx.hir().get(id);
if let PatKind::Binding(ann, _, _, _) = pat.kind;
if ann != BindingAnnotation::Mutable;
then {
2 changes: 1 addition & 1 deletion src/tools/clippy/clippy_utils/src/lib.rs
Original file line number Diff line number Diff line change
@@ -183,7 +183,7 @@ pub fn expr_or_init<'a, 'b, 'tcx: 'b>(cx: &LateContext<'tcx>, mut expr: &'a Expr
pub fn find_binding_init<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Option<&'tcx Expr<'tcx>> {
let hir = cx.tcx.hir();
if_chain! {
if let Some(Node::Binding(pat)) = hir.find(hir_id);
if let Some(Node::Pat(pat)) = hir.find(hir_id);
if matches!(pat.kind, PatKind::Binding(BindingAnnotation::Unannotated, ..));
let parent = hir.get_parent_node(hir_id);
if let Some(Node::Local(local)) = hir.find(parent);