|
1 | 1 | use crate::def_id::{DefIndex, LocalDefId};
|
2 | 2 | use crate::hygiene::SyntaxContext;
|
3 |
| -use crate::SPAN_TRACK; |
| 3 | +use crate::{try_with_session_globals, NotSet, Pos, SPAN_TRACK}; |
4 | 4 | use crate::{BytePos, SpanData};
|
5 | 5 |
|
6 | 6 | use rustc_data_structures::fx::FxIndexSet;
|
@@ -103,6 +103,40 @@ impl Span {
|
103 | 103 | ctxt: SyntaxContext,
|
104 | 104 | parent: Option<LocalDefId>,
|
105 | 105 | ) -> Self {
|
| 106 | + // Make sure that the byte positions are at char boundaries. |
| 107 | + // Only do this if the session globals are set correctly, which they aren't in some unit tests. |
| 108 | + if cfg!(debug_assertions) { |
| 109 | + let _: Result<(), NotSet> = try_with_session_globals(|sess| { |
| 110 | + let sm = sess.source_map.lock(); |
| 111 | + if let Some(sm) = &*sm { |
| 112 | + let offset = sm.lookup_byte_offset(lo); |
| 113 | + if let Some(file) = &offset.sf.src { |
| 114 | + // `is_char_boundary` already checks this, but asserting it seperately gives a better panic message. |
| 115 | + assert!( |
| 116 | + file.len() >= offset.pos.to_usize(), |
| 117 | + "start of span is out of bounds" |
| 118 | + ); |
| 119 | + assert!( |
| 120 | + file.is_char_boundary(offset.pos.to_usize()), |
| 121 | + "start of span not on char boundary" |
| 122 | + ); |
| 123 | + } |
| 124 | + |
| 125 | + let offset = sm.lookup_byte_offset(hi); |
| 126 | + if let Some(file) = &offset.sf.src { |
| 127 | + assert!( |
| 128 | + file.len() >= offset.pos.to_usize(), |
| 129 | + "end of span is out of bounds" |
| 130 | + ); |
| 131 | + assert!( |
| 132 | + file.is_char_boundary(offset.pos.to_usize()), |
| 133 | + "end of span not on char boundary" |
| 134 | + ); |
| 135 | + } |
| 136 | + } |
| 137 | + }); |
| 138 | + } |
| 139 | + |
106 | 140 | if lo > hi {
|
107 | 141 | std::mem::swap(&mut lo, &mut hi);
|
108 | 142 | }
|
|
0 commit comments