From 3d2cff0c94a8a882eeca464ef638b0c912cc4f97 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 13:39:39 +0200 Subject: Added source hashes to FileMap We can use these to perform lazy loading of source files belonging to external crates. That way we will be able to show the source code of external spans that have been translated. --- src/libsyntax/codemap.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/libsyntax') diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 830a457df74..0935ec1b01c 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -27,9 +27,12 @@ use std::rc::Rc; use std::env; use std::fs; +use std::hash::Hasher; use std::io::{self, Read}; use errors::CodeMapper; +use rustc_data_structures::stable_hasher::StableHasher; + /// Return the span itself if it doesn't come from a macro expansion, /// otherwise return the call site span up to the `enclosing_sp` by /// following the `expn_info` chain. @@ -171,11 +174,16 @@ impl CodeMap { let (filename, was_remapped) = self.path_mapping.map_prefix(filename); + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + let src_hash = hasher.finish(); + let filemap = Rc::new(FileMap { name: filename, name_was_remapped: was_remapped, crate_of_origin: 0, src: Some(Rc::new(src)), + src_hash: src_hash, start_pos: Pos::from_usize(start_pos), end_pos: Pos::from_usize(end_pos), lines: RefCell::new(Vec::new()), @@ -210,6 +218,7 @@ impl CodeMap { filename: FileName, name_was_remapped: bool, crate_of_origin: u32, + src_hash: u128, source_len: usize, mut file_local_lines: Vec, mut file_local_multibyte_chars: Vec) @@ -233,6 +242,7 @@ impl CodeMap { name_was_remapped: name_was_remapped, crate_of_origin: crate_of_origin, src: None, + src_hash: src_hash, start_pos: start_pos, end_pos: end_pos, lines: RefCell::new(file_local_lines), -- cgit 1.4.1-3-g733a5 From dd8f7cd126403955295c8b0cdbccc5ca5cbef763 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 16:09:51 +0200 Subject: Moved FileMap construction to it's own constructor. The rationale is that BOM stripping is needed for lazy source loading for external crates, and duplication can be avoided by moving the corresponding functionality to libsyntax_pos. --- src/Cargo.lock | 1 + src/libsyntax/codemap.rs | 30 +++--------------------------- src/libsyntax_pos/Cargo.toml | 1 + src/libsyntax_pos/lib.rs | 37 +++++++++++++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 27 deletions(-) (limited to 'src/libsyntax') diff --git a/src/Cargo.lock b/src/Cargo.lock index 8bf4b6ad3e0..3508e8c070b 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -1682,6 +1682,7 @@ dependencies = [ name = "syntax_pos" version = "0.0.0" dependencies = [ + "rustc_data_structures 0.0.0", "serialize 0.0.0", ] diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 0935ec1b01c..442b92be1cb 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -27,12 +27,9 @@ use std::rc::Rc; use std::env; use std::fs; -use std::hash::Hasher; use std::io::{self, Read}; use errors::CodeMapper; -use rustc_data_structures::stable_hasher::StableHasher; - /// Return the span itself if it doesn't come from a macro expansion, /// otherwise return the call site span up to the `enclosing_sp` by /// following the `expn_info` chain. @@ -161,34 +158,13 @@ impl CodeMap { /// Creates a new filemap without setting its line information. If you don't /// intend to set the line information yourself, you should use new_filemap_and_lines. - pub fn new_filemap(&self, filename: FileName, mut src: String) -> Rc { + pub fn new_filemap(&self, filename: FileName, src: String) -> Rc { let start_pos = self.next_start_pos(); let mut files = self.files.borrow_mut(); - // Remove utf-8 BOM if any. - if src.starts_with("\u{feff}") { - src.drain(..3); - } - - let end_pos = start_pos + src.len(); - let (filename, was_remapped) = self.path_mapping.map_prefix(filename); - - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - let src_hash = hasher.finish(); - - let filemap = Rc::new(FileMap { - name: filename, - name_was_remapped: was_remapped, - crate_of_origin: 0, - src: Some(Rc::new(src)), - src_hash: src_hash, - start_pos: Pos::from_usize(start_pos), - end_pos: Pos::from_usize(end_pos), - lines: RefCell::new(Vec::new()), - multibyte_chars: RefCell::new(Vec::new()), - }); + let filemap = + Rc::new(FileMap::new(filename, was_remapped, src, Pos::from_usize(start_pos))); files.push(filemap.clone()); diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index 760aaa8a957..dd8129bab51 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -10,3 +10,4 @@ crate-type = ["dylib"] [dependencies] serialize = { path = "../libserialize" } +rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index caea1497181..75ce8b675f3 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -38,6 +38,11 @@ use std::ops::{Add, Sub}; use std::rc::Rc; use std::cmp; use std::fmt; +use std::hash::Hasher; + +use rustc_data_structures::stable_hasher::StableHasher; + +extern crate rustc_data_structures; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -522,6 +527,31 @@ impl fmt::Debug for FileMap { } impl FileMap { + pub fn new(name: FileName, + name_was_remapped: bool, + mut src: String, + start_pos: BytePos) -> FileMap { + remove_bom(&mut src); + + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + let src_hash = hasher.finish(); + + let end_pos = start_pos.to_usize() + src.len(); + + FileMap { + name: name, + name_was_remapped: name_was_remapped, + crate_of_origin: 0, + src: Some(Rc::new(src)), + src_hash: src_hash, + start_pos: start_pos, + end_pos: Pos::from_usize(end_pos), + lines: RefCell::new(Vec::new()), + multibyte_chars: RefCell::new(Vec::new()), + } + } + /// EFFECT: register a start-of-line offset in the /// table of line-beginnings. /// UNCHECKED INVARIANT: these offsets must be added in the right @@ -621,6 +651,13 @@ impl FileMap { } } +/// Remove utf-8 BOM if any. +fn remove_bom(src: &mut String) { + if src.starts_with("\u{feff}") { + src.drain(..3); + } +} + // _____________________________________________________________________________ // Pos, BytePos, CharPos // -- cgit 1.4.1-3-g733a5 From c2c31b2db33e0d0b5356a0c9e032269034cdc70a Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sat, 10 Jun 2017 21:08:32 +0200 Subject: Added external crates' sources to FileMap. They are now handled in their own member to prevent mutating access to the `src` member. This way, we can safely load external sources, while keeping the mutation of local source strings off-limits. --- src/librustc/ich/impls_syntax.rs | 1 + src/librustc_errors/lib.rs | 1 + src/libsyntax/codemap.rs | 20 ++++++++++++++++++++ src/libsyntax_pos/lib.rs | 13 +++++++++++++ 4 files changed, 35 insertions(+) (limited to 'src/libsyntax') diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index cba5ca148d0..b9cc3b5fb93 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -337,6 +337,7 @@ impl<'a, 'gcx, 'tcx> HashStable> for FileMa // Do not hash the source as it is not encoded src: _, src_hash, + external_src: _, start_pos, end_pos: _, ref lines, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 8d5e9e776ed..545a485732e 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -103,6 +103,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; + fn load_source_for_filemap(&mut self, file: FileName) -> bool; } impl CodeSuggestion { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 442b92be1cb..9779a678845 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -219,6 +219,7 @@ impl CodeMap { crate_of_origin: crate_of_origin, src: None, src_hash: src_hash, + external_src: RefCell::new(ExternalSource::AbsentOk), start_pos: start_pos, end_pos: end_pos, lines: RefCell::new(file_local_lines), @@ -558,6 +559,25 @@ impl CodeMapper for CodeMap { } sp } + fn load_source_for_filemap(&mut self, filename: FileName) -> bool { + let file_map = if let Some(fm) = self.get_filemap(&filename) { + fm + } else { + return false; + }; + + if *file_map.external_src.borrow() == ExternalSource::AbsentOk { + let mut external_src = file_map.external_src.borrow_mut(); + if let Ok(src) = self.file_loader.read_file(Path::new(&filename)) { + *external_src = ExternalSource::Present(src); + return true; + } else { + *external_src = ExternalSource::AbsentErr; + } + } + + false + } } #[derive(Clone)] diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 75ce8b675f3..d6adf45e68a 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -374,6 +374,14 @@ pub struct MultiByteChar { pub bytes: usize, } +#[derive(PartialEq, Eq, Clone)] +pub enum ExternalSource { + Present(String), + AbsentOk, + AbsentErr, + Unneeded, +} + /// A single source in the CodeMap. #[derive(Clone)] pub struct FileMap { @@ -389,6 +397,9 @@ pub struct FileMap { pub src: Option>, /// The source code's hash pub src_hash: u128, + /// The external source code (used for external crates, which will have a `None` + /// value as `self.src`. + pub external_src: RefCell, /// The start position of this source in the CodeMap pub start_pos: BytePos, /// The end position of this source in the CodeMap @@ -513,6 +524,7 @@ impl Decodable for FileMap { end_pos: end_pos, src: None, src_hash: src_hash, + external_src: RefCell::new(ExternalSource::AbsentOk), lines: RefCell::new(lines), multibyte_chars: RefCell::new(multibyte_chars) }) @@ -545,6 +557,7 @@ impl FileMap { crate_of_origin: 0, src: Some(Rc::new(src)), src_hash: src_hash, + external_src: RefCell::new(ExternalSource::Unneeded), start_pos: start_pos, end_pos: Pos::from_usize(end_pos), lines: RefCell::new(Vec::new()), -- cgit 1.4.1-3-g733a5 From c04aa4ed0ce61d257ab10b4dbdaa64fa5cad37b1 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 10:19:46 +0200 Subject: Improved lazy external source loading and inserted calls. --- src/librustc_errors/emitter.rs | 5 ++++- src/librustc_errors/lib.rs | 2 +- src/libsyntax/codemap.rs | 2 +- src/libsyntax_pos/lib.rs | 23 ++++++++++++++++++++++- 4 files changed, 28 insertions(+), 4 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index f820ea4c5e1..fc4d39ac482 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -131,7 +131,7 @@ impl EmitterWriter { } } - fn preprocess_annotations(&self, msp: &MultiSpan) -> Vec { + fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec { fn add_annotation_to_file(file_vec: &mut Vec, file: Rc, line_index: usize, @@ -175,6 +175,9 @@ impl EmitterWriter { if span_label.span == DUMMY_SP { continue; } + + cm.load_source_for_filemap(cm.span_to_filename(span_label.span)); + let lo = cm.lookup_char_pos(span_label.span.lo); let mut hi = cm.lookup_char_pos(span_label.span.hi); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 545a485732e..a2a20424d6b 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -103,7 +103,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; - fn load_source_for_filemap(&mut self, file: FileName) -> bool; + fn load_source_for_filemap(&self, file: FileName) -> bool; } impl CodeSuggestion { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 9779a678845..fb78b18b898 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -559,7 +559,7 @@ impl CodeMapper for CodeMap { } sp } - fn load_source_for_filemap(&mut self, filename: FileName) -> bool { + fn load_source_for_filemap(&self, filename: FileName) -> bool { let file_map = if let Some(fm) = self.get_filemap(&filename) { fm } else { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d6adf45e68a..9e545b81390 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -374,14 +374,35 @@ pub struct MultiByteChar { pub bytes: usize, } +/// The state of the lazy external source loading mechanism of a FileMap. #[derive(PartialEq, Eq, Clone)] pub enum ExternalSource { + /// The external source has been loaded already. Present(String), + /// No attempt has been made to load the external source. AbsentOk, + /// A failed attempt has been made to load the external source. AbsentErr, + /// No external source has to be loaded, since the FileMap represents a local crate. Unneeded, } +impl ExternalSource { + pub fn is_absent(&self) -> bool { + match *self { + ExternalSource::Present(_) => false, + _ => true, + } + } + + pub fn get_source(&self) -> Option<&str> { + match *self { + ExternalSource::Present(ref src) => Some(src), + _ => None, + } + } +} + /// A single source in the CodeMap. #[derive(Clone)] pub struct FileMap { @@ -620,7 +641,7 @@ impl FileMap { } pub fn is_imported(&self) -> bool { - self.src.is_none() + self.src.is_none() // TODO: change to something more sensible } pub fn byte_length(&self) -> u32 { -- cgit 1.4.1-3-g733a5 From a5b8851e220d7a80222ea04d242603dd3392d17b Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 13:31:40 +0200 Subject: Added consumption logic for external sources in FileMap We now fetch source lines from the `external_src` member as a secondary fallback if no regular source is present, that is, if the file map belongs to an external crate and the source has been fetched from disk. --- src/librustc_errors/emitter.rs | 6 ++++-- src/librustc_errors/lib.rs | 11 +++++----- src/libsyntax/json.rs | 2 +- src/libsyntax_pos/lib.rs | 46 +++++++++++++++++++++++++----------------- 4 files changed, 39 insertions(+), 26 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index fc4d39ac482..2099725c48a 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -17,6 +17,7 @@ use RenderSpan::*; use snippet::{Annotation, AnnotationType, Line, MultilineAnnotation, StyledString, Style}; use styled_buffer::StyledBuffer; +use std::borrow::Cow; use std::io::prelude::*; use std::io; use std::rc::Rc; @@ -911,7 +912,8 @@ impl EmitterWriter { // Print out the annotate source lines that correspond with the error for annotated_file in annotated_files { // we can't annotate anything if the source is unavailable. - if annotated_file.file.src.is_none() { + if annotated_file.file.src.is_none() + && annotated_file.file.external_src.borrow().is_absent() { continue; } @@ -1012,7 +1014,7 @@ impl EmitterWriter { } else if line_idx_delta == 2 { let unannotated_line = annotated_file.file .get_line(annotated_file.lines[line_idx].line_index) - .unwrap_or(""); + .unwrap_or_else(|| Cow::from("")); let last_buffer_line_num = buffer.num_lines(); diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index a2a20424d6b..26ecbe724f8 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -37,6 +37,7 @@ use self::Level::*; use emitter::{Emitter, EmitterWriter}; +use std::borrow::Cow; use std::cell::{RefCell, Cell}; use std::{error, fmt}; use std::rc::Rc; @@ -122,7 +123,7 @@ impl CodeSuggestion { use syntax_pos::{CharPos, Loc, Pos}; fn push_trailing(buf: &mut String, - line_opt: Option<&str>, + line_opt: Option<&Cow>, lo: &Loc, hi_opt: Option<&Loc>) { let (lo, hi_opt) = (lo.col.to_usize(), hi_opt.map(|hi| hi.col.to_usize())); @@ -184,13 +185,13 @@ impl CodeSuggestion { let cur_lo = cm.lookup_char_pos(sp.lo); for (buf, substitute) in bufs.iter_mut().zip(substitutes) { if prev_hi.line == cur_lo.line { - push_trailing(buf, prev_line, &prev_hi, Some(&cur_lo)); + push_trailing(buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); } else { - push_trailing(buf, prev_line, &prev_hi, None); + push_trailing(buf, prev_line.as_ref(), &prev_hi, None); // push lines between the previous and current span (if any) for idx in prev_hi.line..(cur_lo.line - 1) { if let Some(line) = fm.get_line(idx) { - buf.push_str(line); + buf.push_str(line.as_ref()); buf.push('\n'); } } @@ -206,7 +207,7 @@ impl CodeSuggestion { for buf in &mut bufs { // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { - push_trailing(buf, prev_line, &prev_hi, None); + push_trailing(buf, prev_line.as_ref(), &prev_hi, None); } // remove trailing newline buf.pop(); diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index f37dcfdde89..e60edafe4ee 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -314,7 +314,7 @@ impl DiagnosticSpanLine { h_end: usize) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: fm.get_line(index).unwrap_or("").to_owned(), + text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 9e545b81390..0bac896f6a2 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -33,6 +33,7 @@ #![cfg_attr(stage0, feature(rustc_private))] #![cfg_attr(stage0, feature(staged_api))] +use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::ops::{Add, Sub}; use std::rc::Rc; @@ -605,24 +606,33 @@ impl FileMap { /// get a line from the list of pre-computed line-beginnings. /// line-number here is 0-based. - pub fn get_line(&self, line_number: usize) -> Option<&str> { - match self.src { - Some(ref src) => { - let lines = self.lines.borrow(); - lines.get(line_number).map(|&line| { - let begin: BytePos = line - self.start_pos; - let begin = begin.to_usize(); - // We can't use `lines.get(line_number+1)` because we might - // be parsing when we call this function and thus the current - // line is the last one we have line info for. - let slice = &src[begin..]; - match slice.find('\n') { - Some(e) => &slice[..e], - None => slice - } - }) + pub fn get_line(&self, line_number: usize) -> Option> { + fn get_until_newline(src: &str, begin: usize) -> &str { + // We can't use `lines.get(line_number+1)` because we might + // be parsing when we call this function and thus the current + // line is the last one we have line info for. + let slice = &src[begin..]; + match slice.find('\n') { + Some(e) => &slice[..e], + None => slice } - None => None + } + + let lines = self.lines.borrow(); + let line = if let Some(line) = lines.get(line_number) { + line + } else { + return None; + }; + let begin: BytePos = *line - self.start_pos; + let begin = begin.to_usize(); + + if let Some(ref src) = self.src { + Some(Cow::from(get_until_newline(src, begin))) + } else if let Some(src) = self.external_src.borrow().get_source() { + Some(Cow::Owned(String::from(get_until_newline(src, begin)))) + } else { + None } } @@ -641,7 +651,7 @@ impl FileMap { } pub fn is_imported(&self) -> bool { - self.src.is_none() // TODO: change to something more sensible + self.src.is_none() } pub fn byte_length(&self) -> u32 { -- cgit 1.4.1-3-g733a5 From 9a8bbe9da9a9c5537379ee38e755cf35c7a4fc96 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 13:48:54 +0200 Subject: Added hash verification to external source loading. --- src/libsyntax/codemap.rs | 9 ++------- src/libsyntax_pos/lib.rs | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index fb78b18b898..8e04e47e25f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -567,13 +567,8 @@ impl CodeMapper for CodeMap { }; if *file_map.external_src.borrow() == ExternalSource::AbsentOk { - let mut external_src = file_map.external_src.borrow_mut(); - if let Ok(src) = self.file_loader.read_file(Path::new(&filename)) { - *external_src = ExternalSource::Present(src); - return true; - } else { - *external_src = ExternalSource::AbsentErr; - } + let src = self.file_loader.read_file(Path::new(&filename)).ok(); + return file_map.add_external_src(src); } false diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 0bac896f6a2..719c25e2410 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -604,6 +604,26 @@ impl FileMap { lines.push(pos); } + /// add externally loaded source. + /// if the hash of the input doesn't match or no input is supplied via None, + /// it is interpreted as an error and the corresponding enum variant is set. + pub fn add_external_src(&self, src: Option) -> bool { + let mut external_src = self.external_src.borrow_mut(); + if let Some(src) = src { + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + + if hasher.finish() == self.src_hash { + *external_src = ExternalSource::Present(src); + return true; + } + } else { + *external_src = ExternalSource::AbsentErr; + } + + false + } + /// get a line from the list of pre-computed line-beginnings. /// line-number here is 0-based. pub fn get_line(&self, line_number: usize) -> Option> { -- cgit 1.4.1-3-g733a5 From afe841587df0d20b344b576641d0a32d32b87f54 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Sun, 11 Jun 2017 16:45:51 +0200 Subject: External spans: fixed unit tests and addressed review. --- src/librustc_data_structures/stable_hasher.rs | 2 +- src/libsyntax/codemap.rs | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index f3572d3e25b..5e291ea3c15 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -81,7 +81,7 @@ impl StableHasherResult for [u8; 20] { impl StableHasherResult for u128 { fn finish(mut hasher: StableHasher) -> Self { let hash_bytes: &[u8] = hasher.finalize(); - assert!(hash_bytes.len() >= mem::size_of::() * 2); + assert!(hash_bytes.len() >= mem::size_of::()); unsafe { ::std::ptr::read_unaligned(hash_bytes.as_ptr() as *const u128) diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 8e04e47e25f..7267f510a49 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -618,6 +618,7 @@ impl FilePathMapping { #[cfg(test)] mod tests { use super::*; + use std::borrow::Cow; use std::rc::Rc; #[test] @@ -627,12 +628,12 @@ mod tests { "first line.\nsecond line".to_string()); fm.next_line(BytePos(0)); // Test we can get lines with partial line info. - assert_eq!(fm.get_line(0), Some("first line.")); + assert_eq!(fm.get_line(0), Some(Cow::from("first line."))); // TESTING BROKEN BEHAVIOR: line break declared before actual line break. fm.next_line(BytePos(10)); - assert_eq!(fm.get_line(1), Some(".")); + assert_eq!(fm.get_line(1), Some(Cow::from("."))); fm.next_line(BytePos(12)); - assert_eq!(fm.get_line(2), Some("second line")); + assert_eq!(fm.get_line(2), Some(Cow::from("second line"))); } #[test] -- cgit 1.4.1-3-g733a5 From 271133b03ee5da57334670f50cd8a6ebbc35d140 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 12 Jun 2017 15:37:26 +0200 Subject: External spans: address review. * The lazy loading mechanism has been moved to a more appropriate place. * Return values from the functions invoked there are properly used. * Documentation has gotten some minor improvements. * Possibly some larger restructuring will need to take place still. --- src/librustc_errors/emitter.rs | 9 +++------ src/librustc_errors/lib.rs | 4 ++-- src/libsyntax/codemap.rs | 16 +++------------- src/libsyntax_pos/lib.rs | 35 ++++++++++++++++++++--------------- 4 files changed, 28 insertions(+), 36 deletions(-) (limited to 'src/libsyntax') diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2099725c48a..b4b14328b3d 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -177,8 +177,6 @@ impl EmitterWriter { continue; } - cm.load_source_for_filemap(cm.span_to_filename(span_label.span)); - let lo = cm.lookup_char_pos(span_label.span.lo); let mut hi = cm.lookup_char_pos(span_label.span.hi); @@ -891,10 +889,10 @@ impl EmitterWriter { let mut annotated_files = self.preprocess_annotations(msp); // Make sure our primary file comes first - let primary_lo = if let (Some(ref cm), Some(ref primary_span)) = + let (primary_lo, cm) = if let (Some(cm), Some(ref primary_span)) = (self.cm.as_ref(), msp.primary_span().as_ref()) { if primary_span != &&DUMMY_SP { - cm.lookup_char_pos(primary_span.lo) + (cm.lookup_char_pos(primary_span.lo), cm) } else { emit_to_destination(&buffer.render(), level, &mut self.dst)?; return Ok(()); @@ -912,8 +910,7 @@ impl EmitterWriter { // Print out the annotate source lines that correspond with the error for annotated_file in annotated_files { // we can't annotate anything if the source is unavailable. - if annotated_file.file.src.is_none() - && annotated_file.file.external_src.borrow().is_absent() { + if !cm.ensure_filemap_source_present(annotated_file.file.clone()) { continue; } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 26ecbe724f8..975b720276e 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -50,7 +50,7 @@ pub mod registry; pub mod styled_buffer; mod lock; -use syntax_pos::{BytePos, Loc, FileLinesResult, FileName, MultiSpan, Span, NO_EXPANSION}; +use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION}; #[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)] pub enum RenderSpan { @@ -104,7 +104,7 @@ pub trait CodeMapper { fn span_to_filename(&self, sp: Span) -> FileName; fn merge_spans(&self, sp_lhs: Span, sp_rhs: Span) -> Option; fn call_span_if_macro(&self, sp: Span) -> Span; - fn load_source_for_filemap(&self, file: FileName) -> bool; + fn ensure_filemap_source_present(&self, file_map: Rc) -> bool; } impl CodeSuggestion { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 7267f510a49..5b10139cd19 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -559,19 +559,9 @@ impl CodeMapper for CodeMap { } sp } - fn load_source_for_filemap(&self, filename: FileName) -> bool { - let file_map = if let Some(fm) = self.get_filemap(&filename) { - fm - } else { - return false; - }; - - if *file_map.external_src.borrow() == ExternalSource::AbsentOk { - let src = self.file_loader.read_file(Path::new(&filename)).ok(); - return file_map.add_external_src(src); - } - - false + fn ensure_filemap_source_present(&self, file_map: Rc) -> bool { + let src = self.file_loader.read_file(Path::new(&file_map.name)).ok(); + return file_map.add_external_src(src) } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 719c25e2410..94656b3aea7 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -604,28 +604,33 @@ impl FileMap { lines.push(pos); } - /// add externally loaded source. - /// if the hash of the input doesn't match or no input is supplied via None, + /// Add externally loaded source. + /// If the hash of the input doesn't match or no input is supplied via None, /// it is interpreted as an error and the corresponding enum variant is set. + /// The return value signifies whether some kind of source is present. pub fn add_external_src(&self, src: Option) -> bool { - let mut external_src = self.external_src.borrow_mut(); - if let Some(src) = src { - let mut hasher: StableHasher = StableHasher::new(); - hasher.write(src.as_bytes()); - - if hasher.finish() == self.src_hash { - *external_src = ExternalSource::Present(src); - return true; + if *self.external_src.borrow() == ExternalSource::AbsentOk { + let mut external_src = self.external_src.borrow_mut(); + if let Some(src) = src { + let mut hasher: StableHasher = StableHasher::new(); + hasher.write(src.as_bytes()); + + if hasher.finish() == self.src_hash { + *external_src = ExternalSource::Present(src); + return true; + } + } else { + *external_src = ExternalSource::AbsentErr; } + + false } else { - *external_src = ExternalSource::AbsentErr; + self.src.is_some() || self.external_src.borrow().get_source().is_some() } - - false } - /// get a line from the list of pre-computed line-beginnings. - /// line-number here is 0-based. + /// Get a line from the list of pre-computed line-beginnings. + /// The line number here is 0-based. pub fn get_line(&self, line_number: usize) -> Option> { fn get_until_newline(src: &str, begin: usize) -> &str { // We can't use `lines.get(line_number+1)` because we might -- cgit 1.4.1-3-g733a5 From d11973ae2a41bb84cd933e6646f3d8e6f28201e8 Mon Sep 17 00:00:00 2001 From: Inokentiy Babushkin Date: Mon, 12 Jun 2017 21:47:39 +0200 Subject: External spans: added lazy source loading elsewhere * In other places where the `src` member of a file map is accessed, we now load and possibly work with external source as well. --- src/libsyntax/codemap.rs | 49 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) (limited to 'src/libsyntax') diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 5b10139cd19..b3d9cf9da36 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -415,30 +415,31 @@ impl CodeMap { local_end.fm.start_pos) })); } else { - match local_begin.fm.src { - Some(ref src) => { - let start_index = local_begin.pos.to_usize(); - let end_index = local_end.pos.to_usize(); - let source_len = (local_begin.fm.end_pos - - local_begin.fm.start_pos).to_usize(); - - if start_index > end_index || end_index > source_len { - return Err(SpanSnippetError::MalformedForCodemap( - MalformedCodemapPositions { - name: local_begin.fm.name.clone(), - source_len: source_len, - begin_pos: local_begin.pos, - end_pos: local_end.pos, - })); - } - - return Ok((&src[start_index..end_index]).to_string()) - } - None => { - return Err(SpanSnippetError::SourceNotAvailable { - filename: local_begin.fm.name.clone() - }); - } + self.ensure_filemap_source_present(local_begin.fm.clone()); + + let start_index = local_begin.pos.to_usize(); + let end_index = local_end.pos.to_usize(); + let source_len = (local_begin.fm.end_pos - + local_begin.fm.start_pos).to_usize(); + + if start_index > end_index || end_index > source_len { + return Err(SpanSnippetError::MalformedForCodemap( + MalformedCodemapPositions { + name: local_begin.fm.name.clone(), + source_len: source_len, + begin_pos: local_begin.pos, + end_pos: local_end.pos, + })); + } + + if let Some(ref src) = local_begin.fm.src { + return Ok((&src[start_index..end_index]).to_string()); + } else if let Some(src) = local_begin.fm.external_src.borrow().get_source() { + return Ok((&src[start_index..end_index]).to_string()); + } else { + return Err(SpanSnippetError::SourceNotAvailable { + filename: local_begin.fm.name.clone() + }); } } } -- cgit 1.4.1-3-g733a5