Skip to content

Commit 9c34740

Browse files
authored
Rollup merge of rust-lang#71048 - arlosi:normalize_ext_src, r=eddyb
Normalize source when loading external foreign source into SourceMap The compiler normalizes source when reading files initially (removes BOMs, etc), but not when loading external sources. This leads to the external source matching according to the `src_hash`, but differing internally because it was not normalized. Fixes rust-lang#70874.
2 parents d608dfc + f41aa16 commit 9c34740

File tree

2 files changed

+59
-1
lines changed

2 files changed

+59
-1
lines changed

src/librustc_span/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1192,8 +1192,10 @@ impl SourceFile {
11921192
kind: src_kind @ ExternalSourceKind::AbsentOk, ..
11931193
} = &mut *external_src
11941194
{
1195-
if let Some(src) = src {
1195+
if let Some(mut src) = src {
1196+
// The src_hash needs to be computed on the pre-normalized src.
11961197
if self.src_hash.matches(&src) {
1198+
normalize_src(&mut src, BytePos::from_usize(0));
11971199
*src_kind = ExternalSourceKind::Present(Lrc::new(src));
11981200
return true;
11991201
}

src/librustc_span/source_map/tests.rs

+56
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,62 @@ fn span_merging_fail() {
168168
assert!(sm.merge_spans(span1, span2).is_none());
169169
}
170170

171+
/// Tests loading an external source file that requires normalization.
172+
#[test]
173+
fn t10() {
174+
let sm = SourceMap::new(FilePathMapping::empty());
175+
let unnormalized = "first line.\r\nsecond line";
176+
let normalized = "first line.\nsecond line";
177+
178+
let src_file = sm.new_source_file(PathBuf::from("blork.rs").into(), unnormalized.to_string());
179+
180+
assert_eq!(src_file.src.as_ref().unwrap().as_ref(), normalized);
181+
assert!(
182+
src_file.src_hash.matches(unnormalized),
183+
"src_hash should use the source before normalization"
184+
);
185+
186+
let SourceFile {
187+
name,
188+
name_was_remapped,
189+
src_hash,
190+
start_pos,
191+
end_pos,
192+
lines,
193+
multibyte_chars,
194+
non_narrow_chars,
195+
normalized_pos,
196+
name_hash,
197+
..
198+
} = (*src_file).clone();
199+
200+
let imported_src_file = sm.new_imported_source_file(
201+
name,
202+
name_was_remapped,
203+
src_hash,
204+
name_hash,
205+
(end_pos - start_pos).to_usize(),
206+
CrateNum::new(0),
207+
lines,
208+
multibyte_chars,
209+
non_narrow_chars,
210+
normalized_pos,
211+
start_pos,
212+
end_pos,
213+
);
214+
215+
assert!(
216+
imported_src_file.external_src.borrow().get_source().is_none(),
217+
"imported source file should not have source yet"
218+
);
219+
imported_src_file.add_external_src(|| Some(unnormalized.to_string()));
220+
assert_eq!(
221+
imported_src_file.external_src.borrow().get_source().unwrap().as_ref(),
222+
normalized,
223+
"imported source file should be normalized"
224+
);
225+
}
226+
171227
/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
172228
trait SourceMapExtension {
173229
fn span_substr(

0 commit comments

Comments
 (0)