@@ -785,13 +785,30 @@ impl Span {
785
785
/// ^^^^^^^^^^^^^^^^^
786
786
/// ```
787
787
pub fn until ( self , end : Span ) -> Span {
788
- let span = self . data ( ) ;
789
- let end = end. data ( ) ;
788
+ // Most of this function's body is copied from `to`.
789
+ // We can't just do `self.to(end.shrink_to_lo())`,
790
+ // because to also does some magic where it uses min/max so
791
+ // it can handle overlapping spans. Some advanced mis-use of
792
+ // `until` with different ctxts makes this visible.
793
+ let span_data = self . data ( ) ;
794
+ let end_data = end. data ( ) ;
795
+ // FIXME(jseyfried): `self.ctxt` should always equal `end.ctxt` here (cf. issue #23480).
796
+ // Return the macro span on its own to avoid weird diagnostic output. It is preferable to
797
+ // have an incomplete span than a completely nonsensical one.
798
+ if span_data. ctxt != end_data. ctxt {
799
+ if span_data. ctxt == SyntaxContext :: root ( ) {
800
+ return end;
801
+ } else if end_data. ctxt == SyntaxContext :: root ( ) {
802
+ return self ;
803
+ }
804
+ // Both spans fall within a macro.
805
+ // FIXME(estebank): check if it is the *same* macro.
806
+ }
790
807
Span :: new (
791
- span . lo ,
792
- end . lo ,
793
- if end . ctxt == SyntaxContext :: root ( ) { end . ctxt } else { span . ctxt } ,
794
- if span . parent == end . parent { span . parent } else { None } ,
808
+ span_data . lo ,
809
+ end_data . lo ,
810
+ if end_data . ctxt == SyntaxContext :: root ( ) { end_data . ctxt } else { span_data . ctxt } ,
811
+ if span_data . parent == end_data . parent { span_data . parent } else { None } ,
795
812
)
796
813
}
797
814
0 commit comments