@@ -51,8 +51,17 @@ impl DocTestBuilder {
5151 !lang_str. compile_fail && !lang_str. test_harness && !lang_str. standalone_crate
5252 } ) ;
5353
54- let SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else } =
55- partition_source ( source, edition) ;
54+ let Some ( SourceInfo { crate_attrs, maybe_crate_attrs, crates, everything_else } ) =
55+ partition_source ( source, edition)
56+ else {
57+ return Self :: invalid (
58+ String :: new ( ) ,
59+ String :: new ( ) ,
60+ String :: new ( ) ,
61+ source. to_string ( ) ,
62+ test_id,
63+ ) ;
64+ } ;
5665
5766 // Uses librustc_ast to parse the doctest and find if there's a main fn and the extern
5867 // crate already is included.
@@ -77,18 +86,7 @@ impl DocTestBuilder {
7786 else {
7887 // If the parser panicked due to a fatal error, pass the test code through unchanged.
7988 // The error will be reported during compilation.
80- return Self {
81- supports_color : false ,
82- has_main_fn : false ,
83- crate_attrs,
84- maybe_crate_attrs,
85- crates,
86- everything_else,
87- already_has_extern_crate : false ,
88- test_id,
89- failed_ast : true ,
90- can_be_merged : false ,
91- } ;
89+ return Self :: invalid ( crate_attrs, maybe_crate_attrs, crates, everything_else, test_id) ;
9290 } ;
9391 // If the AST returned an error, we don't want this doctest to be merged with the
9492 // others. Same if it contains `#[feature]` or `#[no_std]`.
@@ -113,6 +111,27 @@ impl DocTestBuilder {
113111 }
114112 }
115113
114+ fn invalid (
115+ crate_attrs : String ,
116+ maybe_crate_attrs : String ,
117+ crates : String ,
118+ everything_else : String ,
119+ test_id : Option < String > ,
120+ ) -> Self {
121+ Self {
122+ supports_color : false ,
123+ has_main_fn : false ,
124+ crate_attrs,
125+ maybe_crate_attrs,
126+ crates,
127+ everything_else,
128+ already_has_extern_crate : false ,
129+ test_id,
130+ failed_ast : true ,
131+ can_be_merged : false ,
132+ }
133+ }
134+
116135 /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
117136 /// lines before the test code begins.
118137 pub ( crate ) fn generate_unique_doctest (
@@ -518,8 +537,8 @@ fn handle_attr(mod_attr_pending: &mut String, source_info: &mut SourceInfo, edit
518537 push_to. push ( '\n' ) ;
519538 // If it's complete, then we can clear the pending content.
520539 mod_attr_pending. clear ( ) ;
521- } else if mod_attr_pending . ends_with ( '\\' ) {
522- mod_attr_pending. push ( 'n' ) ;
540+ } else {
541+ mod_attr_pending. push_str ( " \n " ) ;
523542 }
524543}
525544
@@ -531,7 +550,7 @@ struct SourceInfo {
531550 everything_else : String ,
532551}
533552
534- fn partition_source ( s : & str , edition : Edition ) -> SourceInfo {
553+ fn partition_source ( s : & str , edition : Edition ) -> Option < SourceInfo > {
535554 #[ derive( Copy , Clone , PartialEq ) ]
536555 enum PartitionState {
537556 Attrs ,
@@ -606,11 +625,16 @@ fn partition_source(s: &str, edition: Edition) -> SourceInfo {
606625 }
607626 }
608627
628+ if !mod_attr_pending. is_empty ( ) {
629+ debug ! ( "invalid doctest code: {s:?}" ) ;
630+ return None ;
631+ }
632+
609633 source_info. everything_else = source_info. everything_else . trim ( ) . to_string ( ) ;
610634
611635 debug ! ( "crate_attrs:\n {}{}" , source_info. crate_attrs, source_info. maybe_crate_attrs) ;
612636 debug ! ( "crates:\n {}" , source_info. crates) ;
613637 debug ! ( "after:\n {}" , source_info. everything_else) ;
614638
615- source_info
639+ Some ( source_info)
616640}
0 commit comments