Use explicit lifetime to get rid of unsafe code

at least this is why we use Rust
This commit is contained in:
Seiichi Uchida 2017-12-07 13:51:30 +09:00
parent 7c4a84751f
commit 1d9a10e00e
3 changed files with 24 additions and 24 deletions

View file

@ -45,7 +45,7 @@ use config::Config;
use filemap::FileMap; use filemap::FileMap;
use issues::{BadIssueSeeker, Issue}; use issues::{BadIssueSeeker, Issue};
use utils::use_colored_tty; use utils::use_colored_tty;
use visitor::FmtVisitor; use visitor::{FmtVisitor, SnippetProvider};
pub use self::summary::Summary; pub use self::summary::Summary;
@ -317,8 +317,13 @@ where
if config.verbose() { if config.verbose() {
println!("Formatting {}", path_str); println!("Formatting {}", path_str);
} }
let mut visitor = FmtVisitor::from_codemap(parse_session, config, module.inner); let filemap = parse_session
let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; .codemap()
.lookup_char_pos(module.inner.lo())
.file;
let big_snippet = filemap.src.as_ref().unwrap();
let snippet_provider = SnippetProvider::new(filemap.start_pos, big_snippet);
let mut visitor = FmtVisitor::from_codemap(parse_session, config, &snippet_provider);
// Format inner attributes if available. // Format inner attributes if available.
if !krate.attrs.is_empty() && path == main_file { if !krate.attrs.is_empty() && path == main_file {
visitor.skip_empty_lines(filemap.end_pos); visitor.skip_empty_lines(filemap.end_pos);

View file

@ -35,7 +35,7 @@ pub struct RewriteContext<'a> {
pub is_if_else_block: bool, pub is_if_else_block: bool,
// When rewriting chain, veto going multi line except the last element // When rewriting chain, veto going multi line except the last element
pub force_one_line_chain: bool, pub force_one_line_chain: bool,
pub snippet_provider: &'a SnippetProvider, pub snippet_provider: &'a SnippetProvider<'a>,
} }
impl<'a> RewriteContext<'a> { impl<'a> RewriteContext<'a> {

View file

@ -10,7 +10,6 @@
use std::rc::Rc; use std::rc::Rc;
use std::cmp; use std::cmp;
use std::mem;
use strings::string_buffer::StringBuffer; use strings::string_buffer::StringBuffer;
use syntax::{ast, visit}; use syntax::{ast, visit};
@ -50,24 +49,22 @@ fn is_extern_crate(item: &ast::Item) -> bool {
} }
/// Creates a string slice corresponding to the specified span. /// Creates a string slice corresponding to the specified span.
pub struct SnippetProvider { pub struct SnippetProvider<'a> {
/// A pointer to the content of the file we are formatting. /// A pointer to the content of the file we are formatting.
big_snippet: *const Rc<String>, big_snippet: &'a Rc<String>,
/// A position of the start of `big_snippet`, used as an offset. /// A position of the start of `big_snippet`, used as an offset.
start_pos: usize, start_pos: usize,
} }
impl SnippetProvider { impl<'b, 'a: 'b> SnippetProvider<'a> {
pub fn span_to_snippet(&self, span: Span) -> Option<&str> { pub fn span_to_snippet(&'b self, span: Span) -> Option<&'a str> {
let start_index = span.lo().to_usize().checked_sub(self.start_pos)?; let start_index = span.lo().to_usize().checked_sub(self.start_pos)?;
let end_index = span.hi().to_usize().checked_sub(self.start_pos)?; let end_index = span.hi().to_usize().checked_sub(self.start_pos)?;
unsafe { Some(&(*self.big_snippet)[start_index..end_index]) } Some(&self.big_snippet[start_index..end_index])
} }
pub fn from_codemap(codemap: &CodeMap, span: Span) -> Self { pub fn new(start_pos: BytePos, big_snippet: &'a Rc<String>) -> Self {
let filemap = codemap.lookup_char_pos(span.lo()).file; let start_pos = start_pos.to_usize();
let big_snippet = unsafe { mem::transmute(&filemap.src) };
let start_pos = filemap.start_pos.to_usize();
SnippetProvider { SnippetProvider {
big_snippet, big_snippet,
start_pos, start_pos,
@ -84,10 +81,10 @@ pub struct FmtVisitor<'a> {
pub block_indent: Indent, pub block_indent: Indent,
pub config: &'a Config, pub config: &'a Config,
pub is_if_else_block: bool, pub is_if_else_block: bool,
pub snippet_provier: SnippetProvider, pub snippet_provider: &'a SnippetProvider<'a>,
} }
impl<'a> FmtVisitor<'a> { impl<'b, 'a: 'b> FmtVisitor<'a> {
pub fn shape(&self) -> Shape { pub fn shape(&self) -> Shape {
Shape::indented(self.block_indent, self.config) Shape::indented(self.block_indent, self.config)
} }
@ -537,7 +534,7 @@ impl<'a> FmtVisitor<'a> {
pub fn from_codemap( pub fn from_codemap(
parse_session: &'a ParseSess, parse_session: &'a ParseSess,
config: &'a Config, config: &'a Config,
span: Span, snippet_provider: &'a SnippetProvider,
) -> FmtVisitor<'a> { ) -> FmtVisitor<'a> {
FmtVisitor { FmtVisitor {
parse_session: parse_session, parse_session: parse_session,
@ -547,17 +544,15 @@ impl<'a> FmtVisitor<'a> {
block_indent: Indent::empty(), block_indent: Indent::empty(),
config: config, config: config,
is_if_else_block: false, is_if_else_block: false,
snippet_provier: SnippetProvider::from_codemap(parse_session.codemap(), span), snippet_provider: snippet_provider,
} }
} }
pub fn opt_snippet<'b: 'a>(&'a self, span: Span) -> Option<&'b str> { pub fn opt_snippet(&'b self, span: Span) -> Option<&'a str> {
self.snippet_provier self.snippet_provider.span_to_snippet(span)
.span_to_snippet(span)
.map(|s| unsafe { mem::transmute::<&'a str, &'b str>(s) })
} }
pub fn snippet<'b: 'a>(&'a self, span: Span) -> &'b str { pub fn snippet(&'b self, span: Span) -> &'a str {
self.opt_snippet(span).unwrap() self.opt_snippet(span).unwrap()
} }
@ -755,7 +750,7 @@ impl<'a> FmtVisitor<'a> {
use_block: false, use_block: false,
is_if_else_block: false, is_if_else_block: false,
force_one_line_chain: false, force_one_line_chain: false,
snippet_provider: &self.snippet_provier, snippet_provider: &self.snippet_provider,
} }
} }
} }