diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 1420871b0256e..621580793ebe8 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1565,10 +1565,10 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { src_hash, start_pos, end_pos, - mut lines, - mut multibyte_chars, - mut non_narrow_chars, - mut normalized_pos, + lines, + multibyte_chars, + non_narrow_chars, + normalized_pos, name_hash, .. } = source_file_to_import; @@ -1605,24 +1605,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let source_length = (end_pos - start_pos).to_usize(); - // Translate line-start positions and multibyte character - // position into frame of reference local to file. - // `SourceMap::new_imported_source_file()` will then translate those - // coordinates to their new global frame of reference when the - // offset of the SourceFile is known. - for pos in &mut lines { - *pos = *pos - start_pos; - } - for mbc in &mut multibyte_chars { - mbc.pos = mbc.pos - start_pos; - } - for swc in &mut non_narrow_chars { - *swc = *swc - start_pos; - } - for np in &mut normalized_pos { - np.pos = np.pos - start_pos; - } - let local_version = sess.source_map().new_imported_source_file( name, src_hash, diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 8737e45487e90..f44eac63cef10 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1270,7 +1270,9 @@ impl Encodable for SourceFile { // the lines list is sorted and individual lines are // probably not that long. Because of that we can store lines // as a difference list, using as little space as possible - // for the differences. + // for the differences. But note that the first line is + // always encoded as a `BytePos` because its position is + // often much larger than any of the differences. let max_line_length = if lines.len() == 1 { 0 } else { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 020ae3ad0c78c..d60b4d3d021e8 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -345,20 +345,27 @@ impl SourceMap { let end_pos = Pos::from_usize(start_pos + source_len); let start_pos = Pos::from_usize(start_pos); + // Translate these positions into the new global frame of reference, + // now that the offset of the SourceFile is known. + // + // These are all unsigned values. `original_start_pos` may be larger or + // smaller than `start_pos`, but `pos` is always larger than both. + // Therefore, `(pos - original_start_pos) + start_pos` won't overflow + // but `start_pos - original_start_pos` might. So we use the former + // form rather than pre-computing the offset into a local variable. The + // compiler backend can optimize away the repeated computations in a + // way that won't trigger overflow checks. for pos in &mut file_local_lines { - *pos = *pos + start_pos; + *pos = (*pos - original_start_pos) + start_pos; } - for mbc in &mut file_local_multibyte_chars { - mbc.pos = mbc.pos + start_pos; + mbc.pos = (mbc.pos - original_start_pos) + start_pos; } - for swc in &mut file_local_non_narrow_chars { - *swc = *swc + start_pos; + *swc = (*swc - original_start_pos) + start_pos; } - for nc in &mut file_local_normalized_pos { - nc.pos = nc.pos + start_pos; + nc.pos = (nc.pos - original_start_pos) + start_pos; } let source_file = Lrc::new(SourceFile {