@@ -49,6 +49,9 @@ pub struct DocFragment {
4949 pub doc : Symbol ,
5050 pub kind : DocFragmentKind ,
5151 pub indent : usize ,
52+ /// Because we temper with the spans context, this information cannot be correctly retrieved
53+ /// later on. So instead, we compute it and store it here.
54+ pub from_expansion : bool ,
5255}
5356
5457#[ derive( Clone , Copy , Debug ) ]
@@ -208,17 +211,18 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
208211 for ( attr, item_id) in attrs {
209212 if let Some ( ( doc_str, comment_kind) ) = attr. doc_str_and_comment_kind ( ) {
210213 let doc = beautify_doc_string ( doc_str, comment_kind) ;
211- let ( span, kind) = if attr. is_doc_comment ( ) {
212- ( attr. span ( ) , DocFragmentKind :: SugaredDoc )
214+ let ( span, kind, from_expansion) = if attr. is_doc_comment ( ) {
215+ let span = attr. span ( ) ;
216+ ( span, DocFragmentKind :: SugaredDoc , span. from_expansion ( ) )
213217 } else {
214- (
215- attr. value_span ( )
216- . map ( |i| i . with_ctxt ( attr . span ( ) . ctxt ( ) ) )
217- . unwrap_or ( attr . span ( ) ) ,
218- DocFragmentKind :: RawDoc ,
219- )
218+ let attr_span = attr . span ( ) ;
219+ let ( span , from_expansion ) = match attr. value_span ( ) {
220+ Some ( sp ) => ( sp . with_ctxt ( attr_span . ctxt ( ) ) , sp . from_expansion ( ) ) ,
221+ None => ( attr_span , attr_span . from_expansion ( ) ) ,
222+ } ;
223+ ( span , DocFragmentKind :: RawDoc , from_expansion )
220224 } ;
221- let fragment = DocFragment { span, doc, kind, item_id, indent : 0 } ;
225+ let fragment = DocFragment { span, doc, kind, item_id, indent : 0 , from_expansion } ;
222226 doc_fragments. push ( fragment) ;
223227 } else if !doc_only {
224228 other_attrs. push ( attr. clone ( ) ) ;
@@ -506,16 +510,21 @@ fn collect_link_data<'input, F: BrokenLinkCallback<'input>>(
506510}
507511
508512/// Returns a span encompassing all the document fragments.
509- pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
510- if fragments. is_empty ( ) {
511- return None ;
512- }
513- let start = fragments[ 0 ] . span ;
514- if start == DUMMY_SP {
513+ pub fn span_of_fragments_with_expansion ( fragments : & [ DocFragment ] ) -> Option < ( Span , bool ) > {
514+ let Some ( first_fragment) = fragments. first ( ) else { return None } ;
515+ if first_fragment. span == DUMMY_SP {
515516 return None ;
516517 }
517- let end = fragments. last ( ) . expect ( "no doc strings provided" ) . span ;
518- Some ( start. to ( end) )
518+ let last_fragment = fragments. last ( ) . expect ( "no doc strings provided" ) ;
519+ Some ( (
520+ first_fragment. span . to ( last_fragment. span ) ,
521+ first_fragment. from_expansion || last_fragment. from_expansion ,
522+ ) )
523+ }
524+
525+ /// Returns a span encompassing all the document fragments.
526+ pub fn span_of_fragments ( fragments : & [ DocFragment ] ) -> Option < Span > {
527+ span_of_fragments_with_expansion ( fragments) . map ( |( sp, _) | sp)
519528}
520529
521530/// Attempts to match a range of bytes from parsed markdown to a `Span` in the source code.
@@ -540,7 +549,7 @@ pub fn source_span_for_markdown_range(
540549 markdown : & str ,
541550 md_range : & Range < usize > ,
542551 fragments : & [ DocFragment ] ,
543- ) -> Option < Span > {
552+ ) -> Option < ( Span , bool ) > {
544553 let map = tcx. sess . source_map ( ) ;
545554 source_span_for_markdown_range_inner ( map, markdown, md_range, fragments)
546555}
@@ -551,7 +560,7 @@ pub fn source_span_for_markdown_range_inner(
551560 markdown : & str ,
552561 md_range : & Range < usize > ,
553562 fragments : & [ DocFragment ] ,
554- ) -> Option < Span > {
563+ ) -> Option < ( Span , bool ) > {
555564 use rustc_span:: BytePos ;
556565
557566 if let & [ fragment] = & fragments
@@ -562,11 +571,14 @@ pub fn source_span_for_markdown_range_inner(
562571 && let Ok ( md_range_hi) = u32:: try_from ( md_range. end )
563572 {
564573 // Single fragment with string that contains same bytes as doc.
565- return Some ( Span :: new (
566- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
567- fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
568- fragment. span . ctxt ( ) ,
569- fragment. span . parent ( ) ,
574+ return Some ( (
575+ Span :: new (
576+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_lo) ,
577+ fragment. span . lo ( ) + rustc_span:: BytePos ( md_range_hi) ,
578+ fragment. span . ctxt ( ) ,
579+ fragment. span . parent ( ) ,
580+ ) ,
581+ fragment. from_expansion ,
570582 ) ) ;
571583 }
572584
@@ -598,19 +610,21 @@ pub fn source_span_for_markdown_range_inner(
598610 {
599611 match_data = Some ( ( i, match_start) ) ;
600612 } else {
601- // Heirustic produced ambiguity, return nothing.
613+ // Heuristic produced ambiguity, return nothing.
602614 return None ;
603615 }
604616 }
605617 }
606618 if let Some ( ( i, match_start) ) = match_data {
607- let sp = fragments[ i] . span ;
619+ let fragment = & fragments[ i] ;
620+ let sp = fragment. span ;
608621 // we need to calculate the span start,
609622 // then use that in our calulations for the span end
610623 let lo = sp. lo ( ) + BytePos ( match_start as u32 ) ;
611- return Some (
624+ return Some ( (
612625 sp. with_lo ( lo) . with_hi ( lo + BytePos ( ( md_range. end - md_range. start ) as u32 ) ) ,
613- ) ;
626+ fragment. from_expansion ,
627+ ) ) ;
614628 }
615629 return None ;
616630 }
@@ -664,8 +678,12 @@ pub fn source_span_for_markdown_range_inner(
664678 }
665679 }
666680
667- Some ( span_of_fragments ( fragments) ?. from_inner ( InnerSpan :: new (
668- md_range. start + start_bytes,
669- md_range. end + start_bytes + end_bytes,
670- ) ) )
681+ let ( span, from_expansion) = span_of_fragments_with_expansion ( fragments) ?;
682+ Some ( (
683+ span. from_inner ( InnerSpan :: new (
684+ md_range. start + start_bytes,
685+ md_range. end + start_bytes + end_bytes,
686+ ) ) ,
687+ from_expansion,
688+ ) )
671689}
0 commit comments