Skip to content
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

Accept tuple.0.0 as tuple indexing #70420

Closed
wants to merge 9 commits into from
19 changes: 17 additions & 2 deletions src/librustc_parse/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ impl<'a> StringReader<'a> {
/// Turns simple `rustc_lexer::TokenKind` enum into a rich
/// `librustc_ast::TokenKind`. This turns strings into interned
/// symbols and runs additional validation.
fn cook_lexer_token(&self, token: rustc_lexer::TokenKind, start: BytePos) -> TokenKind {
fn cook_lexer_token(&mut self, token: rustc_lexer::TokenKind, start: BytePos) -> TokenKind {
match token {
rustc_lexer::TokenKind::LineComment => {
let string = self.str_from(start);
Expand Down Expand Up @@ -323,7 +323,7 @@ impl<'a> StringReader<'a> {
}

fn cook_lexer_literal(
&self,
&mut self,
start: BytePos,
suffix_start: BytePos,
kind: rustc_lexer::LiteralKind,
Expand Down Expand Up @@ -440,6 +440,16 @@ impl<'a> StringReader<'a> {
_ => (),
}

// tuple.0.0
// ^^^ we truncate this "float" literal at the dot.
if self.ends_with(start, ".") && !self.ends_with(start, "..") {
if let Some(dot) = self.str_from(start).find('.') {
self.pos = start + BytePos(dot as u32);
let id = self.symbol_from(start);
return (token::Integer, id);
}
}

let id = self.symbol_from_to(start, suffix_start);
(token::Float, id)
}
Expand Down Expand Up @@ -474,6 +484,11 @@ impl<'a> StringReader<'a> {
&self.src[self.src_index(start)..self.src_index(end)]
}

/// Whether the source text leading up to position `pos` ends with `suffix`.
fn ends_with(&self, pos: BytePos, suffix: &str) -> bool {
self.src[..self.src_index(pos)].ends_with(suffix)
}

fn forbid_bare_cr(&self, start: BytePos, s: &str, errmsg: &str) {
let mut idx = 0;
loop {
Expand Down
44 changes: 0 additions & 44 deletions src/librustc_parse/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -767,9 +767,6 @@ impl<'a> Parser<'a> {
token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => {
Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix))
}
token::Literal(token::Lit { kind: token::Float, symbol, .. }) => {
self.recover_field_access_by_float_lit(lo, base, symbol)
}
_ => {
self.error_unexpected_after_dot();
Ok(base)
Expand All @@ -783,47 +780,6 @@ impl<'a> Parser<'a> {
self.struct_span_err(self.token.span, &format!("unexpected token: `{}`", actual)).emit();
}

fn recover_field_access_by_float_lit(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to see this method go; it was ungreat to refactor in the past :) 🎉

&mut self,
lo: Span,
base: P<Expr>,
sym: Symbol,
) -> PResult<'a, P<Expr>> {
self.bump();

let fstr = sym.as_str();
let msg = format!("unexpected token: `{}`", sym);

let mut err = self.struct_span_err(self.prev_token.span, &msg);
err.span_label(self.prev_token.span, "unexpected token");

if fstr.chars().all(|x| "0123456789.".contains(x)) {
let float = match fstr.parse::<f64>() {
Ok(f) => f,
Err(_) => {
err.emit();
return Ok(base);
}
};
let sugg = pprust::to_string(|s| {
s.popen();
s.print_expr(&base);
s.s.word(".");
s.print_usize(float.trunc() as usize);
s.pclose();
s.s.word(".");
s.s.word(fstr.splitn(2, '.').last().unwrap().to_string())
});
err.span_suggestion(
lo.to(self.prev_token.span),
"try parenthesizing the first index",
sugg,
Applicability::MachineApplicable,
);
}
Err(err)
}

fn parse_tuple_field_access_expr(
&mut self,
lo: Span,
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/tuple/nested-index.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// run-pass

fn main () {
let n = (1, (2, 3)).1.1;
assert_eq!(n, 3);

let n = (1, (2, (3, 4))).1.1.1;
assert_eq!(n, 4);

// This is a range expression, not nested indexing.
let _ = 0.0..1.1;
}
5 changes: 0 additions & 5 deletions src/test/ui/tuple/tuple-float-index.fixed

This file was deleted.

5 changes: 0 additions & 5 deletions src/test/ui/tuple/tuple-float-index.rs

This file was deleted.

11 changes: 0 additions & 11 deletions src/test/ui/tuple/tuple-float-index.stderr

This file was deleted.