@@ -144,16 +144,8 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
144144 } ) ;
145145 return ;
146146 }
147- ExprKind :: Match { scrutinee, scrutinee_hir_id, box ref arms } => {
148- let source = match ex. span . desugaring_kind ( ) {
149- Some ( DesugaringKind :: ForLoop ) => hir:: MatchSource :: ForLoopDesugar ,
150- Some ( DesugaringKind :: QuestionMark ) => {
151- hir:: MatchSource :: TryDesugar ( scrutinee_hir_id)
152- }
153- Some ( DesugaringKind :: Await ) => hir:: MatchSource :: AwaitDesugar ,
154- _ => hir:: MatchSource :: Normal ,
155- } ;
156- self . check_match ( scrutinee, arms, source, ex. span ) ;
147+ ExprKind :: Match { scrutinee, scrutinee_hir_id : _, box ref arms, match_source } => {
148+ self . check_match ( scrutinee, arms, match_source, ex. span ) ;
157149 }
158150 ExprKind :: Let { box ref pat, expr } => {
159151 self . check_let ( pat, Some ( expr) , ex. span ) ;
@@ -505,8 +497,41 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
505497 None ,
506498 ) ;
507499 } else {
500+ // span after scrutinee, or after `.match`. That is, the braces, arms,
501+ // and any whitespace preceding the braces.
502+ let braces_span = match source {
503+ hir:: MatchSource :: Normal => scrut
504+ . span
505+ . find_ancestor_in_same_ctxt ( expr_span)
506+ . map ( |scrut_span| scrut_span. shrink_to_hi ( ) . with_hi ( expr_span. hi ( ) ) ) ,
507+ hir:: MatchSource :: Postfix => {
508+ // This is horrendous, and we should deal with it by just
509+ // stashing the span of the braces somewhere (like in the match source).
510+ scrut. span . find_ancestor_in_same_ctxt ( expr_span) . and_then ( |scrut_span| {
511+ let sm = self . tcx . sess . source_map ( ) ;
512+ let brace_span = sm. span_extend_to_next_char ( scrut_span, '{' , true ) ;
513+ if sm. span_to_snippet ( sm. next_point ( brace_span) ) . as_deref ( ) == Ok ( "{" ) {
514+ let sp = brace_span. shrink_to_hi ( ) . with_hi ( expr_span. hi ( ) ) ;
515+ // We also need to extend backwards for whitespace
516+ sm. span_extend_prev_while ( sp, |c| c. is_whitespace ( ) ) . ok ( )
517+ } else {
518+ None
519+ }
520+ } )
521+ }
522+ hir:: MatchSource :: ForLoopDesugar
523+ | hir:: MatchSource :: TryDesugar ( _)
524+ | hir:: MatchSource :: AwaitDesugar
525+ | hir:: MatchSource :: FormatArgs => None ,
526+ } ;
508527 self . error = Err ( report_non_exhaustive_match (
509- & cx, self . thir , scrut. ty , scrut. span , witnesses, arms, expr_span,
528+ & cx,
529+ self . thir ,
530+ scrut. ty ,
531+ scrut. span ,
532+ witnesses,
533+ arms,
534+ braces_span,
510535 ) ) ;
511536 }
512537 }
@@ -929,7 +954,7 @@ fn report_non_exhaustive_match<'p, 'tcx>(
929954 sp : Span ,
930955 witnesses : Vec < WitnessPat < ' p , ' tcx > > ,
931956 arms : & [ ArmId ] ,
932- expr_span : Span ,
957+ braces_span : Option < Span > ,
933958) -> ErrorGuaranteed {
934959 let is_empty_match = arms. is_empty ( ) ;
935960 let non_empty_enum = match scrut_ty. kind ( ) {
@@ -941,8 +966,8 @@ fn report_non_exhaustive_match<'p, 'tcx>(
941966 if is_empty_match && !non_empty_enum {
942967 return cx. tcx . dcx ( ) . emit_err ( NonExhaustivePatternsTypeNotEmpty {
943968 cx,
944- expr_span ,
945- span : sp ,
969+ scrut_span : sp ,
970+ braces_span ,
946971 ty : scrut_ty,
947972 } ) ;
948973 }
@@ -1028,15 +1053,15 @@ fn report_non_exhaustive_match<'p, 'tcx>(
10281053 let mut suggestion = None ;
10291054 let sm = cx. tcx . sess . source_map ( ) ;
10301055 match arms {
1031- [ ] if sp . eq_ctxt ( expr_span ) => {
1056+ [ ] if let Some ( braces_span ) = braces_span => {
10321057 // Get the span for the empty match body `{}`.
10331058 let ( indentation, more) = if let Some ( snippet) = sm. indentation_before ( sp) {
10341059 ( format ! ( "\n {snippet}" ) , " " )
10351060 } else {
10361061 ( " " . to_string ( ) , "" )
10371062 } ;
10381063 suggestion = Some ( (
1039- sp . shrink_to_hi ( ) . with_hi ( expr_span . hi ( ) ) ,
1064+ braces_span ,
10401065 format ! ( " {{{indentation}{more}{suggested_arm},{indentation}}}" , ) ,
10411066 ) ) ;
10421067 }
0 commit comments