8
8
//! Thank you!
9
9
//! ~The `INTERNAL_METADATA_COLLECTOR` lint
10
10
11
- use rustc_errors:: { Applicability , Diag , DiagMessage , MultiSpan , SubdiagMessage } ;
11
+ use rustc_errors:: {
12
+ Applicability , Diag , DiagMessage , EmissionGuarantee , MultiSpan , SubdiagMessage , SubstitutionPart , Suggestions ,
13
+ } ;
12
14
use rustc_hir:: HirId ;
13
15
use rustc_lint:: { LateContext , Lint , LintContext } ;
14
16
use rustc_span:: Span ;
@@ -28,6 +30,42 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) {
28
30
}
29
31
}
30
32
33
+ /// Makes sure that a diagnostic is well formed.
34
+ ///
35
+ /// rustc debug asserts a few properties about spans,
36
+ /// but the clippy repo uses a distributed rustc build with debug assertions disabled,
37
+ /// so this has historically led to problems during subtree syncs where those debug assertions
38
+ /// only started triggered there.
39
+ ///
40
+ /// This function makes sure we also validate them in debug clippy builds.
41
+ fn validate_diag ( diag : & Diag < ' _ , impl EmissionGuarantee > ) {
42
+ let suggestions = match & diag. suggestions {
43
+ Suggestions :: Enabled ( suggs) => & * * suggs,
44
+ Suggestions :: Sealed ( suggs) => & * * suggs,
45
+ Suggestions :: Disabled => return ,
46
+ } ;
47
+
48
+ for substitution in suggestions. iter ( ) . flat_map ( |s| & s. substitutions ) {
49
+ assert_eq ! (
50
+ substitution
51
+ . parts
52
+ . iter( )
53
+ . find( |SubstitutionPart { snippet, span } | snippet. is_empty( ) && span. is_empty( ) ) ,
54
+ None ,
55
+ "span must not be empty and have no suggestion"
56
+ ) ;
57
+
58
+ assert_eq ! (
59
+ substitution
60
+ . parts
61
+ . array_windows( )
62
+ . find( |[ a, b] | a. span. overlaps( b. span) ) ,
63
+ None ,
64
+ "suggestion must not have overlapping parts"
65
+ ) ;
66
+ }
67
+ }
68
+
31
69
/// Emit a basic lint message with a `msg` and a `span`.
32
70
///
33
71
/// This is the most primitive of our lint emission methods and can
@@ -64,6 +102,9 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult
64
102
cx. span_lint ( lint, sp, |diag| {
65
103
diag. primary_message ( msg) ;
66
104
docs_link ( diag, lint) ;
105
+
106
+ #[ cfg( debug_assertions) ]
107
+ validate_diag ( diag) ;
67
108
} ) ;
68
109
}
69
110
@@ -118,6 +159,9 @@ pub fn span_lint_and_help<T: LintContext>(
118
159
diag. help ( help. into ( ) ) ;
119
160
}
120
161
docs_link ( diag, lint) ;
162
+
163
+ #[ cfg( debug_assertions) ]
164
+ validate_diag ( diag) ;
121
165
} ) ;
122
166
}
123
167
@@ -175,6 +219,9 @@ pub fn span_lint_and_note<T: LintContext>(
175
219
diag. note ( note. into ( ) ) ;
176
220
}
177
221
docs_link ( diag, lint) ;
222
+
223
+ #[ cfg( debug_assertions) ]
224
+ validate_diag ( diag) ;
178
225
} ) ;
179
226
}
180
227
@@ -208,6 +255,9 @@ where
208
255
diag. primary_message ( msg) ;
209
256
f ( diag) ;
210
257
docs_link ( diag, lint) ;
258
+
259
+ #[ cfg( debug_assertions) ]
260
+ validate_diag ( diag) ;
211
261
} ) ;
212
262
}
213
263
@@ -240,6 +290,9 @@ pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, s
240
290
cx. tcx . node_span_lint ( lint, hir_id, sp, |diag| {
241
291
diag. primary_message ( msg) ;
242
292
docs_link ( diag, lint) ;
293
+
294
+ #[ cfg( debug_assertions) ]
295
+ validate_diag ( diag) ;
243
296
} ) ;
244
297
}
245
298
@@ -280,6 +333,9 @@ pub fn span_lint_hir_and_then(
280
333
diag. primary_message ( msg) ;
281
334
f ( diag) ;
282
335
docs_link ( diag, lint) ;
336
+
337
+ #[ cfg( debug_assertions) ]
338
+ validate_diag ( diag) ;
283
339
} ) ;
284
340
}
285
341
@@ -328,5 +384,8 @@ pub fn span_lint_and_sugg<T: LintContext>(
328
384
) {
329
385
span_lint_and_then ( cx, lint, sp, msg. into ( ) , |diag| {
330
386
diag. span_suggestion ( sp, help. into ( ) , sugg, applicability) ;
387
+
388
+ #[ cfg( debug_assertions) ]
389
+ validate_diag ( diag) ;
331
390
} ) ;
332
391
}
0 commit comments