@@ -258,7 +258,7 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
258
258
let mut next_feature_omits_tracking_issue = false ;
259
259
260
260
let mut in_feature_group = false ;
261
- let mut prev_name = None ;
261
+ let mut prev_names = vec ! [ ] ;
262
262
263
263
contents
264
264
. lines ( )
@@ -291,11 +291,11 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
291
291
}
292
292
293
293
in_feature_group = true ;
294
- prev_name = None ;
294
+ prev_names = vec ! [ ] ;
295
295
return None ;
296
296
} else if line. starts_with ( FEATURE_GROUP_END_PREFIX ) {
297
297
in_feature_group = false ;
298
- prev_name = None ;
298
+ prev_names = vec ! [ ] ;
299
299
return None ;
300
300
}
301
301
@@ -325,16 +325,49 @@ fn collect_lang_features_in(base: &Path, file: &str, bad: &mut bool) -> Features
325
325
}
326
326
} ;
327
327
if in_feature_group {
328
- if prev_name > Some ( name) {
328
+ if prev_names. last ( ) > Some ( & name) {
329
+ // This assumes the user adds the feature name at the end of the list, as we're
330
+ // not looking ahead.
331
+ let correct_index = match prev_names. binary_search ( & name) {
332
+ Ok ( _) => {
333
+ // This only occurs when the feature name has already been declared.
334
+ tidy_error ! (
335
+ bad,
336
+ "{}:{}: duplicate feature {}" ,
337
+ path. display( ) ,
338
+ line_number,
339
+ name,
340
+ ) ;
341
+ // skip any additional checks for this line
342
+ return None ;
343
+ }
344
+ Err ( index) => index,
345
+ } ;
346
+
347
+ let correct_placement = if correct_index == 0 {
348
+ "at the beginning of the feature group" . to_owned ( )
349
+ } else if correct_index == prev_names. len ( ) {
350
+ // I don't believe this is reachable given the above assumption, but it
351
+ // doesn't hurt to be safe.
352
+ "at the end of the feature group" . to_owned ( )
353
+ } else {
354
+ format ! (
355
+ "between {} and {}" ,
356
+ prev_names[ correct_index - 1 ] ,
357
+ prev_names[ correct_index] ,
358
+ )
359
+ } ;
360
+
329
361
tidy_error ! (
330
362
bad,
331
- "{}:{}: feature {} is not sorted by feature name" ,
363
+ "{}:{}: feature {} is not sorted by feature name (should be {}) " ,
332
364
path. display( ) ,
333
365
line_number,
334
366
name,
367
+ correct_placement,
335
368
) ;
336
369
}
337
- prev_name = Some ( name) ;
370
+ prev_names . push ( name) ;
338
371
}
339
372
340
373
let issue_str = parts. next ( ) . unwrap ( ) . trim ( ) ;
0 commit comments