Skip to content

Commit a068ef8

Browse files
committed
Fix parentheses for missing_unsafe
I seem unable to use `Expr::needs_parens*` to complete it Example --- ```rust static mut STATIC_MUT: u8 = 0; fn foo() -> u8 { STATIC_MUT$0 * 2 } ``` **Before this PR**: ```rust static mut STATIC_MUT: u8 = 0; fn foo() -> u8 { unsafe { STATIC_MUT } * 2 } ``` **After this PR**: ```rust static mut STATIC_MUT: u8 = 0; fn foo() -> u8 { (unsafe { STATIC_MUT }) * 2 } ```
1 parent a56e577 commit a068ef8

File tree

1 file changed

+38
-1
lines changed

1 file changed

+38
-1
lines changed

crates/ide-diagnostics/src/handlers/missing_unsafe.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingUnsafe) -> Option<Vec<Ass
5050

5151
let node_to_add_unsafe_block = pick_best_node_to_add_unsafe_block(&expr)?;
5252

53-
let replacement = format!("unsafe {{ {} }}", node_to_add_unsafe_block.text());
53+
let mut replacement = format!("unsafe {{ {} }}", node_to_add_unsafe_block.text());
54+
if let Some(expr) = ast::Expr::cast(node_to_add_unsafe_block.clone())
55+
&& needs_parentheses(&expr)
56+
{
57+
replacement = format!("({replacement})");
58+
}
5459
let edit = TextEdit::replace(node_to_add_unsafe_block.text_range(), replacement);
5560
let source_change = SourceChange::from_text_edit(
5661
d.node.file_id.original_file(ctx.sema.db).file_id(ctx.sema.db),
@@ -112,6 +117,17 @@ fn pick_best_node_to_add_unsafe_block(unsafe_expr: &ast::Expr) -> Option<SyntaxN
112117
None
113118
}
114119

120+
fn needs_parentheses(expr: &ast::Expr) -> bool {
121+
let node = expr.syntax();
122+
node.ancestors()
123+
.skip(1)
124+
.take_while(|it| it.text_range().start() == node.text_range().start())
125+
.map_while(ast::Expr::cast)
126+
.last()
127+
.and_then(|it| Some(it.syntax().parent()?.kind()))
128+
.is_some_and(|kind| ast::ExprStmt::can_cast(kind) || ast::StmtList::can_cast(kind))
129+
}
130+
115131
#[cfg(test)]
116132
mod tests {
117133
use crate::tests::{check_diagnostics, check_fix, check_no_fix};
@@ -527,6 +543,27 @@ fn main() {
527543
)
528544
}
529545

546+
#[test]
547+
fn needs_parentheses_for_unambiguous() {
548+
check_fix(
549+
r#"
550+
//- minicore: copy
551+
static mut STATIC_MUT: u8 = 0;
552+
553+
fn foo() -> u8 {
554+
STATIC_MUT$0 * 2
555+
}
556+
"#,
557+
r#"
558+
static mut STATIC_MUT: u8 = 0;
559+
560+
fn foo() -> u8 {
561+
(unsafe { STATIC_MUT }) * 2
562+
}
563+
"#,
564+
)
565+
}
566+
530567
#[test]
531568
fn ref_to_unsafe_expr() {
532569
check_fix(

0 commit comments

Comments
 (0)