@@ -785,13 +785,30 @@ impl Span {
785785 /// ^^^^^^^^^^^^^^^^^
786786 /// ```
787787 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+ }
790807 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 } ,
795812 )
796813 }
797814
0 commit comments