Skip to content

Commit c3fd5d0

Browse files
committed
Auto merge of #48904 - Zoxc:code-and-file-maps, r=michaelwoerister
Make CodeMap and FileMap thread-safe r? @michaelwoerister
2 parents 8cabda4 + 65b4990 commit c3fd5d0

File tree

8 files changed

+112
-99
lines changed

8 files changed

+112
-99
lines changed

src/librustc/ich/impls_syntax.rs

+18-15
Original file line numberDiff line numberDiff line change
@@ -417,24 +417,27 @@ impl<'a> HashStable<StableHashingContext<'a>> for FileMap {
417417
src_hash.hash_stable(hcx, hasher);
418418

419419
// We only hash the relative position within this filemap
420-
let lines = lines.borrow();
421-
lines.len().hash_stable(hcx, hasher);
422-
for &line in lines.iter() {
423-
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
424-
}
420+
lines.with_lock(|lines| {
421+
lines.len().hash_stable(hcx, hasher);
422+
for &line in lines.iter() {
423+
stable_byte_pos(line, start_pos).hash_stable(hcx, hasher);
424+
}
425+
});
425426

426427
// We only hash the relative position within this filemap
427-
let multibyte_chars = multibyte_chars.borrow();
428-
multibyte_chars.len().hash_stable(hcx, hasher);
429-
for &char_pos in multibyte_chars.iter() {
430-
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
431-
}
428+
multibyte_chars.with_lock(|multibyte_chars| {
429+
multibyte_chars.len().hash_stable(hcx, hasher);
430+
for &char_pos in multibyte_chars.iter() {
431+
stable_multibyte_char(char_pos, start_pos).hash_stable(hcx, hasher);
432+
}
433+
});
432434

433-
let non_narrow_chars = non_narrow_chars.borrow();
434-
non_narrow_chars.len().hash_stable(hcx, hasher);
435-
for &char_pos in non_narrow_chars.iter() {
436-
stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
437-
}
435+
non_narrow_chars.with_lock(|non_narrow_chars| {
436+
non_narrow_chars.len().hash_stable(hcx, hasher);
437+
for &char_pos in non_narrow_chars.iter() {
438+
stable_non_narrow_char(char_pos, start_pos).hash_stable(hcx, hasher);
439+
}
440+
});
438441
}
439442
}
440443

src/librustc_driver/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ fn get_trans_sysroot(backend_name: &str) -> fn() -> Box<TransCrate> {
444444
// The FileLoader provides a way to load files from sources other than the file system.
445445
pub fn run_compiler<'a>(args: &[String],
446446
callbacks: &mut CompilerCalls<'a>,
447-
file_loader: Option<Box<FileLoader + 'static>>,
447+
file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
448448
emitter_dest: Option<Box<Write + Send>>)
449449
-> (CompileResult, Option<Session>)
450450
{
@@ -455,7 +455,7 @@ pub fn run_compiler<'a>(args: &[String],
455455

456456
fn run_compiler_impl<'a>(args: &[String],
457457
callbacks: &mut CompilerCalls<'a>,
458-
file_loader: Option<Box<FileLoader + 'static>>,
458+
file_loader: Option<Box<FileLoader + Send + Sync + 'static>>,
459459
emitter_dest: Option<Box<Write + Send>>)
460460
-> (CompileResult, Option<Session>)
461461
{

src/librustc_errors/emitter.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use self::Destination::*;
1212

1313
use syntax_pos::{DUMMY_SP, FileMap, Span, MultiSpan};
1414

15-
use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapper, DiagnosticId};
15+
use {Level, CodeSuggestion, DiagnosticBuilder, SubDiagnostic, CodeMapperDyn, DiagnosticId};
1616
use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style};
1717
use styled_buffer::StyledBuffer;
1818

@@ -120,7 +120,7 @@ impl ColorConfig {
120120

121121
pub struct EmitterWriter {
122122
dst: Destination,
123-
cm: Option<Lrc<CodeMapper>>,
123+
cm: Option<Lrc<CodeMapperDyn>>,
124124
short_message: bool,
125125
teach: bool,
126126
ui_testing: bool,
@@ -134,7 +134,7 @@ struct FileWithAnnotatedLines {
134134

135135
impl EmitterWriter {
136136
pub fn stderr(color_config: ColorConfig,
137-
code_map: Option<Lrc<CodeMapper>>,
137+
code_map: Option<Lrc<CodeMapperDyn>>,
138138
short_message: bool,
139139
teach: bool)
140140
-> EmitterWriter {
@@ -149,7 +149,7 @@ impl EmitterWriter {
149149
}
150150

151151
pub fn new(dst: Box<Write + Send>,
152-
code_map: Option<Lrc<CodeMapper>>,
152+
code_map: Option<Lrc<CodeMapperDyn>>,
153153
short_message: bool,
154154
teach: bool)
155155
-> EmitterWriter {
@@ -1195,8 +1195,6 @@ impl EmitterWriter {
11951195
level: &Level,
11961196
max_line_num_len: usize)
11971197
-> io::Result<()> {
1198-
use std::borrow::Borrow;
1199-
12001198
if let Some(ref cm) = self.cm {
12011199
let mut buffer = StyledBuffer::new();
12021200

@@ -1213,7 +1211,7 @@ impl EmitterWriter {
12131211
Some(Style::HeaderMsg));
12141212

12151213
// Render the replacements for each suggestion
1216-
let suggestions = suggestion.splice_lines(cm.borrow());
1214+
let suggestions = suggestion.splice_lines(&**cm);
12171215

12181216
let mut row_num = 2;
12191217
for &(ref complete, ref parts) in suggestions.iter().take(MAX_SUGGESTIONS) {

src/librustc_errors/lib.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ use self::Level::*;
3636

3737
use emitter::{Emitter, EmitterWriter};
3838

39-
use rustc_data_structures::sync::Lrc;
39+
use rustc_data_structures::sync::{self, Lrc};
4040
use rustc_data_structures::fx::FxHashSet;
4141
use rustc_data_structures::stable_hasher::StableHasher;
4242

@@ -106,6 +106,8 @@ pub struct SubstitutionPart {
106106
pub snippet: String,
107107
}
108108

109+
pub type CodeMapperDyn = CodeMapper + sync::Send + sync::Sync;
110+
109111
pub trait CodeMapper {
110112
fn lookup_char_pos(&self, pos: BytePos) -> Loc;
111113
fn span_to_lines(&self, sp: Span) -> FileLinesResult;
@@ -119,7 +121,8 @@ pub trait CodeMapper {
119121

120122
impl CodeSuggestion {
121123
/// Returns the assembled code suggestions and whether they should be shown with an underline.
122-
pub fn splice_lines(&self, cm: &CodeMapper) -> Vec<(String, Vec<SubstitutionPart>)> {
124+
pub fn splice_lines(&self, cm: &CodeMapperDyn)
125+
-> Vec<(String, Vec<SubstitutionPart>)> {
123126
use syntax_pos::{CharPos, Loc, Pos};
124127

125128
fn push_trailing(buf: &mut String,
@@ -290,7 +293,7 @@ impl Handler {
290293
pub fn with_tty_emitter(color_config: ColorConfig,
291294
can_emit_warnings: bool,
292295
treat_err_as_bug: bool,
293-
cm: Option<Lrc<CodeMapper>>)
296+
cm: Option<Lrc<CodeMapperDyn>>)
294297
-> Handler {
295298
Handler::with_tty_emitter_and_flags(
296299
color_config,
@@ -303,7 +306,7 @@ impl Handler {
303306
}
304307

305308
pub fn with_tty_emitter_and_flags(color_config: ColorConfig,
306-
cm: Option<Lrc<CodeMapper>>,
309+
cm: Option<Lrc<CodeMapperDyn>>,
307310
flags: HandlerFlags)
308311
-> Handler {
309312
let emitter = Box::new(EmitterWriter::stderr(color_config, cm, false, false));

src/libsyntax/codemap.rs

+40-38
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ pub use self::ExpnFormat::*;
2424

2525
use rustc_data_structures::fx::FxHashMap;
2626
use rustc_data_structures::stable_hasher::StableHasher;
27-
use rustc_data_structures::sync::Lrc;
28-
use std::cell::{RefCell, Ref};
27+
use rustc_data_structures::sync::{Lrc, Lock, LockGuard};
2928
use std::cmp;
3029
use std::hash::Hash;
3130
use std::path::{Path, PathBuf};
@@ -125,13 +124,17 @@ impl StableFilemapId {
125124
// CodeMap
126125
//
127126

127+
pub(super) struct CodeMapFiles {
128+
pub(super) file_maps: Vec<Lrc<FileMap>>,
129+
stable_id_to_filemap: FxHashMap<StableFilemapId, Lrc<FileMap>>
130+
}
131+
128132
pub struct CodeMap {
129-
pub(super) files: RefCell<Vec<Lrc<FileMap>>>,
130-
file_loader: Box<FileLoader>,
133+
pub(super) files: Lock<CodeMapFiles>,
134+
file_loader: Box<FileLoader + Sync + Send>,
131135
// This is used to apply the file path remapping as specified via
132136
// --remap-path-prefix to all FileMaps allocated within this CodeMap.
133137
path_mapping: FilePathMapping,
134-
stable_id_to_filemap: RefCell<FxHashMap<StableFilemapId, Lrc<FileMap>>>,
135138
/// In case we are in a doctest, replace all file names with the PathBuf,
136139
/// and add the given offsets to the line info
137140
doctest_offset: Option<(FileName, isize)>,
@@ -140,10 +143,12 @@ pub struct CodeMap {
140143
impl CodeMap {
141144
pub fn new(path_mapping: FilePathMapping) -> CodeMap {
142145
CodeMap {
143-
files: RefCell::new(Vec::new()),
146+
files: Lock::new(CodeMapFiles {
147+
file_maps: Vec::new(),
148+
stable_id_to_filemap: FxHashMap(),
149+
}),
144150
file_loader: Box::new(RealFileLoader),
145151
path_mapping,
146-
stable_id_to_filemap: RefCell::new(FxHashMap()),
147152
doctest_offset: None,
148153
}
149154
}
@@ -157,14 +162,16 @@ impl CodeMap {
157162

158163
}
159164

160-
pub fn with_file_loader(file_loader: Box<FileLoader>,
165+
pub fn with_file_loader(file_loader: Box<FileLoader + Sync + Send>,
161166
path_mapping: FilePathMapping)
162167
-> CodeMap {
163168
CodeMap {
164-
files: RefCell::new(Vec::new()),
165-
file_loader,
169+
files: Lock::new(CodeMapFiles {
170+
file_maps: Vec::new(),
171+
stable_id_to_filemap: FxHashMap(),
172+
}),
173+
file_loader: file_loader,
166174
path_mapping,
167-
stable_id_to_filemap: RefCell::new(FxHashMap()),
168175
doctest_offset: None,
169176
}
170177
}
@@ -187,17 +194,16 @@ impl CodeMap {
187194
Ok(self.new_filemap(filename, src))
188195
}
189196

190-
pub fn files(&self) -> Ref<Vec<Lrc<FileMap>>> {
191-
self.files.borrow()
197+
pub fn files(&self) -> LockGuard<Vec<Lrc<FileMap>>> {
198+
LockGuard::map(self.files.borrow(), |files| &mut files.file_maps)
192199
}
193200

194201
pub fn filemap_by_stable_id(&self, stable_id: StableFilemapId) -> Option<Lrc<FileMap>> {
195-
self.stable_id_to_filemap.borrow().get(&stable_id).map(|fm| fm.clone())
202+
self.files.borrow().stable_id_to_filemap.get(&stable_id).map(|fm| fm.clone())
196203
}
197204

198205
fn next_start_pos(&self) -> usize {
199-
let files = self.files.borrow();
200-
match files.last() {
206+
match self.files.borrow().file_maps.last() {
201207
None => 0,
202208
// Add one so there is some space between files. This lets us distinguish
203209
// positions in the codemap, even in the presence of zero-length files.
@@ -207,9 +213,9 @@ impl CodeMap {
207213

208214
/// Creates a new filemap without setting its line information. If you don't
209215
/// intend to set the line information yourself, you should use new_filemap_and_lines.
216+
/// This does not ensure that only one FileMap exists per file name.
210217
pub fn new_filemap(&self, filename: FileName, src: String) -> Lrc<FileMap> {
211218
let start_pos = self.next_start_pos();
212-
let mut files = self.files.borrow_mut();
213219

214220
// The path is used to determine the directory for loading submodules and
215221
// include files, so it must be before remapping.
@@ -233,16 +239,16 @@ impl CodeMap {
233239
Pos::from_usize(start_pos),
234240
));
235241

236-
files.push(filemap.clone());
242+
let mut files = self.files.borrow_mut();
237243

238-
self.stable_id_to_filemap
239-
.borrow_mut()
240-
.insert(StableFilemapId::new(&filemap), filemap.clone());
244+
files.file_maps.push(filemap.clone());
245+
files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
241246

242247
filemap
243248
}
244249

245250
/// Creates a new filemap and sets its line information.
251+
/// This does not ensure that only one FileMap exists per file name.
246252
pub fn new_filemap_and_lines(&self, filename: &Path, src: &str) -> Lrc<FileMap> {
247253
let fm = self.new_filemap(filename.to_owned().into(), src.to_owned());
248254
let mut byte_pos: u32 = fm.start_pos.0;
@@ -273,7 +279,6 @@ impl CodeMap {
273279
mut file_local_non_narrow_chars: Vec<NonNarrowChar>)
274280
-> Lrc<FileMap> {
275281
let start_pos = self.next_start_pos();
276-
let mut files = self.files.borrow_mut();
277282

278283
let end_pos = Pos::from_usize(start_pos + source_len);
279284
let start_pos = Pos::from_usize(start_pos);
@@ -297,20 +302,19 @@ impl CodeMap {
297302
crate_of_origin,
298303
src: None,
299304
src_hash,
300-
external_src: RefCell::new(ExternalSource::AbsentOk),
305+
external_src: Lock::new(ExternalSource::AbsentOk),
301306
start_pos,
302307
end_pos,
303-
lines: RefCell::new(file_local_lines),
304-
multibyte_chars: RefCell::new(file_local_multibyte_chars),
305-
non_narrow_chars: RefCell::new(file_local_non_narrow_chars),
308+
lines: Lock::new(file_local_lines),
309+
multibyte_chars: Lock::new(file_local_multibyte_chars),
310+
non_narrow_chars: Lock::new(file_local_non_narrow_chars),
306311
name_hash,
307312
});
308313

309-
files.push(filemap.clone());
314+
let mut files = self.files.borrow_mut();
310315

311-
self.stable_id_to_filemap
312-
.borrow_mut()
313-
.insert(StableFilemapId::new(&filemap), filemap.clone());
316+
files.file_maps.push(filemap.clone());
317+
files.stable_id_to_filemap.insert(StableFilemapId::new(&filemap), filemap.clone());
314318

315319
filemap
316320
}
@@ -401,8 +405,7 @@ impl CodeMap {
401405
pub fn lookup_line(&self, pos: BytePos) -> Result<FileMapAndLine, Lrc<FileMap>> {
402406
let idx = self.lookup_filemap_idx(pos);
403407

404-
let files = self.files.borrow();
405-
let f = (*files)[idx].clone();
408+
let f = (*self.files.borrow().file_maps)[idx].clone();
406409

407410
match f.lookup_line(pos) {
408411
Some(line) => Ok(FileMapAndLine { fm: f, line: line }),
@@ -456,7 +459,7 @@ impl CodeMap {
456459
}
457460

458461
pub fn span_to_string(&self, sp: Span) -> String {
459-
if self.files.borrow().is_empty() && sp.source_equal(&DUMMY_SP) {
462+
if self.files.borrow().file_maps.is_empty() && sp.source_equal(&DUMMY_SP) {
460463
return "no-location".to_string();
461464
}
462465

@@ -799,7 +802,7 @@ impl CodeMap {
799802
}
800803

801804
pub fn get_filemap(&self, filename: &FileName) -> Option<Lrc<FileMap>> {
802-
for fm in self.files.borrow().iter() {
805+
for fm in self.files.borrow().file_maps.iter() {
803806
if *filename == fm.name {
804807
return Some(fm.clone());
805808
}
@@ -810,16 +813,15 @@ impl CodeMap {
810813
/// For a global BytePos compute the local offset within the containing FileMap
811814
pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
812815
let idx = self.lookup_filemap_idx(bpos);
813-
let fm = (*self.files.borrow())[idx].clone();
816+
let fm = (*self.files.borrow().file_maps)[idx].clone();
814817
let offset = bpos - fm.start_pos;
815818
FileMapAndBytePos {fm: fm, pos: offset}
816819
}
817820

818821
/// Converts an absolute BytePos to a CharPos relative to the filemap.
819822
pub fn bytepos_to_file_charpos(&self, bpos: BytePos) -> CharPos {
820823
let idx = self.lookup_filemap_idx(bpos);
821-
let files = self.files.borrow();
822-
let map = &(*files)[idx];
824+
let map = &(*self.files.borrow().file_maps)[idx];
823825

824826
// The number of extra bytes due to multibyte chars in the FileMap
825827
let mut total_extra_bytes = 0;
@@ -845,7 +847,7 @@ impl CodeMap {
845847
// Return the index of the filemap (in self.files) which contains pos.
846848
pub fn lookup_filemap_idx(&self, pos: BytePos) -> usize {
847849
let files = self.files.borrow();
848-
let files = &*files;
850+
let files = &files.file_maps;
849851
let count = files.len();
850852

851853
// Binary search for the filemap.

src/libsyntax/json.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use errors::{DiagnosticBuilder, SubDiagnostic, CodeSuggestion, CodeMapper};
2626
use errors::DiagnosticId;
2727
use errors::emitter::{Emitter, EmitterWriter};
2828

29-
use rustc_data_structures::sync::Lrc;
29+
use rustc_data_structures::sync::{self, Lrc};
3030
use std::io::{self, Write};
3131
use std::vec;
3232
use std::sync::{Arc, Mutex};
@@ -36,7 +36,7 @@ use rustc_serialize::json::{as_json, as_pretty_json};
3636
pub struct JsonEmitter {
3737
dst: Box<Write + Send>,
3838
registry: Option<Registry>,
39-
cm: Lrc<CodeMapper + 'static>,
39+
cm: Lrc<CodeMapper + sync::Send + sync::Sync>,
4040
pretty: bool,
4141
/// Whether "approximate suggestions" are enabled in the config
4242
approximate_suggestions: bool,

0 commit comments

Comments
 (0)