@@ -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) ]
116132mod 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