Skip to content

Rollup of 12 pull requests #24265

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
549bd55
resurrect research paper list #24004
Apr 9, 2015
c3aa057
Add regression test for #19097
aturon Apr 9, 2015
644a75e
Fix `borrow` docs
apasel422 Apr 9, 2015
69f63e9
Indicate keyword in doc comment is code-like
frewsxcv Apr 9, 2015
8578fee
Don't use skolemized parameters but rather fresh variables in
nikomatsakis Apr 9, 2015
9eb8528
Copyediting for 'variable bindings'
steveklabnik Apr 9, 2015
bf88539
TRPL: new introduction
steveklabnik Apr 9, 2015
06dc26d
More editing work on TRPL
steveklabnik Apr 9, 2015
7bb0cd7
Write the 'primitive types' section of TRPL
steveklabnik Apr 9, 2015
2a88b79
Add tests for E-needstest issues
lgrz Apr 10, 2015
16574e3
Replace the use of the rather randomly named boolean `custom` to mean
nikomatsakis Apr 9, 2015
5156b3a
Modify the codemap code to use more slices and to information about
nikomatsakis Apr 9, 2015
906a972
Add a new `span_suggestion` infrastructure. This lets you edit a snippet
nikomatsakis Apr 9, 2015
e313b33
Improve error message where a closure escapes fn while trying to borrow
nikomatsakis Apr 9, 2015
b6c8e23
Add examples for Convert
steveklabnik Apr 6, 2015
b1e6625
Rollup merge of #24121 - steveklabnik:gh24107, r=alexcrichton
steveklabnik Apr 10, 2015
f3b7768
Rollup merge of #24234 - thiagooak:academic-research, r=steveklabnik
steveklabnik Apr 10, 2015
48d692f
Rollup merge of #24236 - aturon:issue-19097, r=alexcrichton
steveklabnik Apr 10, 2015
fa2e35b
Rollup merge of #24239 - steveklabnik:editing_pass, r=steveklabnik
steveklabnik Apr 10, 2015
0d51a2f
Rollup merge of #24240 - apasel422:patch-1, r=aturon
steveklabnik Apr 10, 2015
fb65d25
Rollup merge of #24242 - nikomatsakis:escaping-closure-error-message,…
steveklabnik Apr 10, 2015
9f5bbfd
Rollup merge of #24243 - frewsxcv:patch-13, r=steveklabnik
steveklabnik Apr 10, 2015
09e9b4c
Rollup merge of #24244 - steveklabnik:more_editing, r=steveklabnik
steveklabnik Apr 10, 2015
f5f3de1
Rollup merge of #24245 - nikomatsakis:issue-24241-coherence-failure, …
steveklabnik Apr 10, 2015
cf06dc4
Rollup merge of #24247 - steveklabnik:update_variable_bindings, r=huonw
steveklabnik Apr 10, 2015
88b7869
Rollup merge of #24253 - steveklabnik:doc_primitive_types, r=alexcric…
steveklabnik Apr 10, 2015
2cb82b6
Rollup merge of #24259 - lstat:needstest, r=alexcrichton
steveklabnik Apr 10, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/librustc/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ impl Session {
pub fn span_end_note(&self, sp: Span, msg: &str) {
self.diagnostic().span_end_note(sp, msg)
}

/// Prints out a message with a suggested edit of the code.
///
/// See `diagnostic::RenderSpan::Suggestion` for more information.
pub fn span_suggestion(&self, sp: Span, msg: &str, suggestion: String) {
self.diagnostic().span_suggestion(sp, msg, suggestion)
}
pub fn span_help(&self, sp: Span, msg: &str) {
self.diagnostic().span_help(sp, msg)
}
Expand Down
62 changes: 53 additions & 9 deletions src/librustc_borrowck/borrowck/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,16 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}

pub fn report(&self, err: BckError<'tcx>) {
// Catch and handle some particular cases.
match (&err.code, &err.cause) {
(&err_out_of_scope(ty::ReScope(_), ty::ReStatic), &euv::ClosureCapture(span)) |
(&err_out_of_scope(ty::ReScope(_), ty::ReFree(..)), &euv::ClosureCapture(span)) => {
return self.report_out_of_scope_escaping_closure_capture(&err, span);
}
_ => { }
}

// General fallback.
self.span_err(
err.span,
&self.bckerr_to_string(&err));
Expand Down Expand Up @@ -796,16 +806,10 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
format!("{} does not live long enough", msg)
}
err_borrowed_pointer_too_short(..) => {
let descr = match opt_loan_path(&err.cmt) {
Some(lp) => {
format!("`{}`", self.loan_path_to_string(&*lp))
}
None => self.cmt_to_string(&*err.cmt),
};

let descr = self.cmt_to_path_or_string(&err.cmt);
format!("lifetime of {} is too short to guarantee \
its contents can be safely reborrowed",
descr)
its contents can be safely reborrowed",
descr)
}
}
}
Expand Down Expand Up @@ -888,6 +892,39 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
}
}

fn report_out_of_scope_escaping_closure_capture(&self,
err: &BckError<'tcx>,
capture_span: Span)
{
let cmt_path_or_string = self.cmt_to_path_or_string(&err.cmt);

span_err!(
self.tcx.sess, err.span, E0373,
"closure may outlive the current function, \
but it borrows {}, \
which is owned by the current function",
cmt_path_or_string);

self.tcx.sess.span_note(
capture_span,
&format!("{} is borrowed here",
cmt_path_or_string));

let suggestion =
match self.tcx.sess.codemap().span_to_snippet(err.span) {
Ok(string) => format!("move {}", string),
Err(_) => format!("move |<args>| <body>")
};

self.tcx.sess.span_suggestion(
err.span,
&format!("to force the closure to take ownership of {} \
(and any other referenced variables), \
use the `move` keyword, as shown:",
cmt_path_or_string),
suggestion);
}

pub fn note_and_explain_bckerr(&self, err: BckError<'tcx>) {
let code = err.code;
match code {
Expand Down Expand Up @@ -1035,6 +1072,13 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
pub fn cmt_to_string(&self, cmt: &mc::cmt_<'tcx>) -> String {
cmt.descriptive_string(self.tcx)
}

pub fn cmt_to_path_or_string(&self, cmt: &mc::cmt<'tcx>) -> String {
match opt_loan_path(cmt) {
Some(lp) => format!("`{}`", self.loan_path_to_string(&lp)),
None => self.cmt_to_string(cmt),
}
}
}

fn is_statement_scope(tcx: &ty::ctxt, region: ty::Region) -> bool {
Expand Down
17 changes: 17 additions & 0 deletions src/librustc_borrowck/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(non_snake_case)]

register_diagnostics! {
E0373 // closure may outlive current fn, but it borrows {}, which is owned by current fn
}

__build_diagnostic_array! { DIAGNOSTICS }
4 changes: 4 additions & 0 deletions src/librustc_borrowck/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ pub use borrowck::check_crate;
pub use borrowck::build_borrowck_dataflow_data_for_fn;
pub use borrowck::FnPartsWithCFG;

// NB: This module needs to be declared first so diagnostics are
// registered before they are used.
pub mod diagnostics;

mod borrowck;

pub mod graphviz;
105 changes: 92 additions & 13 deletions src/libsyntax/codemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ pub struct BytePos(pub u32);
/// A character offset. Because of multibyte utf8 characters, a byte offset
/// is not equivalent to a character offset. The CodeMap will convert BytePos
/// values to CharPos values as necessary.
#[derive(Copy, Clone, PartialEq, Hash, PartialOrd, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Debug)]
pub struct CharPos(pub usize);

// FIXME: Lots of boilerplate in these impls, but so far my attempts to fix
Expand Down Expand Up @@ -305,9 +305,21 @@ impl ExpnId {

pub type FileName = String;

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct LineInfo {
/// Index of line, starting from 0.
pub line_index: usize,

/// Column in line where span begins, starting from 0.
pub start_col: CharPos,

/// Column in line where span ends, starting from 0, exclusive.
pub end_col: CharPos,
}

pub struct FileLines {
pub file: Rc<FileMap>,
pub lines: Vec<usize>
pub lines: Vec<LineInfo>
}

/// Identifies an offset of a multi-byte character in a FileMap
Expand Down Expand Up @@ -479,9 +491,9 @@ impl FileMap {
lines.push(pos);
}

/// get a line from the list of pre-computed line-beginnings
///
pub fn get_line(&self, line_number: usize) -> Option<String> {
/// 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();
Expand All @@ -492,7 +504,7 @@ impl FileMap {
match slice.find('\n') {
Some(e) => &slice[..e],
None => slice
}.to_string()
}
})
}
None => None
Expand Down Expand Up @@ -661,10 +673,29 @@ impl CodeMap {
pub fn span_to_lines(&self, sp: Span) -> FileLines {
let lo = self.lookup_char_pos(sp.lo);
let hi = self.lookup_char_pos(sp.hi);
let mut lines = Vec::new();
for i in lo.line - 1..hi.line {
lines.push(i);
};
let mut lines = Vec::with_capacity(hi.line - lo.line + 1);

// The span starts partway through the first line,
// but after that it starts from offset 0.
let mut start_col = lo.col;

// For every line but the last, it extends from `start_col`
// and to the end of the line. Be careful because the line
// numbers in Loc are 1-based, so we subtract 1 to get 0-based
// lines.
for line_index in lo.line-1 .. hi.line-1 {
let line_len = lo.file.get_line(line_index).map(|s| s.len()).unwrap_or(0);
lines.push(LineInfo { line_index: line_index,
start_col: start_col,
end_col: CharPos::from_usize(line_len) });
start_col = CharPos::from_usize(0);
}

// For the last line, it extends from `start_col` to `hi.col`:
lines.push(LineInfo { line_index: hi.line - 1,
start_col: start_col,
end_col: hi.col });

FileLines {file: lo.file, lines: lines}
}

Expand Down Expand Up @@ -919,17 +950,18 @@ pub struct MalformedCodemapPositions {
#[cfg(test)]
mod test {
use super::*;
use std::rc::Rc;

#[test]
fn t1 () {
let cm = CodeMap::new();
let fm = cm.new_filemap("blork.rs".to_string(),
"first line.\nsecond line".to_string());
fm.next_line(BytePos(0));
assert_eq!(fm.get_line(0), Some("first line.".to_string()));
assert_eq!(fm.get_line(0), Some("first line."));
// TESTING BROKEN BEHAVIOR:
fm.next_line(BytePos(10));
assert_eq!(fm.get_line(1), Some(".".to_string()));
assert_eq!(fm.get_line(1), Some("."));
}

#[test]
Expand Down Expand Up @@ -1057,7 +1089,54 @@ mod test {

assert_eq!(file_lines.file.name, "blork.rs");
assert_eq!(file_lines.lines.len(), 1);
assert_eq!(file_lines.lines[0], 1);
assert_eq!(file_lines.lines[0].line_index, 1);
}

/// Given a string like " ^~~~~~~~~~~~ ", produces a span
/// coverting that range. The idea is that the string has the same
/// length as the input, and we uncover the byte positions. Note
/// that this can span lines and so on.
fn span_from_selection(input: &str, selection: &str) -> Span {
assert_eq!(input.len(), selection.len());
let left_index = selection.find('^').unwrap() as u32;
let right_index = selection.rfind('~').unwrap() as u32;
Span { lo: BytePos(left_index), hi: BytePos(right_index + 1), expn_id: NO_EXPANSION }
}

fn new_filemap_and_lines(cm: &CodeMap, filename: &str, input: &str) -> Rc<FileMap> {
let fm = cm.new_filemap(filename.to_string(), input.to_string());
let mut byte_pos: u32 = 0;
for line in input.lines() {
// register the start of this line
fm.next_line(BytePos(byte_pos));

// update byte_pos to include this line and the \n at the end
byte_pos += line.len() as u32 + 1;
}
fm
}

/// Test span_to_snippet and span_to_lines for a span coverting 3
/// lines in the middle of a file.
#[test]
fn span_to_snippet_and_lines_spanning_multiple_lines() {
let cm = CodeMap::new();
let inputtext = "aaaaa\nbbbbBB\nCCC\nDDDDDddddd\neee\n";
let selection = " \n ^~\n~~~\n~~~~~ \n \n";
new_filemap_and_lines(&cm, "blork.rs", inputtext);
let span = span_from_selection(inputtext, selection);

// check that we are extracting the text we thought we were extracting
assert_eq!(&cm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD");

// check that span_to_lines gives us the complete result with the lines/cols we expected
let lines = cm.span_to_lines(span);
let expected = vec![
LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) },
LineInfo { line_index: 2, start_col: CharPos(0), end_col: CharPos(3) },
LineInfo { line_index: 3, start_col: CharPos(0), end_col: CharPos(5) }
];
assert_eq!(lines.lines, expected);
}

#[test]
Expand Down
Loading