@@ -473,37 +473,64 @@ impl<'a> LintExtractor<'a> {
473473 . filter ( |line| line. starts_with ( '{' ) )
474474 . map ( serde_json:: from_str)
475475 . collect :: < Result < Vec < serde_json:: Value > , _ > > ( ) ?;
476+
476477 // First try to find the messages with the `code` field set to our lint.
477478 let matches: Vec < _ > = msgs
478479 . iter ( )
479480 . filter ( |msg| matches ! ( & msg[ "code" ] [ "code" ] , serde_json:: Value :: String ( s) if s==name) )
480481 . map ( |msg| msg[ "rendered" ] . as_str ( ) . expect ( "rendered field should exist" ) . to_string ( ) )
481482 . collect ( ) ;
482- if matches. is_empty ( ) {
483- // Some lints override their code to something else (E0566).
484- // Try to find something that looks like it could be our lint.
485- let matches: Vec < _ > = msgs. iter ( ) . filter ( |msg|
486- matches ! ( & msg[ "rendered" ] , serde_json:: Value :: String ( s) if s. contains( name) ) )
487- . map ( |msg| msg[ "rendered" ] . as_str ( ) . expect ( "rendered field should exist" ) . to_string ( ) )
488- . collect ( ) ;
489- if matches. is_empty ( ) {
490- let rendered: Vec < & str > =
491- msgs. iter ( ) . filter_map ( |msg| msg[ "rendered" ] . as_str ( ) ) . collect ( ) ;
492- let non_json: Vec < & str > =
493- stderr. lines ( ) . filter ( |line| !line. starts_with ( '{' ) ) . collect ( ) ;
494- Err ( format ! (
495- "did not find lint `{}` in output of example, got:\n {}\n {}" ,
496- name,
497- non_json. join( "\n " ) ,
498- rendered. join( "\n " )
499- )
500- . into ( ) )
501- } else {
502- Ok ( matches. join ( "\n " ) )
503- }
504- } else {
505- Ok ( matches. join ( "\n " ) )
483+ if !matches. is_empty ( ) {
484+ return Ok ( matches. join ( "\n " ) ) ;
485+ }
486+
487+ // Try to detect if an unstable lint forgot to enable a `#![feature(..)]`.
488+ // Specifically exclude `test_unstable_lint` which exercises this on purpose.
489+ if name != "test_unstable_lint"
490+ && msgs. iter ( ) . any ( |msg| {
491+ matches ! ( & msg[ "code" ] [ "code" ] , serde_json:: Value :: String ( s) if s=="unknown_lints" )
492+ && matches ! ( & msg[ "message" ] , serde_json:: Value :: String ( s) if s. contains( name) )
493+ } )
494+ {
495+ let rendered: Vec < & str > =
496+ msgs. iter ( ) . filter_map ( |msg| msg[ "rendered" ] . as_str ( ) ) . collect ( ) ;
497+ let non_json: Vec < & str > =
498+ stderr. lines ( ) . filter ( |line| !line. starts_with ( '{' ) ) . collect ( ) ;
499+ return Err ( format ! (
500+ "did not find lint `{}` in output of example (got unknown_lints)\n \
501+ Is the lint possibly misspelled, or does it need a `#![feature(...)]`?\n \
502+ Output was:\n \
503+ {}\n {}",
504+ name,
505+ rendered. join( "\n " ) ,
506+ non_json. join( "\n " ) ,
507+ )
508+ . into ( ) ) ;
506509 }
510+
511+ // Some lints override their code to something else (E0566).
512+ // Try to find something that looks like it could be our lint.
513+ let matches: Vec < _ > = msgs
514+ . iter ( )
515+ . filter (
516+ |msg| matches ! ( & msg[ "rendered" ] , serde_json:: Value :: String ( s) if s. contains( name) ) ,
517+ )
518+ . map ( |msg| msg[ "rendered" ] . as_str ( ) . expect ( "rendered field should exist" ) . to_string ( ) )
519+ . collect ( ) ;
520+ if !matches. is_empty ( ) {
521+ return Ok ( matches. join ( "\n " ) ) ;
522+ }
523+
524+ // Otherwise, give a descriptive error.
525+ let rendered: Vec < & str > = msgs. iter ( ) . filter_map ( |msg| msg[ "rendered" ] . as_str ( ) ) . collect ( ) ;
526+ let non_json: Vec < & str > = stderr. lines ( ) . filter ( |line| !line. starts_with ( '{' ) ) . collect ( ) ;
527+ Err ( format ! (
528+ "did not find lint `{}` in output of example, got:\n {}\n {}" ,
529+ name,
530+ non_json. join( "\n " ) ,
531+ rendered. join( "\n " )
532+ )
533+ . into ( ) )
507534 }
508535
509536 /// Saves the mdbook lint chapters at the given path.
0 commit comments