@@ -9,9 +9,7 @@ use rustc_arena::TypedArena;
9
9
use rustc_ast:: Mutability ;
10
10
use rustc_data_structures:: fx:: FxHashSet ;
11
11
use 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 } ;
15
13
use rustc_hir as hir;
16
14
use rustc_hir:: def:: * ;
17
15
use rustc_hir:: def_id:: LocalDefId ;
@@ -507,17 +505,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
507
505
} ) ;
508
506
} ;
509
507
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 ) ;
521
509
522
510
// Emit an extra note if the first uncovered witness would be uninhabited
523
511
// if we disregard visibility.
@@ -842,7 +830,22 @@ fn non_exhaustive_match<'p, 'tcx>(
842
830
} ;
843
831
} ;
844
832
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
+ }
846
849
err. note ( format ! ( "the matched value is of type `{}`" , scrut_ty) ) ;
847
850
848
851
if !is_empty_match && witnesses. len ( ) == 1 {
@@ -1008,39 +1011,33 @@ fn collect_non_exhaustive_tys<'tcx>(
1008
1011
. for_each ( |field_pat| collect_non_exhaustive_tys ( field_pat, non_exhaustive_tys) )
1009
1012
}
1010
1013
1011
- /// Point at the definition of non-covered `enum` variants.
1012
- fn adt_defined_here < ' p , ' tcx > (
1013
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
1014
- err : & mut Diagnostic ,
1014
+ fn report_adt_defined_here < ' tcx > (
1015
+ tcx : TyCtxt < ' tcx > ,
1015
1016
ty : Ty < ' tcx > ,
1016
1017
witnesses : & [ WitnessPat < ' tcx > ] ,
1017
- ) {
1018
+ point_at_non_local_ty : bool ,
1019
+ ) -> Option < AdtDefinedHere < ' tcx > > {
1018
1020
let ty = ty. peel_refs ( ) ;
1019
- if let ty:: Adt ( def, _) = ty. kind ( ) {
1020
- let mut spans = vec ! [ ] ;
1021
- for sp in maybe_point_at_variant ( cx, * def, witnesses. iter ( ) . take ( 5 ) ) {
1022
- spans. push ( sp) ;
1023
- }
1024
- let def_span = cx
1025
- . tcx
1026
- . hir ( )
1027
- . get_if_local ( def. did ( ) )
1028
- . and_then ( |node| node. ident ( ) )
1029
- . map ( |ident| ident. span )
1030
- . unwrap_or_else ( || cx. tcx . def_span ( def. did ( ) ) ) ;
1031
- let mut span: MultiSpan =
1032
- if spans. is_empty ( ) { def_span. into ( ) } else { spans. clone ( ) . into ( ) } ;
1033
-
1034
- span. push_span_label ( def_span, "" ) ;
1035
- for pat in spans {
1036
- span. push_span_label ( pat, "not covered" ) ;
1037
- }
1038
- err. span_note ( span, format ! ( "`{ty}` defined here" ) ) ;
1021
+ let ty:: Adt ( def, _) = ty. kind ( ) else {
1022
+ return None ;
1023
+ } ;
1024
+ let adt_def_span =
1025
+ tcx. hir ( ) . get_if_local ( def. did ( ) ) . and_then ( |node| node. ident ( ) ) . map ( |ident| ident. span ) ;
1026
+ let adt_def_span = if point_at_non_local_ty {
1027
+ adt_def_span. unwrap_or_else ( || tcx. def_span ( def. did ( ) ) )
1028
+ } else {
1029
+ adt_def_span?
1030
+ } ;
1031
+
1032
+ let mut variants = vec ! [ ] ;
1033
+ for span in maybe_point_at_variant ( tcx, * def, witnesses. iter ( ) . take ( 5 ) ) {
1034
+ variants. push ( Variant { span } ) ;
1039
1035
}
1036
+ Some ( AdtDefinedHere { adt_def_span, ty, variants } )
1040
1037
}
1041
1038
1042
- fn maybe_point_at_variant < ' a , ' p : ' a , ' tcx : ' a > (
1043
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
1039
+ fn maybe_point_at_variant < ' a , ' tcx : ' a > (
1040
+ tcx : TyCtxt < ' tcx > ,
1044
1041
def : AdtDef < ' tcx > ,
1045
1042
patterns : impl Iterator < Item = & ' a WitnessPat < ' tcx > > ,
1046
1043
) -> Vec < Span > {
@@ -1053,15 +1050,15 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
1053
1050
{
1054
1051
continue ;
1055
1052
}
1056
- let sp = def. variant ( * variant_index) . ident ( cx . tcx ) . span ;
1053
+ let sp = def. variant ( * variant_index) . ident ( tcx) . span ;
1057
1054
if covered. contains ( & sp) {
1058
1055
// Don't point at variants that have already been covered due to other patterns to avoid
1059
1056
// visual clutter.
1060
1057
continue ;
1061
1058
}
1062
1059
covered. push ( sp) ;
1063
1060
}
1064
- covered. extend ( maybe_point_at_variant ( cx , def, pattern. iter_fields ( ) ) ) ;
1061
+ covered. extend ( maybe_point_at_variant ( tcx , def, pattern. iter_fields ( ) ) ) ;
1065
1062
}
1066
1063
covered
1067
1064
}
0 commit comments