@@ -116,31 +116,35 @@ fn is_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
116116/// The expression inside a closure may or may not have surrounding braces and
117117/// semicolons, which causes problems when generating a suggestion. Given an
118118/// expression that evaluates to '()' or '!', recursively remove useless braces
119- /// and semi-colons until is suitable for including in the suggestion template
120- fn reduce_unit_expression ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > ) -> Option < Span > {
119+ /// and semi-colons until is suitable for including in the suggestion template.
120+ /// The `bool` is `true` when the resulting `span` needs to be enclosed in an
121+ /// `unsafe` block.
122+ fn reduce_unit_expression ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > ) -> Option < ( Span , bool ) > {
121123 if !is_unit_expression ( cx, expr) {
122124 return None ;
123125 }
124126
125127 match expr. kind {
126128 hir:: ExprKind :: Call ( _, _) | hir:: ExprKind :: MethodCall ( ..) => {
127129 // Calls can't be reduced any more
128- Some ( expr. span )
130+ Some ( ( expr. span , false ) )
129131 } ,
130132 hir:: ExprKind :: Block ( block, _) => {
133+ let is_unsafe = matches ! ( block. rules, hir:: BlockCheckMode :: UnsafeBlock ( _) ) ;
131134 match ( block. stmts , block. expr . as_ref ( ) ) {
132135 ( [ ] , Some ( inner_expr) ) => {
133136 // If block only contains an expression,
134137 // reduce `{ X }` to `X`
135138 reduce_unit_expression ( cx, inner_expr)
139+ . map ( |( span, inner_is_unsafe) | ( span, inner_is_unsafe || is_unsafe) )
136140 } ,
137141 ( [ inner_stmt] , None ) => {
138142 // If block only contains statements,
139143 // reduce `{ X; }` to `X` or `X;`
140144 match inner_stmt. kind {
141- hir:: StmtKind :: Let ( local) => Some ( local. span ) ,
142- hir:: StmtKind :: Expr ( e) => Some ( e. span ) ,
143- hir:: StmtKind :: Semi ( ..) => Some ( inner_stmt. span ) ,
145+ hir:: StmtKind :: Let ( local) => Some ( ( local. span , is_unsafe ) ) ,
146+ hir:: StmtKind :: Expr ( e) => Some ( ( e. span , is_unsafe ) ) ,
147+ hir:: StmtKind :: Semi ( ..) => Some ( ( inner_stmt. span , is_unsafe ) ) ,
144148 hir:: StmtKind :: Item ( ..) => None ,
145149 }
146150 } ,
@@ -228,10 +232,11 @@ fn lint_map_unit_fn(
228232 let msg = suggestion_msg ( "closure" , map_type) ;
229233
230234 span_lint_and_then ( cx, lint, expr. span , msg, |diag| {
231- if let Some ( reduced_expr_span) = reduce_unit_expression ( cx, closure_expr) {
235+ if let Some ( ( reduced_expr_span, is_unsafe ) ) = reduce_unit_expression ( cx, closure_expr) {
232236 let mut applicability = Applicability :: MachineApplicable ;
237+ let ( prefix_is_unsafe, suffix_is_unsafe) = if is_unsafe { ( "unsafe { " , " }" ) } else { ( "" , "" ) } ;
233238 let suggestion = format ! (
234- "if let {0}({1}) = {2} {{ {3 } }}" ,
239+ "if let {0}({1}) = {2} {{ {prefix_is_unsafe}{3}{suffix_is_unsafe } }}" ,
235240 variant,
236241 snippet_with_applicability( cx, binding. pat. span, "_" , & mut applicability) ,
237242 snippet_with_applicability( cx, var_arg. span, "_" , & mut applicability) ,
0 commit comments