From 082c03b0780b2de24b68be04e96d1596a7c5b3cf Mon Sep 17 00:00:00 2001 From: Daan Sprenkels Date: Wed, 6 Jan 2016 23:58:45 +0100 Subject: [PATCH 1/6] libsyntax: note that `let a = (let b = something)` is invalid in parse_bottom_expr (parser.rs) --- src/libsyntax/parse/parser.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index bfa42e76129..edb1f7eb926 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2199,6 +2199,12 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { UnsafeBlock(ast::UserProvided), attrs); } + if self.eat_keyword(keywords::Let) { + return Err(self.span_fatal(self.span, + "`let` is not an expression, so it cannot \ + be used in this way")) + + } if self.eat_keyword(keywords::Return) { if self.token.can_begin_expr() { let e = try!(self.parse_expr()); From 79f2cff44ec62cf42f6c97d28dc4286de683b1e5 Mon Sep 17 00:00:00 2001 From: Daan Sprenkels Date: Fri, 8 Jan 2016 00:01:59 +0100 Subject: [PATCH 2/6] libsyntax: move check for keyword Let to a more logical spot --- src/libsyntax/parse/parser.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index edb1f7eb926..f3809455fe0 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2134,6 +2134,12 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { } hi = self.last_span.hi; } + _ if self.token.is_keyword(keywords::Let) => { + // Catch this syntax error here, instead of in `check_strict_keywords`, so that + // we can explicitly mention that let is not to be used as an expression + let msg = "`let` is not an expression, so it cannot be used in this way"; + return Err(self.diagnostic().struct_span_err(self.span, &msg)); + }, _ => { if self.eat_lt() { let (qself, path) = @@ -2199,12 +2205,6 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { UnsafeBlock(ast::UserProvided), attrs); } - if self.eat_keyword(keywords::Let) { - return Err(self.span_fatal(self.span, - "`let` is not an expression, so it cannot \ - be used in this way")) - - } if self.eat_keyword(keywords::Return) { if self.token.can_begin_expr() { let e = try!(self.parse_expr()); From 2b1e2732930830fc295d26bfb4bb29931e7e84ac Mon Sep 17 00:00:00 2001 From: Daan Sprenkels Date: Thu, 14 Jan 2016 16:04:35 +0100 Subject: [PATCH 3/6] Update qquote.rs test case and make unexpected `let` error fatal --- src/libsyntax/parse/parser.rs | 12 ++++++------ src/test/run-fail-fulldeps/qquote.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index f3809455fe0..c071670ea6e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2134,12 +2134,6 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { } hi = self.last_span.hi; } - _ if self.token.is_keyword(keywords::Let) => { - // Catch this syntax error here, instead of in `check_strict_keywords`, so that - // we can explicitly mention that let is not to be used as an expression - let msg = "`let` is not an expression, so it cannot be used in this way"; - return Err(self.diagnostic().struct_span_err(self.span, &msg)); - }, _ => { if self.eat_lt() { let (qself, path) = @@ -2162,6 +2156,12 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { let lo = self.last_span.lo; return self.parse_while_expr(None, lo, attrs); } + if self.token.is_keyword(keywords::Let) { + // Catch this syntax error here, instead of in `check_strict_keywords`, so + // that we can explicitly mention that let is not to be used as an expression + let msg = "`let` is not an expression, so it cannot be used in this way"; + self.span_err(self.span, msg); + } if self.token.is_lifetime() { let lifetime = self.get_lifetime(); let lo = self.span.lo; diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs index d42a777a019..297a1da25b5 100644 --- a/src/test/run-fail-fulldeps/qquote.rs +++ b/src/test/run-fail-fulldeps/qquote.rs @@ -10,7 +10,7 @@ // ignore-cross-compile -// error-pattern:expected identifier, found keyword `let` +// error-pattern:`let` is not an expression, so it cannot be used in this way #![feature(quote, rustc_private)] From 1745153eaeeb0793876b36422bda6764483ceefb Mon Sep 17 00:00:00 2001 From: Daan Sprenkels Date: Thu, 14 Jan 2016 16:52:24 +0100 Subject: [PATCH 4/6] do not additionally note about unexpected identifier after unexpected let error, by moving unexpected let check into the proper if-else clause --- src/libsyntax/parse/parser.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c071670ea6e..daa13885e0d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2156,12 +2156,6 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { let lo = self.last_span.lo; return self.parse_while_expr(None, lo, attrs); } - if self.token.is_keyword(keywords::Let) { - // Catch this syntax error here, instead of in `check_strict_keywords`, so - // that we can explicitly mention that let is not to be used as an expression - let msg = "`let` is not an expression, so it cannot be used in this way"; - self.span_err(self.span, msg); - } if self.token.is_lifetime() { let lifetime = self.get_lifetime(); let lo = self.span.lo; @@ -2224,6 +2218,11 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { ex = ExprBreak(None); } hi = self.last_span.hi; + } else if self.token.is_keyword(keywords::Let) { + // Catch this syntax error here, instead of in `check_strict_keywords`, so + // that we can explicitly mention that let is not to be used as an expression + let msg = "`let` is not an expression, so it cannot be used in this way"; + return Err(self.fatal(&msg)); } else if self.check(&token::ModSep) || self.token.is_ident() && !self.check_keyword(keywords::True) && From d829019ff4874e2a4f1b6780c442dfa524e75d38 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 26 Jan 2016 13:49:21 +0530 Subject: [PATCH 5/6] Make emitter handle DUMMY_SP correctly --- src/libsyntax/errors/emitter.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/errors/emitter.rs b/src/libsyntax/errors/emitter.rs index c21bf1e6a1f..51013d68930 100644 --- a/src/libsyntax/errors/emitter.rs +++ b/src/libsyntax/errors/emitter.rs @@ -10,7 +10,7 @@ use self::Destination::*; -use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, Pos, Span}; +use codemap::{self, COMMAND_LINE_SP, COMMAND_LINE_EXPN, DUMMY_SP, Pos, Span}; use diagnostics; use errors::{Level, RenderSpan, DiagnosticBuilder}; @@ -109,8 +109,8 @@ fn emit(&mut self, lvl: Level) { let error = match sp { Some(COMMAND_LINE_SP) => self.emit_(FileLine(COMMAND_LINE_SP), msg, code, lvl), + Some(DUMMY_SP) | None => print_diagnostic(&mut self.dst, "", lvl, msg, code), Some(sp) => self.emit_(FullSpan(sp), msg, code, lvl), - None => print_diagnostic(&mut self.dst, "", lvl, msg, code), }; if let Err(e) = error { From 065e47eb3b23a9bd3074d3406157f0aafc575150 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 26 Jan 2016 13:53:28 +0530 Subject: [PATCH 6/6] Improve error message for let-in-expr-position --- src/libsyntax/parse/parser.rs | 5 +++-- src/test/run-fail-fulldeps/qquote.rs | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index daa13885e0d..4ee3ce63a8d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2221,8 +2221,9 @@ fn parse_bottom_expr(&mut self) -> PResult<'a, P> { } else if self.token.is_keyword(keywords::Let) { // Catch this syntax error here, instead of in `check_strict_keywords`, so // that we can explicitly mention that let is not to be used as an expression - let msg = "`let` is not an expression, so it cannot be used in this way"; - return Err(self.fatal(&msg)); + let mut db = self.fatal("expected expression, found statement (`let`)"); + db.note("variable declaration using `let` is a statement"); + return Err(db); } else if self.check(&token::ModSep) || self.token.is_ident() && !self.check_keyword(keywords::True) && diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs index 297a1da25b5..41a6fd05c37 100644 --- a/src/test/run-fail-fulldeps/qquote.rs +++ b/src/test/run-fail-fulldeps/qquote.rs @@ -10,7 +10,7 @@ // ignore-cross-compile -// error-pattern:`let` is not an expression, so it cannot be used in this way +// error-pattern:expected expression, found statement (`let`) #![feature(quote, rustc_private)]