diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 541c1356dd4abbd73ae604adf5c2a22c499b8786..b10e742595720dc595863c124d1404ce9d74f8b8 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -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 }; diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 862ea0c240ab9bd286b47b2780b821822c107ae7..9888b2fffc7792beaa1a8c4590a185966f372621 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -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) => diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index f755efc89a58ed1925807a912161a4fa40f1ada5..b35e8c6b41953dc27c870b314b823ca5f57bf516 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -1276,7 +1276,8 @@ fn report_out_of_scope_escaping_closure_capture(&self, fn region_end_span(&self, region: ty::Region<'tcx>) -> Option { 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 } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index d6937c405f961d91c95a64834f0edc26d2b950e5..f69236516630ded31a4709edb1ded82c96427c3a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -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(), ) } diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 50e50b95f7750401cff775c2e15c1a271e630322..a631ab27d1c872bf50800437c988fd103b0c13d1 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -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, diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index f543a33b130b6f9b2f05f402caa84a0ff8e3e9a3..d7cd8830adb00f78b9d4390a5c091c0719d4f228 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -537,8 +537,8 @@ pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option { 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)) } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 557ff887a3ef283c205ac6b8a4421b61f435c811..f7228fc3314c30b43f02da009db506316f1d9388 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 6147743437b8e638b5be3ad4814dcb3d27f2a0ea..9b24c09036bce9e893317f1871a0968bf43a61b9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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()); diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index a58a61c36361b4d82f0dd548a1f08464e1344d04..e74066da0ac83183662be1ea5a9cd2a8376aa823 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -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> { for fm in self.files.borrow().iter() { if *filename == fm.name { diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index d393cab471850a5af744a53f39f23ccee8a83bbb..e8e87e2854b777db8ae86cd0262487cad70e3fd3 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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) -> PResult<'a, P 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 }