@@ -9,9 +9,7 @@ use rustc_arena::TypedArena;
99use rustc_ast:: Mutability ;
1010use rustc_data_structures:: fx:: FxHashSet ;
1111use rustc_data_structures:: stack:: ensure_sufficient_stack;
12- use rustc_errors:: {
13- struct_span_err, Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed , MultiSpan ,
14- } ;
12+ use rustc_errors:: { struct_span_err, Applicability , DiagnosticBuilder , ErrorGuaranteed , MultiSpan } ;
1513use rustc_hir as hir;
1614use rustc_hir:: def:: * ;
1715use rustc_hir:: def_id:: LocalDefId ;
@@ -507,17 +505,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
507505 } ) ;
508506 } ;
509507
510- let adt_defined_here = try {
511- let ty = pattern_ty. peel_refs ( ) ;
512- let ty:: Adt ( def, _) = ty. kind ( ) else { None ? } ;
513- let adt_def_span = cx. tcx . hir ( ) . get_if_local ( def. did ( ) ) ?. ident ( ) ?. span ;
514- let mut variants = vec ! [ ] ;
515-
516- for span in maybe_point_at_variant ( & cx, * def, witnesses. iter ( ) . take ( 5 ) ) {
517- variants. push ( Variant { span } ) ;
518- }
519- AdtDefinedHere { adt_def_span, ty, variants }
520- } ;
508+ let adt_defined_here = report_adt_defined_here ( self . tcx , pattern_ty, & witnesses, false ) ;
521509
522510 // Emit an extra note if the first uncovered witness would be uninhabited
523511 // if we disregard visibility.
@@ -842,7 +830,22 @@ fn non_exhaustive_match<'p, 'tcx>(
842830 } ;
843831 } ;
844832
845- adt_defined_here ( cx, & mut err, scrut_ty, & witnesses) ;
833+ // Point at the definition of non-covered `enum` variants.
834+ if let Some ( AdtDefinedHere { adt_def_span, ty, variants } ) =
835+ report_adt_defined_here ( cx. tcx , scrut_ty, & witnesses, true )
836+ {
837+ let mut multi_span = if variants. is_empty ( ) {
838+ MultiSpan :: from_span ( adt_def_span)
839+ } else {
840+ MultiSpan :: from_spans ( variants. iter ( ) . map ( |Variant { span } | * span) . collect ( ) )
841+ } ;
842+
843+ multi_span. push_span_label ( adt_def_span, "" ) ;
844+ for Variant { span } in variants {
845+ multi_span. push_span_label ( span, "not covered" ) ;
846+ }
847+ err. span_note ( multi_span, format ! ( "`{ty}` defined here" ) ) ;
848+ }
846849 err. note ( format ! ( "the matched value is of type `{}`" , scrut_ty) ) ;
847850
848851 if !is_empty_match {
@@ -1023,39 +1026,33 @@ fn collect_non_exhaustive_tys<'tcx>(
10231026 . for_each ( |field_pat| collect_non_exhaustive_tys ( tcx, field_pat, non_exhaustive_tys) )
10241027}
10251028
1026- /// Point at the definition of non-covered `enum` variants.
1027- fn adt_defined_here < ' p , ' tcx > (
1028- cx : & MatchCheckCtxt < ' p , ' tcx > ,
1029- err : & mut Diagnostic ,
1029+ fn report_adt_defined_here < ' tcx > (
1030+ tcx : TyCtxt < ' tcx > ,
10301031 ty : Ty < ' tcx > ,
10311032 witnesses : & [ WitnessPat < ' tcx > ] ,
1032- ) {
1033+ point_at_non_local_ty : bool ,
1034+ ) -> Option < AdtDefinedHere < ' tcx > > {
10331035 let ty = ty. peel_refs ( ) ;
1034- if let ty:: Adt ( def, _) = ty. kind ( ) {
1035- let mut spans = vec ! [ ] ;
1036- for sp in maybe_point_at_variant ( cx, * def, witnesses. iter ( ) . take ( 5 ) ) {
1037- spans. push ( sp) ;
1038- }
1039- let def_span = cx
1040- . tcx
1041- . hir ( )
1042- . get_if_local ( def. did ( ) )
1043- . and_then ( |node| node. ident ( ) )
1044- . map ( |ident| ident. span )
1045- . unwrap_or_else ( || cx. tcx . def_span ( def. did ( ) ) ) ;
1046- let mut span: MultiSpan =
1047- if spans. is_empty ( ) { def_span. into ( ) } else { spans. clone ( ) . into ( ) } ;
1048-
1049- span. push_span_label ( def_span, "" ) ;
1050- for pat in spans {
1051- span. push_span_label ( pat, "not covered" ) ;
1052- }
1053- err. span_note ( span, format ! ( "`{ty}` defined here" ) ) ;
1036+ let ty:: Adt ( def, _) = ty. kind ( ) else {
1037+ return None ;
1038+ } ;
1039+ let adt_def_span =
1040+ tcx. hir ( ) . get_if_local ( def. did ( ) ) . and_then ( |node| node. ident ( ) ) . map ( |ident| ident. span ) ;
1041+ let adt_def_span = if point_at_non_local_ty {
1042+ adt_def_span. unwrap_or_else ( || tcx. def_span ( def. did ( ) ) )
1043+ } else {
1044+ adt_def_span?
1045+ } ;
1046+
1047+ let mut variants = vec ! [ ] ;
1048+ for span in maybe_point_at_variant ( tcx, * def, witnesses. iter ( ) . take ( 5 ) ) {
1049+ variants. push ( Variant { span } ) ;
10541050 }
1051+ Some ( AdtDefinedHere { adt_def_span, ty, variants } )
10551052}
10561053
1057- fn maybe_point_at_variant < ' a , ' p : ' a , ' tcx : ' a > (
1058- cx : & MatchCheckCtxt < ' p , ' tcx > ,
1054+ fn maybe_point_at_variant < ' a , ' tcx : ' a > (
1055+ tcx : TyCtxt < ' tcx > ,
10591056 def : AdtDef < ' tcx > ,
10601057 patterns : impl Iterator < Item = & ' a WitnessPat < ' tcx > > ,
10611058) -> Vec < Span > {
@@ -1068,15 +1065,15 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
10681065 {
10691066 continue ;
10701067 }
1071- let sp = def. variant ( * variant_index) . ident ( cx . tcx ) . span ;
1068+ let sp = def. variant ( * variant_index) . ident ( tcx) . span ;
10721069 if covered. contains ( & sp) {
10731070 // Don't point at variants that have already been covered due to other patterns to avoid
10741071 // visual clutter.
10751072 continue ;
10761073 }
10771074 covered. push ( sp) ;
10781075 }
1079- covered. extend ( maybe_point_at_variant ( cx , def, pattern. iter_fields ( ) ) ) ;
1076+ covered. extend ( maybe_point_at_variant ( tcx , def, pattern. iter_fields ( ) ) ) ;
10801077 }
10811078 covered
10821079}
0 commit comments