@@ -199,7 +199,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
199199                return ; 
200200            } 
201201
202-             let  mut  compatible_variants = expected_adt
202+             // If the expression is of type () and it's the return expression of a block, 
203+             // we suggest adding a separate return expression instead. 
204+             // (To avoid things like suggesting `Ok(while .. { .. })`.) 
205+             if  expr_ty. is_unit ( )  { 
206+                 if  let  Some ( hir:: Node :: Block ( & hir:: Block  { 
207+                     span :  block_span,  expr :  Some ( e) ,  ..
208+                 } ) )  = self . tcx . hir ( ) . find ( self . tcx . hir ( ) . get_parent_node ( expr. hir_id ) ) 
209+                 { 
210+                     if  e. hir_id  == expr. hir_id  { 
211+                         if  let  Some ( span)  = expr. span . find_ancestor_inside ( block_span)  { 
212+                             let  return_suggestions =
213+                                 if  self . tcx . is_diagnostic_item ( sym:: Result ,  expected_adt. did )  { 
214+                                     vec ! [ "Ok(())" . to_string( ) ] 
215+                                 }  else  if  self . tcx . is_diagnostic_item ( sym:: Option ,  expected_adt. did ) 
216+                                 { 
217+                                     vec ! [ "None" . to_string( ) ,  "Some(())" . to_string( ) ] 
218+                                 }  else  { 
219+                                     return ; 
220+                                 } ; 
221+                             if  let  Some ( indent)  =
222+                                 self . tcx . sess . source_map ( ) . indentation_before ( span. shrink_to_lo ( ) ) 
223+                             { 
224+                                 // Add a semicolon, except after `}`. 
225+                                 let  semicolon =
226+                                     match  self . tcx . sess . source_map ( ) . span_to_snippet ( span)  { 
227+                                         Ok ( s)  if  s. ends_with ( '}' )  => "" , 
228+                                         _ => ";" , 
229+                                     } ; 
230+                                 err. span_suggestions ( 
231+                                     span. shrink_to_hi ( ) , 
232+                                     "try adding an expression at the end of the block" , 
233+                                     return_suggestions
234+                                         . into_iter ( ) 
235+                                         . map ( |r| format ! ( "{}\n {}{}" ,  semicolon,  indent,  r) ) , 
236+                                     Applicability :: MaybeIncorrect , 
237+                                 ) ; 
238+                             } 
239+                             return ; 
240+                         } 
241+                     } 
242+                 } 
243+             } 
244+ 
245+             let  compatible_variants:  Vec < String >  = expected_adt
203246                . variants 
204247                . iter ( ) 
205248                . filter ( |variant| variant. fields . len ( )  == 1 ) 
@@ -220,19 +263,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
220263                        None 
221264                    } 
222265                } ) 
223-                 . peekable ( ) ; 
266+                 . collect ( ) ; 
224267
225-             if  compatible_variants. peek ( ) . is_some ( )  { 
226-                 if  let  Ok ( expr_text)  = self . tcx . sess . source_map ( ) . span_to_snippet ( expr. span )  { 
227-                     let  suggestions = compatible_variants. map ( |v| format ! ( "{}({})" ,  v,  expr_text) ) ; 
228-                     let  msg = "try using a variant of the expected enum" ; 
229-                     err. span_suggestions ( 
230-                         expr. span , 
231-                         msg, 
232-                         suggestions, 
233-                         Applicability :: MaybeIncorrect , 
234-                     ) ; 
235-                 } 
268+             if  let  [ variant]  = & compatible_variants[ ..]  { 
269+                 // Just a single matching variant. 
270+                 err. multipart_suggestion ( 
271+                     & format ! ( "try wrapping the expression in `{}`" ,  variant) , 
272+                     vec ! [ 
273+                         ( expr. span. shrink_to_lo( ) ,  format!( "{}(" ,  variant) ) , 
274+                         ( expr. span. shrink_to_hi( ) ,  ")" . to_string( ) ) , 
275+                     ] , 
276+                     Applicability :: MaybeIncorrect , 
277+                 ) ; 
278+             }  else  if  compatible_variants. len ( )  > 1  { 
279+                 // More than one matching variant. 
280+                 err. multipart_suggestions ( 
281+                     & format ! ( 
282+                         "try wrapping the expression in a variant of `{}`" , 
283+                         self . tcx. def_path_str( expected_adt. did) 
284+                     ) , 
285+                     compatible_variants. into_iter ( ) . map ( |variant| { 
286+                         vec ! [ 
287+                             ( expr. span. shrink_to_lo( ) ,  format!( "{}(" ,  variant) ) , 
288+                             ( expr. span. shrink_to_hi( ) ,  ")" . to_string( ) ) , 
289+                         ] 
290+                     } ) , 
291+                     Applicability :: MaybeIncorrect , 
292+                 ) ; 
236293            } 
237294        } 
238295    } 
0 commit comments