From e92614818879f24994c3890dcb958b8baa2d0678 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 22 May 2023 04:07:17 -0400 Subject: [PATCH] Fix unsafe blocks --- clippy_utils/src/source.rs | 14 +++-- tests/ui/single_match.stderr | 45 +++++++++++++- tests/ui/single_match_else.stderr | 99 ++++++++++++++++++++++++++++++- 3 files changed, 152 insertions(+), 6 deletions(-) diff --git a/clippy_utils/src/source.rs b/clippy_utils/src/source.rs index 0f60290644a..61e249b995e 100644 --- a/clippy_utils/src/source.rs +++ b/clippy_utils/src/source.rs @@ -4,7 +4,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{BlockCheckMode, Expr, ExprKind, UnsafeSource}; use rustc_lint::{LateContext, LintContext}; use rustc_session::Session; use rustc_span::source_map::{original_sp, SourceMap}; @@ -71,11 +71,17 @@ pub fn expr_block( app: &mut Applicability, ) -> String { let (code, from_macro) = snippet_block_with_context(cx, expr.span, outer, default, indent_relative_to, app); - if from_macro { - format!("{{ {code} }}") - } else if let ExprKind::Block(_, _) = expr.kind { + if !from_macro && + let ExprKind::Block(block, _) = expr.kind && + // TODO: Is this enough UnsafeSource::UserProvided, or should CompilerGenerated be also included? + block.rules != BlockCheckMode::UnsafeBlock(UnsafeSource::UserProvided) + { format!("{code}") } else { + // FIXME: add extra indent for the unsafe blocks: + // original code: unsafe { ... } + // result code: { unsafe { ... } } + // desired code: {\n unsafe { ... }\n} format!("{{ {code} }}") } } diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 7cecc1b7395..810f153fe62 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -155,5 +155,48 @@ LL | | (..) => {}, LL | | } | |_____^ help: try this: `if let (.., Some(E::V), _) = (Some(42), Some(E::V), Some(42)) {}` -error: aborting due to 16 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:249:5 + | +LL | / match bar { +LL | | Some(v) => unsafe { +LL | | let r = &v as *const i32; +LL | | println!("{}", *r); +LL | | }, +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match.rs:257:5 + | +LL | / match bar { +LL | | Some(v) => { +LL | | // this comment prevents rustfmt from collapsing the block +LL | | unsafe { +... | +LL | | _ => {}, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { +LL + // this comment prevents rustfmt from collapsing the block +LL + unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } +LL + } + | + +error: aborting due to 18 previous errors diff --git a/tests/ui/single_match_else.stderr b/tests/ui/single_match_else.stderr index 62876a55dc6..6537156d515 100644 --- a/tests/ui/single_match_else.stderr +++ b/tests/ui/single_match_else.stderr @@ -100,5 +100,102 @@ LL + return; LL + } | -error: aborting due to 5 previous errors +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:120:5 + | +LL | / match bar { +LL | | Some(v) => unsafe { +LL | | let r = &v as *const i32; +LL | | println!("{}", *r); +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } else { +LL + println!("None1"); +LL + println!("None2"); +LL + } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:131:5 + | +LL | / match bar { +LL | | Some(v) => { +LL | | println!("Some"); +LL | | println!("{v}"); +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { +LL + println!("Some"); +LL + println!("{v}"); +LL + } else { unsafe { +LL + let v = 0; +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:143:5 + | +LL | / match bar { +LL | | Some(v) => unsafe { +LL | | let r = &v as *const i32; +LL | | println!("{}", *r); +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } else { unsafe { +LL + let v = 0; +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } } + | + +error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` + --> $DIR/single_match_else.rs:155:5 + | +LL | / match bar { +LL | | Some(v) => { +LL | | // this comment prevents rustfmt from collapsing the block +LL | | unsafe { +... | +LL | | }, +LL | | } + | |_____^ + | +help: try this + | +LL ~ if let Some(v) = bar { +LL + // this comment prevents rustfmt from collapsing the block +LL + unsafe { +LL + let r = &v as *const i32; +LL + println!("{}", *r); +LL + } +LL + } else { +LL + println!("None"); +LL + println!("None"); +LL + } + | + +error: aborting due to 9 previous errors