@@ -6,7 +6,6 @@ use rustc_ast::{ast, token::Delimiter, visit};
66use rustc_span:: { BytePos , Ident , Pos , Span , symbol} ;
77use tracing:: debug;
88
9- use crate :: attr:: * ;
109use crate :: comment:: { CodeCharKind , CommentCodeSlices , contains_comment, rewrite_comment} ;
1110use crate :: config:: { BraceStyle , Config , MacroSelector , StyleEdition } ;
1211use crate :: coverage:: transform_missing_snippet;
@@ -25,8 +24,9 @@ use crate::spanned::Spanned;
2524use crate :: stmt:: Stmt ;
2625use crate :: utils:: {
2726 self , contains_skip, count_newlines, depr_skip_annotation, format_safety, inner_attributes,
28- last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr ,
27+ last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline,
2928} ;
29+ use crate :: { Edition , attr:: * } ;
3030use crate :: { ErrorKind , FormatReport , FormattingError } ;
3131
3232/// Creates a string slice corresponding to the specified span.
@@ -78,6 +78,7 @@ pub(crate) struct FmtVisitor<'a> {
7878 pub ( crate ) block_indent : Indent ,
7979 pub ( crate ) config : & ' a Config ,
8080 pub ( crate ) is_if_else_block : bool ,
81+ pub ( crate ) is_loop_block : bool ,
8182 pub ( crate ) snippet_provider : & ' a SnippetProvider ,
8283 pub ( crate ) line_number : usize ,
8384 /// List of 1-based line ranges which were annotated with skip
@@ -231,11 +232,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
231232
232233 self . walk_block_stmts ( b) ;
233234
234- if !b. stmts . is_empty ( ) {
235- if let Some ( expr) = stmt_expr ( & b. stmts [ b. stmts . len ( ) - 1 ] ) {
236- if utils:: semicolon_for_expr ( & self . get_context ( ) , expr) {
237- self . push_str ( ";" ) ;
238- }
235+ if let Some ( stmt) = b. stmts . last ( ) {
236+ if self . add_semi_on_last_block_stmt ( stmt) {
237+ self . push_str ( ";" ) ;
239238 }
240239 }
241240
@@ -802,6 +801,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
802801 block_indent : Indent :: empty ( ) ,
803802 config,
804803 is_if_else_block : false ,
804+ is_loop_block : false ,
805805 snippet_provider,
806806 line_number : 0 ,
807807 skipped_range : Rc :: new ( RefCell :: new ( vec ! [ ] ) ) ,
@@ -1019,6 +1019,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
10191019 inside_macro : Rc :: new ( Cell :: new ( false ) ) ,
10201020 use_block : Cell :: new ( false ) ,
10211021 is_if_else_block : Cell :: new ( false ) ,
1022+ is_loop_block : Cell :: new ( false ) ,
10221023 force_one_line_chain : Cell :: new ( false ) ,
10231024 snippet_provider : self . snippet_provider ,
10241025 macro_rewrite_failure : Cell :: new ( false ) ,
@@ -1028,4 +1029,43 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
10281029 skipped_range : self . skipped_range . clone ( ) ,
10291030 }
10301031 }
1032+
1033+ fn add_semi_on_last_block_stmt ( & self , stmt : & ast:: Stmt ) -> bool {
1034+ let ast:: StmtKind :: Expr ( expr) = & stmt. kind else {
1035+ return false ;
1036+ } ;
1037+
1038+ if self . is_macro_def {
1039+ return false ;
1040+ }
1041+
1042+ match expr. kind {
1043+ ast:: ExprKind :: Ret ( ..) | ast:: ExprKind :: Continue ( ..) | ast:: ExprKind :: Break ( ..) => {
1044+ self . config . trailing_semicolon ( )
1045+ }
1046+
1047+ // TODO[reviewer-help]: This is roughly "does it end in a
1048+ // curly". There might be a helper for this, or cases I'm
1049+ // missing.
1050+ ast:: ExprKind :: Loop ( ..)
1051+ | ast:: ExprKind :: While ( ..)
1052+ | ast:: ExprKind :: ForLoop { .. }
1053+ | ast:: ExprKind :: Let ( ..)
1054+ | ast:: ExprKind :: If ( ..)
1055+ | ast:: ExprKind :: Match ( ..) => false ,
1056+
1057+ _ => {
1058+ // Checking the edition as before 2024 the lack of a
1059+ // semicolon could impact temporary lifetimes[1].
1060+ //
1061+ // 1: https://rust-lang.github.io/rfcs/
1062+ // 3606-temporary-lifetimes-in-tail-expressions.html
1063+ let allowed_to_add_semi = self . is_loop_block
1064+ && self . config . edition ( ) >= Edition :: Edition2024
1065+ && self . config . style_edition ( ) >= StyleEdition :: Edition2027 ;
1066+
1067+ allowed_to_add_semi && self . config . trailing_semicolon ( )
1068+ }
1069+ }
1070+ }
10311071}
0 commit comments