]> git.lizzy.rs Git - rust.git/commitdiff
end_point handling multibyte characters correctly.
authorDavid Wood <david@davidtw.co>
Sun, 14 Jan 2018 17:29:07 +0000 (17:29 +0000)
committerDavid Wood <david@davidtw.co>
Sat, 27 Jan 2018 11:46:27 +0000 (11:46 +0000)
src/librustc/infer/error_reporting/mod.rs
src/librustc_borrowck/borrowck/check_loans.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_mir/borrow_check/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/dataflow/impls/borrows.rs
src/librustc_resolve/lib.rs
src/librustc_typeck/check/mod.rs
src/libsyntax/codemap.rs
src/libsyntax/parse/parser.rs
src/libsyntax_pos/lib.rs

index 541c1356dd4abbd73ae604adf5c2a22c499b8786..b10e742595720dc595863c124d1404ce9d74f8b8 100644 (file)
@@ -958,7 +958,8 @@ pub fn report_generic_bound_failure(&self,
                             // `sp` only covers `T`, change it so that it covers
                             // `T:` when appropriate
                             let sp = if has_lifetimes {
-                                sp.to(sp.next_point().next_point())
+                                sp.to(self.tcx.sess.codemap().next_point(
+                                        self.tcx.sess.codemap().next_point(sp)))
                             } else {
                                 sp
                             };
index 862ea0c240ab9bd286b47b2780b821822c107ae7..9888b2fffc7792beaa1a8c4590a185966f372621 100644 (file)
@@ -591,8 +591,8 @@ pub fn report_error_if_loan_conflicts_with_restriction(&self,
             // 3. Where does old loan expire.
 
             let previous_end_span =
-                Some(old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree)
-                     .end_point());
+                Some(self.tcx().sess.codemap().end_point(
+                        old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree)));
 
             let mut err = match (new_loan.kind, old_loan.kind) {
                 (ty::MutBorrow, ty::MutBorrow) =>
index f755efc89a58ed1925807a912161a4fa40f1ada5..b35e8c6b41953dc27c870b314b823ca5f57bf516 100644 (file)
@@ -1276,7 +1276,8 @@ fn report_out_of_scope_escaping_closure_capture(&self,
     fn region_end_span(&self, region: ty::Region<'tcx>) -> Option<Span> {
         match *region {
             ty::ReScope(scope) => {
-                Some(scope.span(self.tcx, &self.region_scope_tree).end_point())
+                Some(self.tcx.sess.codemap().end_point(
+                        scope.span(self.tcx, &self.region_scope_tree)))
             }
             _ => None
         }
index d6937c405f961d91c95a64834f0edc26d2b950e5..f69236516630ded31a4709edb1ded82c96427c3a 100644 (file)
@@ -1112,10 +1112,11 @@ fn check_for_invalidation_at_exit(
             debug!("check_for_invalidation_at_exit({:?}): INVALID", place);
             // FIXME: should be talking about the region lifetime instead
             // of just a span here.
+            let span = self.tcx.sess.codemap().end_point(span);
             self.report_borrowed_value_does_not_live_long_enough(
                 context,
                 borrow,
-                span.end_point(),
+                span,
                 flow_state.borrows.operator(),
             )
         }
index 50e50b95f7750401cff775c2e15c1a271e630322..a631ab27d1c872bf50800437c988fd103b0c13d1 100644 (file)
@@ -699,7 +699,7 @@ pub fn schedule_drop(&mut self,
                 let region_scope_span = region_scope.span(self.hir.tcx(),
                                                           &self.hir.region_scope_tree);
                 // Attribute scope exit drops to scope's closing brace.
-                let scope_end = region_scope_span.end_point();
+                let scope_end = self.hir.tcx().sess.codemap().end_point(region_scope_span);
 
                 scope.drops.push(DropData {
                     span: scope_end,
index f543a33b130b6f9b2f05f402caa84a0ff8e3e9a3..d7cd8830adb00f78b9d4390a5c091c0719d4f228 100644 (file)
@@ -537,8 +537,8 @@ pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option<Span> {
             Some(_) => None,
             None => {
                 match self.0.region_span_map.get(region) {
-                    Some(span) => Some(span.end_point()),
-                    None => Some(self.0.mir.span.end_point())
+                    Some(span) => Some(self.0.tcx.sess.codemap().end_point(*span)),
+                    None => Some(self.0.tcx.sess.codemap().end_point(self.0.mir.span))
                 }
             }
         }
index 557ff887a3ef283c205ac6b8a4421b61f435c811..f7228fc3314c30b43f02da009db506316f1d9388 100644 (file)
@@ -2871,8 +2871,8 @@ fn type_ascription_suggestion(&self,
         if let Some(sp) = self.current_type_ascription.last() {
             let mut sp = *sp;
             loop {  // try to find the `:`, bail on first non-':'/non-whitespace
-                sp = sp.next_point();
-                if let Ok(snippet) = cm.span_to_snippet(sp.to(sp.next_point())) {
+                sp = cm.next_point(sp);
+                if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
                     debug!("snippet {:?}", snippet);
                     let line_sp = cm.lookup_char_pos(sp.hi()).line;
                     let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;
index 6147743437b8e638b5be3ad4814dcb3d27f2a0ea..9b24c09036bce9e893317f1871a0968bf43a61b9 100644 (file)
@@ -2457,7 +2457,7 @@ fn parameter_count_error<'tcx>(sess: &Session,
                 err.span_label(def_s, "defined here");
             }
             if sugg_unit {
-                let sugg_span = expr_sp.end_point();
+                let sugg_span = sess.codemap().end_point(expr_sp);
                 // remove closing `)` from the span
                 let sugg_span = sugg_span.with_hi(sugg_span.lo());
                 err.span_suggestion(
@@ -4446,10 +4446,10 @@ pub fn suggest_mismatched_types_on_tail(&self,
     /// statement and the return type has been left as default or has been specified as `()`. If so,
     /// it suggests adding a semicolon.
     fn suggest_missing_semicolon(&self,
-                                     err: &mut DiagnosticBuilder<'tcx>,
-                                     expression: &'gcx hir::Expr,
-                                     expected: Ty<'tcx>,
-                                     cause_span: Span) {
+                                 err: &mut DiagnosticBuilder<'tcx>,
+                                 expression: &'gcx hir::Expr,
+                                 expected: Ty<'tcx>,
+                                 cause_span: Span) {
         if expected.is_nil() {
             // `BlockTailExpression` only relevant if the tail expr would be
             // useful on its own.
@@ -4461,7 +4461,7 @@ fn suggest_missing_semicolon(&self,
                 hir::ExprLoop(..) |
                 hir::ExprMatch(..) |
                 hir::ExprBlock(..) => {
-                    let sp = cause_span.next_point();
+                    let sp = self.tcx.sess.codemap().next_point(cause_span);
                     err.span_suggestion(sp,
                                         "try adding a semicolon",
                                         ";".to_string());
index a58a61c36361b4d82f0dd548a1f08464e1344d04..e74066da0ac83183662be1ea5a9cd2a8376aa823 100644 (file)
@@ -25,6 +25,7 @@
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::stable_hasher::StableHasher;
 use std::cell::{RefCell, Ref};
+use std::cmp;
 use std::hash::Hash;
 use std::path::{Path, PathBuf};
 use std::rc::Rc;
@@ -607,6 +608,42 @@ pub fn def_span(&self, sp: Span) -> Span {
         self.span_until_char(sp, '{')
     }
 
+    /// Returns a new span representing just the end-point of this span
+    pub fn end_point(&self, sp: Span) -> Span {
+        let hi = sp.hi().0.checked_sub(1).unwrap_or(sp.hi().0);
+        let hi = self.get_start_of_char_bytepos(BytePos(hi));
+        let lo = cmp::max(hi.0, sp.lo().0);
+        sp.with_lo(BytePos(lo))
+    }
+
+    /// Returns a new span representing the next character after the end-point of this span
+    pub fn next_point(&self, sp: Span) -> Span {
+        let hi = sp.lo().0.checked_add(1).unwrap_or(sp.lo().0);
+        let hi = self.get_start_of_char_bytepos(BytePos(hi));
+        let lo = cmp::max(sp.hi().0, hi.0);
+        Span::new(BytePos(lo), BytePos(lo), sp.ctxt())
+    }
+
+    fn get_start_of_char_bytepos(&self, bpos: BytePos) -> BytePos {
+        let idx = self.lookup_filemap_idx(bpos);
+        let files = self.files.borrow();
+        let map = &(*files)[idx];
+
+        for mbc in map.multibyte_chars.borrow().iter() {
+            if mbc.pos < bpos {
+                if bpos.to_usize() >= mbc.pos.to_usize() + mbc.bytes {
+                    // If we do, then return the start of the character.
+                    return mbc.pos;
+                }
+            } else {
+                break;
+            }
+        }
+
+        // If this isn't a multibyte character, return the original position.
+        return bpos;
+    }
+
     pub fn get_filemap(&self, filename: &FileName) -> Option<Rc<FileMap>> {
         for fm in self.files.borrow().iter() {
             if *filename == fm.name {
index d393cab471850a5af744a53f39f23ccee8a83bbb..e8e87e2854b777db8ae86cd0262487cad70e3fd3 100644 (file)
@@ -704,13 +704,15 @@ fn tokens_to_string(tokens: &[TokenType]) -> String {
                     expect.clone()
                 };
                 (format!("expected one of {}, found `{}`", expect, actual),
-                 (self.prev_span.next_point(), format!("expected one of {} here", short_expect)))
+                 (self.sess.codemap().next_point(self.prev_span),
+                  format!("expected one of {} here", short_expect)))
             } else if expected.is_empty() {
                 (format!("unexpected token: `{}`", actual),
                  (self.prev_span, "unexpected token after this".to_string()))
             } else {
                 (format!("expected {}, found `{}`", expect, actual),
-                 (self.prev_span.next_point(), format!("expected {} here", expect)))
+                 (self.sess.codemap().next_point(self.prev_span),
+                  format!("expected {} here", expect)))
             };
             let mut err = self.fatal(&msg_exp);
             let sp = if self.token == token::Token::Eof {
@@ -3190,7 +3192,7 @@ pub fn parse_if_expr(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr
         // return. This won't catch blocks with an explicit `return`, but that would be caught by
         // the dead code lint.
         if self.eat_keyword(keywords::Else) || !cond.returns() {
-            let sp = lo.next_point();
+            let sp = self.sess.codemap().next_point(lo);
             let mut err = self.diagnostic()
                 .struct_span_err(sp, "missing condition for `if` statemement");
             err.span_label(sp, "expected if condition here");
index 5866d8e4aa9323668195c87b2a67c6e9cdaac95e..dd1ec7284f6901320987f68a3bd325bf2ad5201f 100644 (file)
@@ -216,22 +216,6 @@ pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
         self.data().with_ctxt(ctxt)
     }
 
-    /// Returns a new span representing just the end-point of this span
-    pub fn end_point(self) -> Span {
-        let span = self.data();
-        // We can avoid an ICE by checking if subtraction would cause an overflow.
-        let hi = if span.hi.0 == u32::min_value() { span.hi.0 } else { span.hi.0 - 1 };
-        let lo = cmp::max(hi, span.lo.0);
-        span.with_lo(BytePos(lo))
-    }
-
-    /// Returns a new span representing the next character after the end-point of this span
-    pub fn next_point(self) -> Span {
-        let span = self.data();
-        let lo = cmp::max(span.hi.0, span.lo.0 + 1);
-        Span::new(BytePos(lo), BytePos(lo), span.ctxt)
-    }
-
     /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
     pub fn substitute_dummy(self, other: Span) -> Span {
         if self.source_equal(&DUMMY_SP) { other } else { self }