Skip to content

Commit ee606c0

Browse files
committed
end_point handling multibyte characters correctly.
1 parent b7228c8 commit ee606c0

File tree

11 files changed

+61
-35
lines changed

11 files changed

+61
-35
lines changed

src/librustc/infer/error_reporting/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
958958
// `sp` only covers `T`, change it so that it covers
959959
// `T:` when appropriate
960960
let sp = if has_lifetimes {
961-
sp.to(sp.next_point().next_point())
961+
sp.to(self.tcx.sess.codemap().next_point(
962+
self.tcx.sess.codemap().next_point(sp)))
962963
} else {
963964
sp
964965
};

src/librustc_borrowck/borrowck/check_loans.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -484,8 +484,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
484484
// 3. Where does old loan expire.
485485

486486
let previous_end_span =
487-
Some(old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree)
488-
.end_point());
487+
Some(self.tcx().sess.codemap().end_point(
488+
old_loan.kill_scope.span(self.tcx(), &self.bccx.region_scope_tree)));
489489

490490
let mut err = match (new_loan.kind, old_loan.kind) {
491491
(ty::MutBorrow, ty::MutBorrow) =>

src/librustc_borrowck/borrowck/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1321,7 +1321,8 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
13211321
fn region_end_span(&self, region: ty::Region<'tcx>) -> Option<Span> {
13221322
match *region {
13231323
ty::ReScope(scope) => {
1324-
Some(scope.span(self.tcx, &self.region_scope_tree).end_point())
1324+
Some(self.tcx.sess.codemap().end_point(
1325+
scope.span(self.tcx, &self.region_scope_tree)))
13251326
}
13261327
_ => None
13271328
}

src/librustc_mir/borrow_check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1090,10 +1090,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
10901090
debug!("check_for_invalidation_at_exit({:?}): INVALID", place);
10911091
// FIXME: should be talking about the region lifetime instead
10921092
// of just a span here.
1093+
let span = self.tcx.sess.codemap().end_point(span);
10931094
self.report_borrowed_value_does_not_live_long_enough(
10941095
context,
10951096
borrow,
1096-
span.end_point(),
1097+
span,
10971098
flow_state.borrows.operator(),
10981099
)
10991100
}

src/librustc_mir/build/scope.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -699,7 +699,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
699699
let region_scope_span = region_scope.span(self.hir.tcx(),
700700
&self.hir.region_scope_tree);
701701
// Attribute scope exit drops to scope's closing brace.
702-
let scope_end = region_scope_span.end_point();
702+
let scope_end = self.hir.tcx().sess.codemap().end_point(region_scope_span);
703703

704704
scope.drops.push(DropData {
705705
span: scope_end,

src/librustc_mir/dataflow/impls/borrows.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -537,8 +537,8 @@ impl<'a, 'gcx, 'tcx> ActiveBorrows<'a, 'gcx, 'tcx> {
537537
Some(_) => None,
538538
None => {
539539
match self.0.region_span_map.get(region) {
540-
Some(span) => Some(span.end_point()),
541-
None => Some(self.0.mir.span.end_point())
540+
Some(span) => Some(self.0.tcx.sess.codemap().end_point(*span)),
541+
None => Some(self.0.tcx.sess.codemap().end_point(self.0.mir.span))
542542
}
543543
}
544544
}

src/librustc_resolve/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2791,8 +2791,8 @@ impl<'a> Resolver<'a> {
27912791
if let Some(sp) = self.current_type_ascription.last() {
27922792
let mut sp = *sp;
27932793
loop { // try to find the `:`, bail on first non-':'/non-whitespace
2794-
sp = sp.next_point();
2795-
if let Ok(snippet) = cm.span_to_snippet(sp.to(sp.next_point())) {
2794+
sp = cm.next_point(sp);
2795+
if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) {
27962796
debug!("snippet {:?}", snippet);
27972797
let line_sp = cm.lookup_char_pos(sp.hi()).line;
27982798
let line_base_sp = cm.lookup_char_pos(base_span.lo()).line;

src/librustc_typeck/check/mod.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -2410,7 +2410,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
24102410
err.span_label(def_s, "defined here");
24112411
}
24122412
if sugg_unit {
2413-
let sugg_span = expr_sp.end_point();
2413+
let sugg_span = sess.codemap().end_point(expr_sp);
24142414
// remove closing `)` from the span
24152415
let sugg_span = sugg_span.with_hi(sugg_span.lo());
24162416
err.span_suggestion(
@@ -4400,10 +4400,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
44004400
/// statement and the return type has been left as default or has been specified as `()`. If so,
44014401
/// it suggests adding a semicolon.
44024402
fn suggest_missing_semicolon(&self,
4403-
err: &mut DiagnosticBuilder<'tcx>,
4404-
expression: &'gcx hir::Expr,
4405-
expected: Ty<'tcx>,
4406-
cause_span: Span) {
4403+
err: &mut DiagnosticBuilder<'tcx>,
4404+
expression: &'gcx hir::Expr,
4405+
expected: Ty<'tcx>,
4406+
cause_span: Span) {
44074407
if expected.is_nil() {
44084408
// `BlockTailExpression` only relevant if the tail expr would be
44094409
// useful on its own.
@@ -4415,7 +4415,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
44154415
hir::ExprLoop(..) |
44164416
hir::ExprMatch(..) |
44174417
hir::ExprBlock(..) => {
4418-
let sp = cause_span.next_point();
4418+
let sp = self.tcx.sess.codemap().next_point(cause_span);
44194419
err.span_suggestion(sp,
44204420
"try adding a semicolon",
44214421
";".to_string());

src/libsyntax/codemap.rs

+37
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub use self::ExpnFormat::*;
2525
use rustc_data_structures::fx::FxHashMap;
2626
use rustc_data_structures::stable_hasher::StableHasher;
2727
use std::cell::{RefCell, Ref};
28+
use std::cmp;
2829
use std::hash::Hash;
2930
use std::path::{Path, PathBuf};
3031
use std::rc::Rc;
@@ -607,6 +608,42 @@ impl CodeMap {
607608
self.span_until_char(sp, '{')
608609
}
609610

611+
/// Returns a new span representing just the end-point of this span
612+
pub fn end_point(&self, sp: Span) -> Span {
613+
let hi = sp.hi().0.checked_sub(1).unwrap_or(sp.hi().0);
614+
let hi = self.get_start_of_char_bytepos(BytePos(hi));
615+
let lo = cmp::max(hi.0, sp.lo().0);
616+
sp.with_lo(BytePos(lo))
617+
}
618+
619+
/// Returns a new span representing the next character after the end-point of this span
620+
pub fn next_point(&self, sp: Span) -> Span {
621+
let hi = sp.lo().0.checked_add(1).unwrap_or(sp.lo().0);
622+
let hi = self.get_start_of_char_bytepos(BytePos(hi));
623+
let lo = cmp::max(sp.hi().0, hi.0);
624+
Span::new(BytePos(lo), BytePos(lo), sp.ctxt())
625+
}
626+
627+
fn get_start_of_char_bytepos(&self, bpos: BytePos) -> BytePos {
628+
let idx = self.lookup_filemap_idx(bpos);
629+
let files = self.files.borrow();
630+
let map = &(*files)[idx];
631+
632+
for mbc in map.multibyte_chars.borrow().iter() {
633+
if mbc.pos < bpos {
634+
if bpos.to_usize() >= mbc.pos.to_usize() + mbc.bytes {
635+
// If we do, then return the start of the character.
636+
return mbc.pos;
637+
}
638+
} else {
639+
break;
640+
}
641+
}
642+
643+
// If this isn't a multibyte character, return the original position.
644+
return bpos;
645+
}
646+
610647
pub fn get_filemap(&self, filename: &FileName) -> Option<Rc<FileMap>> {
611648
for fm in self.files.borrow().iter() {
612649
if *filename == fm.name {

src/libsyntax/parse/parser.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -702,13 +702,15 @@ impl<'a> Parser<'a> {
702702
expect.clone()
703703
};
704704
(format!("expected one of {}, found `{}`", expect, actual),
705-
(self.prev_span.next_point(), format!("expected one of {} here", short_expect)))
705+
(self.sess.codemap().next_point(self.prev_span),
706+
format!("expected one of {} here", short_expect)))
706707
} else if expected.is_empty() {
707708
(format!("unexpected token: `{}`", actual),
708709
(self.prev_span, "unexpected token after this".to_string()))
709710
} else {
710711
(format!("expected {}, found `{}`", expect, actual),
711-
(self.prev_span.next_point(), format!("expected {} here", expect)))
712+
(self.sess.codemap().next_point(self.prev_span),
713+
format!("expected {} here", expect)))
712714
};
713715
let mut err = self.fatal(&msg_exp);
714716
let sp = if self.token == token::Token::Eof {
@@ -3205,7 +3207,7 @@ impl<'a> Parser<'a> {
32053207
// return. This won't catch blocks with an explicit `return`, but that would be caught by
32063208
// the dead code lint.
32073209
if self.eat_keyword(keywords::Else) || !cond.returns() {
3208-
let sp = lo.next_point();
3210+
let sp = self.sess.codemap().next_point(lo);
32093211
let mut err = self.diagnostic()
32103212
.struct_span_err(sp, "missing condition for `if` statemement");
32113213
err.span_label(sp, "expected if condition here");

src/libsyntax_pos/lib.rs

-16
Original file line numberDiff line numberDiff line change
@@ -216,22 +216,6 @@ impl Span {
216216
self.data().with_ctxt(ctxt)
217217
}
218218

219-
/// Returns a new span representing just the end-point of this span
220-
pub fn end_point(self) -> Span {
221-
let span = self.data();
222-
// We can avoid an ICE by checking if subtraction would cause an overflow.
223-
let hi = if span.hi.0 == u32::min_value() { span.hi.0 } else { span.hi.0 - 1 };
224-
let lo = cmp::max(hi, span.lo.0);
225-
span.with_lo(BytePos(lo))
226-
}
227-
228-
/// Returns a new span representing the next character after the end-point of this span
229-
pub fn next_point(self) -> Span {
230-
let span = self.data();
231-
let lo = cmp::max(span.hi.0, span.lo.0 + 1);
232-
Span::new(BytePos(lo), BytePos(lo), span.ctxt)
233-
}
234-
235219
/// Returns `self` if `self` is not the dummy span, and `other` otherwise.
236220
pub fn substitute_dummy(self, other: Span) -> Span {
237221
if self.source_equal(&DUMMY_SP) { other } else { self }

0 commit comments

Comments
 (0)