@@ -45,6 +45,9 @@ pub struct DocFragment {
4545 pub doc : Symbol ,
4646 pub kind : DocFragmentKind ,
4747 pub indent : usize ,
48+ /// Because we temper with the spans context, this information cannot be correctly retrieved
49+ /// later on. So instead, we compute it and store it here.
50+ pub from_expansion : bool ,
4851}
4952
5053#[ derive( Clone , Copy , Debug ) ]
@@ -204,17 +207,18 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
204207 for ( attr, item_id) in attrs {
205208 if let Some ( ( doc_str, comment_kind) ) = attr. doc_str_and_comment_kind ( ) {
206209 let doc = beautify_doc_string ( doc_str, comment_kind) ;
207- let ( span, kind) = if attr. is_doc_comment ( ) {
208- ( attr. span ( ) , DocFragmentKind :: SugaredDoc )
210+ let ( span, kind, from_expansion) = if attr. is_doc_comment ( ) {
211+ let span = attr. span ( ) ;
212+ ( span, DocFragmentKind :: SugaredDoc , span. from_expansion ( ) )
209213 } else {
210- (
211- attr. value_span ( )
212- . map ( |i| i . with_ctxt ( attr . span ( ) . ctxt ( ) ) )
213- . unwrap_or ( attr . span ( ) ) ,
214- DocFragmentKind :: RawDoc ,
215- )
214+ let attr_span = attr . span ( ) ;
215+ let ( span , from_expansion ) = match attr. value_span ( ) {
216+ Some ( sp ) => ( sp . with_ctxt ( attr_span . ctxt ( ) ) , sp . from_expansion ( ) ) ,
217+ None => ( attr_span , attr_span . from_expansion ( ) ) ,
218+ } ;
219+ ( span , DocFragmentKind :: RawDoc , from_expansion )
216220 } ;
217- let fragment = DocFragment { span, doc, kind, item_id, indent : 0 } ;
221+ let fragment = DocFragment { span, doc, kind, item_id, indent : 0 , from_expansion } ;
218222 doc_fragments. push ( fragment) ;
219223 } else if !doc_only {
220224 other_attrs. push ( attr. clone ( ) ) ;
@@ -497,16 +501,21 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>(
497501}
498502
499503/// Returns a span encompassing all the document fragments.
500- pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
501- if fragments. is_empty ( ) {
502- return None ;
503- }
504- let start = fragments[ 0 ] . span ;
505- if start == DUMMY_SP {
504+ pub fn span_of_fragments_with_expansion ( fragments : & [ DocFragment ] ) -> Option < ( Span , bool ) > {
505+ let Some ( first_fragment) = fragments. first ( ) else { return None } ;
506+ if first_fragment. span == DUMMY_SP {
506507 return None ;
507508 }
508- let end = fragments. last ( ) . expect ( "no doc strings provided" ) . span ;
509- Some ( start. to ( end) )
509+ let last_fragment = fragments. last ( ) . expect ( "no doc strings provided" ) ;
510+ Some ( (
511+ first_fragment. span . to ( last_fragment. span ) ,
512+ first_fragment. from_expansion || last_fragment. from_expansion ,
513+ ) )
514+ }
515+
516+ /// Returns a span encompassing all the document fragments.
517+ pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
518+ span_of_fragments_with_expansion ( fragments) . map ( |( sp, _) | sp)
510519}
511520
512521/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
@@ -531,7 +540,7 @@ pub fn source_span_for_markdown_range(
531540 markdown : & str ,
532541 md_range : & Range < usize > ,
533542 fragments : & [ DocFragment ] ,
534- ) -> Option < Span > {
543+ ) -> Option < ( Span , bool ) > {
535544 use rustc_span:: BytePos ;
536545
537546 let map = tcx. sess . source_map ( ) ;
@@ -543,11 +552,14 @@ pub fn source_span_for_markdown_range(
543552 && let Ok ( md_range_hi) = u32:: try_from ( md_range. end )
544553 {
545554 // Single fragment with string that contains same bytes as doc.
546- return Some ( Span :: new (
547- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
548- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
549- fragment. span . ctxt ( ) ,
550- fragment. span . parent ( ) ,
555+ return Some ( (
556+ Span :: new (
557+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
558+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
559+ fragment. span . ctxt ( ) ,
560+ fragment. span . parent ( ) ,
561+ ) ,
562+ fragment. from_expansion ,
551563 ) ) ;
552564 }
553565
@@ -573,19 +585,21 @@ pub fn source_span_for_markdown_range(
573585 if match_data. is_none ( ) && !snippet[ match_start + 1 ..] . contains ( pat) {
574586 match_data = Some ( ( i, match_start) ) ;
575587 } else {
576- // Heirustic produced ambiguity, return nothing.
588+ // Heuristic produced ambiguity, return nothing.
577589 return None ;
578590 }
579591 }
580592 }
581593 if let Some ( ( i, match_start) ) = match_data {
582- let sp = fragments[ i] . span ;
594+ let fragment = & fragments[ i] ;
595+ let sp = fragment. span ;
583596 // we need to calculate the span start,
584597 // then use that in our calulations for the span end
585598 let lo = sp. lo ( ) + BytePos ( match_start as u32 ) ;
586- return Some (
599+ return Some ( (
587600 sp. with_lo ( lo) . with_hi ( lo + BytePos ( ( md_range. end - md_range. start ) as u32 ) ) ,
588- ) ;
601+ fragment. from_expansion ,
602+ ) ) ;
589603 }
590604 return None ;
591605 }
@@ -639,8 +653,12 @@ pub fn source_span_for_markdown_range(
639653 }
640654 }
641655
642- Some ( span_of_fragments ( fragments) ?. from_inner ( InnerSpan :: new (
643- md_range. start + start_bytes,
644- md_range. end + start_bytes + end_bytes,
645- ) ) )
656+ let ( span, from_expansion) = span_of_fragments_with_expansion ( fragments) ?;
657+ Some ( (
658+ span. from_inner ( InnerSpan :: new (
659+ md_range. start + start_bytes,
660+ md_range. end + start_bytes + end_bytes,
661+ ) ) ,
662+ from_expansion,
663+ ) )
646664}
0 commit comments