- 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 {
- sym::fetch_update => Some((&args[1], &args[2])),
- sym::compare_exchange | sym::compare_exchange_weak => Some((&args[3], &args[4])),
- _ => 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];
-
- let success_lint_info = Self::opt_ordering_defid(cx, success_order_arg)
- .and_then(|success_ord_def_id| -> Option<OrdLintInfo> {
- SEARCH
- .iter()
- .copied()
- .find(|(ordering, ..)| {
- Self::matches_ordering(cx, success_ord_def_id, &[*ordering])
- })
- });
- if Self::matches_ordering(cx, fail_ordering_def_id, &[sym::Release, sym::AcqRel]) {
- // 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| {
- let msg = format!(
- "{}'s failure ordering may not be `Release` or `AcqRel`",
- method,
- );
- diag.build(&msg)
- .help(&format!("consider using {} instead", suggested))
- .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();
- });
- }
- }
+ let Some((method, args)) = Self::inherent_atomic_method_call(cx, expr, &[sym::fetch_update, sym::compare_exchange, sym::compare_exchange_weak])
+ else {return };
+
+ let (success_order_arg, fail_order_arg) = match method {
+ sym::fetch_update => (&args[1], &args[2]),
+ sym::compare_exchange | sym::compare_exchange_weak => (&args[3], &args[4]),
+ _ => return,
+ };
+
+ let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return };
+
+ if matches!(fail_ordering, sym::Release | sym::AcqRel) {
+ cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg.span, |diag| {
+ diag.build(fluent::lint::atomic_ordering_invalid)
+ .set_arg("method", method)
+ .span_label(fail_order_arg.span, fluent::lint::label)
+ .help(fluent::lint::help)
+ .emit();
+ });
+ }
+
+ let Some(success_ordering) = Self::match_ordering(cx, success_order_arg) else { return };
+
+ if matches!(
+ (success_ordering, fail_ordering),
+ (sym::Relaxed | sym::Release, sym::Acquire)
+ | (sym::Relaxed | sym::Release | sym::Acquire | sym::AcqRel, sym::SeqCst)
+ ) {
+ let success_suggestion =
+ if success_ordering == sym::Release && fail_ordering == sym::Acquire {
+ sym::AcqRel
+ } else {
+ fail_ordering
+ };
+ cx.struct_span_lint(INVALID_ATOMIC_ORDERING, success_order_arg.span, |diag| {
+ diag.build(fluent::lint::atomic_ordering_invalid_fail_success)
+ .set_arg("method", method)
+ .set_arg("fail_ordering", fail_ordering)
+ .set_arg("success_ordering", success_ordering)
+ .set_arg("success_suggestion", success_suggestion)
+ .span_label(fail_order_arg.span, fluent::lint::fail_label)
+ .span_label(success_order_arg.span, fluent::lint::success_label)
+ .span_suggestion_short(
+ success_order_arg.span,
+ fluent::lint::suggestion,
+ format!("std::sync::atomic::Ordering::{success_suggestion}"),
+ Applicability::MaybeIncorrect,
+ )
+ .emit();
+ });