Auto merge of #94376 - c410-f3r:more-let-chains, r=petrochenkov

Initiate the inner usage of `let_chains`

The intention here is create a strong and robust foundation for a possible future stabilization so please, do not let the lack of any external tool support prevent the merge of this PR. Besides, `let_chains` is useful by itself.

cc #53667
This commit is contained in:
bors 2022-02-26 14:23:27 +00:00
commit 6f681a8eb3
4 changed files with 87 additions and 100 deletions

View File

@ -3855,7 +3855,6 @@ dependencies = [
name = "rustc_lint" name = "rustc_lint"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"if_chain",
"rustc_ast", "rustc_ast",
"rustc_ast_pretty", "rustc_ast_pretty",
"rustc_attr", "rustc_attr",

View File

@ -4,7 +4,6 @@ version = "0.0.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
if_chain = "1.0"
tracing = "0.1" tracing = "0.1"
unicode-security = "0.0.5" unicode-security = "0.0.5"
rustc_middle = { path = "../rustc_middle" } rustc_middle = { path = "../rustc_middle" }

View File

@ -25,20 +25,21 @@
//! //!
//! This API is completely unstable and subject to change. //! This API is completely unstable and subject to change.
#![allow(rustc::potential_query_instability)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(array_windows)] #![feature(array_windows)]
#![feature(bool_to_option)] #![feature(bool_to_option)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]
#![feature(iter_order_by)] #![feature(iter_order_by)]
#![feature(let_chains)]
#![feature(let_else)] #![feature(let_else)]
#![feature(never_type)] #![feature(never_type)]
#![feature(nll)] #![feature(nll)]
#![feature(control_flow_enum)]
#![recursion_limit = "256"] #![recursion_limit = "256"]
#![allow(rustc::potential_query_instability)]
#[macro_use] #[macro_use]
extern crate rustc_middle; extern crate rustc_middle;

View File

@ -16,7 +16,6 @@
use rustc_target::abi::{Integer, TagEncoding, Variants}; use rustc_target::abi::{Integer, TagEncoding, Variants};
use rustc_target::spec::abi::Abi as SpecAbi; use rustc_target::spec::abi::Abi as SpecAbi;
use if_chain::if_chain;
use std::cmp; use std::cmp;
use std::iter; use std::iter;
use std::ops::ControlFlow; use std::ops::ControlFlow;
@ -1456,21 +1455,18 @@ fn inherent_atomic_method_call<'hir>(
sym::AtomicI64, sym::AtomicI64,
sym::AtomicI128, sym::AtomicI128,
]; ];
if_chain! { if let ExprKind::MethodCall(ref method_path, args, _) = &expr.kind
if let ExprKind::MethodCall(ref method_path, args, _) = &expr.kind; && recognized_names.contains(&method_path.ident.name)
if recognized_names.contains(&method_path.ident.name); && let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
if let Some(m_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id); && let Some(impl_did) = cx.tcx.impl_of_method(m_def_id)
if let Some(impl_did) = cx.tcx.impl_of_method(m_def_id); && let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def()
if let Some(adt) = cx.tcx.type_of(impl_did).ty_adt_def();
// skip extension traits, only lint functions from the standard library // skip extension traits, only lint functions from the standard library
if cx.tcx.trait_id_of_impl(impl_did).is_none(); && cx.tcx.trait_id_of_impl(impl_did).is_none()
&& let Some(parent) = cx.tcx.parent(adt.did)
if let Some(parent) = cx.tcx.parent(adt.did); && cx.tcx.is_diagnostic_item(sym::atomic_mod, parent)
if cx.tcx.is_diagnostic_item(sym::atomic_mod, parent); && ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did))
if ATOMIC_TYPES.contains(&cx.tcx.item_name(adt.did)); {
then { return Some((method_path.ident.name, args));
return Some((method_path.ident.name, args));
}
} }
None None
} }
@ -1499,111 +1495,103 @@ fn opt_ordering_defid(cx: &LateContext<'_>, ord_arg: &Expr<'_>) -> Option<DefId>
fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_atomic_load_store(cx: &LateContext<'_>, expr: &Expr<'_>) {
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::QPath; use rustc_hir::QPath;
if_chain! { if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store])
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::load, sym::store]); && let Some((ordering_arg, invalid_ordering)) = match method {
if let Some((ordering_arg, invalid_ordering)) = match method {
sym::load => Some((&args[1], sym::Release)), sym::load => Some((&args[1], sym::Release)),
sym::store => Some((&args[2], sym::Acquire)), sym::store => Some((&args[2], sym::Acquire)),
_ => None, _ => None,
};
if let ExprKind::Path(QPath::Resolved(_, path)) = ordering_arg.kind;
if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res;
if Self::matches_ordering(cx, ctor_id, &[invalid_ordering, sym::AcqRel]);
then {
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
if method == sym::load {
diag.build("atomic loads cannot have `Release` or `AcqRel` ordering")
.help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")
.emit()
} else {
debug_assert_eq!(method, sym::store);
diag.build("atomic stores cannot have `Acquire` or `AcqRel` ordering")
.help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")
.emit();
}
});
} }
&& let ExprKind::Path(QPath::Resolved(_, path)) = ordering_arg.kind
&& let Res::Def(DefKind::Ctor(..), ctor_id) = path.res
&& Self::matches_ordering(cx, ctor_id, &[invalid_ordering, sym::AcqRel])
{
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, |diag| {
if method == sym::load {
diag.build("atomic loads cannot have `Release` or `AcqRel` ordering")
.help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")
.emit()
} else {
debug_assert_eq!(method, sym::store);
diag.build("atomic stores cannot have `Acquire` or `AcqRel` ordering")
.help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")
.emit();
}
});
} }
} }
fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_memory_fence(cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! { if let ExprKind::Call(ref func, ref args) = expr.kind
if let ExprKind::Call(ref func, ref args) = expr.kind; && let ExprKind::Path(ref func_qpath) = func.kind
if let ExprKind::Path(ref func_qpath) = func.kind; && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id(); && matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
if matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence)); && let ExprKind::Path(ref ordering_qpath) = &args[0].kind
if let ExprKind::Path(ref ordering_qpath) = &args[0].kind; && let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id()
if let Some(ordering_def_id) = cx.qpath_res(ordering_qpath, args[0].hir_id).opt_def_id(); && Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed])
if Self::matches_ordering(cx, ordering_def_id, &[sym::Relaxed]); {
then { cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| {
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, |diag| { diag.build("memory fences cannot have `Relaxed` ordering")
diag.build("memory fences cannot have `Relaxed` ordering") .help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")
.help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`") .emit();
.emit(); });
});
}
} }
} }
fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) { fn check_atomic_compare_exchange(cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! { if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak])
if let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak]); && let Some((success_order_arg, failure_order_arg)) = match method {
if let Some((success_order_arg, failure_order_arg)) = match method {
sym::fetch_update => Some((&args[1], &args[2])), sym::fetch_update => Some((&args[1], &args[2])),
sym::compare_exchange | sym::compare_exchange_weak => Some((&args[3], &args[4])), sym::compare_exchange | sym::compare_exchange_weak => Some((&args[3], &args[4])),
_ => None, _ => None,
}; }
&& let Some(fail_ordering_def_id) = Self::opt_ordering_defid(cx, failure_order_arg)
{
// Helper type holding on to some checking and error reporting data. Has
// - (success ordering,
// - list of failure orderings forbidden by the success order,
// - suggestion message)
type OrdLintInfo = (Symbol, &'static [Symbol], &'static str);
const RELAXED: OrdLintInfo = (sym::Relaxed, &[sym::SeqCst, sym::Acquire], "ordering mode `Relaxed`");
const ACQUIRE: OrdLintInfo = (sym::Acquire, &[sym::SeqCst], "ordering modes `Acquire` or `Relaxed`");
const SEQ_CST: OrdLintInfo = (sym::SeqCst, &[], "ordering modes `Acquire`, `SeqCst` or `Relaxed`");
const RELEASE: OrdLintInfo = (sym::Release, RELAXED.1, RELAXED.2);
const ACQREL: OrdLintInfo = (sym::AcqRel, ACQUIRE.1, ACQUIRE.2);
const SEARCH: [OrdLintInfo; 5] = [RELAXED, ACQUIRE, SEQ_CST, RELEASE, ACQREL];
if let Some(fail_ordering_def_id) = Self::opt_ordering_defid(cx, failure_order_arg); let success_lint_info = Self::opt_ordering_defid(cx, success_order_arg)
then { .and_then(|success_ord_def_id| -> Option<OrdLintInfo> {
// Helper type holding on to some checking and error reporting data. Has SEARCH
// - (success ordering, .iter()
// - list of failure orderings forbidden by the success order, .copied()
// - suggestion message) .find(|(ordering, ..)| {
type OrdLintInfo = (Symbol, &'static [Symbol], &'static str); Self::matches_ordering(cx, success_ord_def_id, &[*ordering])
const RELAXED: OrdLintInfo = (sym::Relaxed, &[sym::SeqCst, sym::Acquire], "ordering mode `Relaxed`"); })
const ACQUIRE: OrdLintInfo = (sym::Acquire, &[sym::SeqCst], "ordering modes `Acquire` or `Relaxed`"); });
const SEQ_CST: OrdLintInfo = (sym::SeqCst, &[], "ordering modes `Acquire`, `SeqCst` or `Relaxed`"); if Self::matches_ordering(cx, fail_ordering_def_id, &[sym::Release, sym::AcqRel]) {
const RELEASE: OrdLintInfo = (sym::Release, RELAXED.1, RELAXED.2); // If we don't know the success order is, use what we'd suggest
const ACQREL: OrdLintInfo = (sym::AcqRel, ACQUIRE.1, ACQUIRE.2); // if it were maximally permissive.
const SEARCH: [OrdLintInfo; 5] = [RELAXED, ACQUIRE, SEQ_CST, RELEASE, ACQREL]; let suggested = success_lint_info.unwrap_or(SEQ_CST).2;
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| {
let success_lint_info = Self::opt_ordering_defid(cx, success_order_arg) let msg = format!(
.and_then(|success_ord_def_id| -> Option<OrdLintInfo> { "{}'s failure ordering may not be `Release` or `AcqRel`",
SEARCH method,
.iter() );
.copied() diag.build(&msg)
.find(|(ordering, ..)| { .help(&format!("consider using {} instead", suggested))
Self::matches_ordering(cx, success_ord_def_id, &[*ordering]) .emit();
}) });
}); } else if let Some((success_ord, bad_ords_given_success, suggested)) = success_lint_info {
if Self::matches_ordering(cx, fail_ordering_def_id, &[sym::Release, sym::AcqRel]) { if Self::matches_ordering(cx, fail_ordering_def_id, bad_ords_given_success) {
// If we don't know the success order is, use what we'd suggest
// if it were maximally permissive.
let suggested = success_lint_info.unwrap_or(SEQ_CST).2;
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| { cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| {
let msg = format!( let msg = format!(
"{}'s failure ordering may not be `Release` or `AcqRel`", "{}'s failure ordering may not be stronger than the success ordering of `{}`",
method, method,
success_ord,
); );
diag.build(&msg) diag.build(&msg)
.help(&format!("consider using {} instead", suggested)) .help(&format!("consider using {} instead", suggested))
.emit(); .emit();
}); });
} else if let Some((success_ord, bad_ords_given_success, suggested)) = success_lint_info {
if Self::matches_ordering(cx, fail_ordering_def_id, bad_ords_given_success) {
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, failure_order_arg.span, |diag| {
let msg = format!(
"{}'s failure ordering may not be stronger than the success ordering of `{}`",
method,
success_ord,
);
diag.build(&msg)
.help(&format!("consider using {} instead", suggested))
.emit();
});
}
} }
} }
} }