@@ -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 {
@@ -1024,39 +1027,33 @@ fn collect_non_exhaustive_tys<'tcx>(
1024
1027
. for_each ( |field_pat| collect_non_exhaustive_tys ( tcx, field_pat, non_exhaustive_tys) )
1025
1028
}
1026
1029
1027
- /// Point at the definition of non-covered `enum` variants.
1028
- fn adt_defined_here < ' p , ' tcx > (
1029
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
1030
- err : & mut Diagnostic ,
1030
+ fn report_adt_defined_here < ' tcx > (
1031
+ tcx : TyCtxt < ' tcx > ,
1031
1032
ty : Ty < ' tcx > ,
1032
1033
witnesses : & [ WitnessPat < ' tcx > ] ,
1033
- ) {
1034
+ point_at_non_local_ty : bool ,
1035
+ ) -> Option < AdtDefinedHere < ' tcx > > {
1034
1036
let ty = ty. peel_refs ( ) ;
1035
- if let ty:: Adt ( def, _) = ty. kind ( ) {
1036
- let mut spans = vec ! [ ] ;
1037
- for sp in maybe_point_at_variant ( cx, * def, witnesses. iter ( ) . take ( 5 ) ) {
1038
- spans. push ( sp) ;
1039
- }
1040
- let def_span = cx
1041
- . tcx
1042
- . hir ( )
1043
- . get_if_local ( def. did ( ) )
1044
- . and_then ( |node| node. ident ( ) )
1045
- . map ( |ident| ident. span )
1046
- . unwrap_or_else ( || cx. tcx . def_span ( def. did ( ) ) ) ;
1047
- let mut span: MultiSpan =
1048
- if spans. is_empty ( ) { def_span. into ( ) } else { spans. clone ( ) . into ( ) } ;
1049
-
1050
- span. push_span_label ( def_span, "" ) ;
1051
- for pat in spans {
1052
- span. push_span_label ( pat, "not covered" ) ;
1053
- }
1054
- err. span_note ( span, format ! ( "`{ty}` defined here" ) ) ;
1037
+ let ty:: Adt ( def, _) = ty. kind ( ) else {
1038
+ return None ;
1039
+ } ;
1040
+ let adt_def_span =
1041
+ tcx. hir ( ) . get_if_local ( def. did ( ) ) . and_then ( |node| node. ident ( ) ) . map ( |ident| ident. span ) ;
1042
+ let adt_def_span = if point_at_non_local_ty {
1043
+ adt_def_span. unwrap_or_else ( || tcx. def_span ( def. did ( ) ) )
1044
+ } else {
1045
+ adt_def_span?
1046
+ } ;
1047
+
1048
+ let mut variants = vec ! [ ] ;
1049
+ for span in maybe_point_at_variant ( tcx, * def, witnesses. iter ( ) . take ( 5 ) ) {
1050
+ variants. push ( Variant { span } ) ;
1055
1051
}
1052
+ Some ( AdtDefinedHere { adt_def_span, ty, variants } )
1056
1053
}
1057
1054
1058
- fn maybe_point_at_variant < ' a , ' p : ' a , ' tcx : ' a > (
1059
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
1055
+ fn maybe_point_at_variant < ' a , ' tcx : ' a > (
1056
+ tcx : TyCtxt < ' tcx > ,
1060
1057
def : AdtDef < ' tcx > ,
1061
1058
patterns : impl Iterator < Item = & ' a WitnessPat < ' tcx > > ,
1062
1059
) -> Vec < Span > {
@@ -1069,15 +1066,15 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
1069
1066
{
1070
1067
continue ;
1071
1068
}
1072
- let sp = def. variant ( * variant_index) . ident ( cx . tcx ) . span ;
1069
+ let sp = def. variant ( * variant_index) . ident ( tcx) . span ;
1073
1070
if covered. contains ( & sp) {
1074
1071
// Don't point at variants that have already been covered due to other patterns to avoid
1075
1072
// visual clutter.
1076
1073
continue ;
1077
1074
}
1078
1075
covered. push ( sp) ;
1079
1076
}
1080
- covered. extend ( maybe_point_at_variant ( cx , def, pattern. iter_fields ( ) ) ) ;
1077
+ covered. extend ( maybe_point_at_variant ( tcx , def, pattern. iter_fields ( ) ) ) ;
1081
1078
}
1082
1079
covered
1083
1080
}
0 commit comments