From c692896ba27adc1c14941593349c76bd27e189f5 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Fri, 2 Jul 2021 17:07:32 +0200 Subject: Recover from `&dyn mut ...` parse errors --- compiler/rustc_parse/src/parser/ty.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index de5a5632600..1fbf01b1b97 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -393,7 +393,7 @@ impl<'a> Parser<'a> { let and_span = self.prev_token.span; let mut opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None }; - let mutbl = self.parse_mutability(); + let mut mutbl = self.parse_mutability(); if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() { // A lifetime is invalid here: it would be part of a bare trait bound, which requires // it to be followed by a plus, but we disallow plus in the pointee type. @@ -417,6 +417,26 @@ impl<'a> Parser<'a> { opt_lifetime = Some(self.expect_lifetime()); } + } else if self.token.is_keyword(kw::Dyn) + && mutbl == Mutability::Not + && self.look_ahead(1, |t| t.is_keyword(kw::Mut)) + { + // We have `&dyn mut ...`, which is invalid and should be `&mut dyn ...`. + let span = and_span.to(self.look_ahead(1, |t| t.span)); + let mut err = self.struct_span_err(span, "`mut` must precede `dyn`"); + err.span_suggestion( + span, + "place `mut` before `dyn`", + "&mut dyn".to_string(), + Applicability::MachineApplicable, + ); + err.emit(); + + // Recovery + mutbl = Mutability::Mut; + let (dyn_tok, dyn_tok_sp) = (self.token.clone(), self.token_spacing); + self.bump(); + self.bump_with((dyn_tok, dyn_tok_sp)); } let ty = self.parse_ty_no_plus()?; Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl })) -- cgit 1.4.1-3-g733a5 From 04a9c10fc27fcf7c4a4415401c7653a361177631 Mon Sep 17 00:00:00 2001 From: Ryan Levick Date: Wed, 7 Jul 2021 14:25:40 +0200 Subject: Fix ICE when misplaced visibility cannot be properly parsed --- compiler/rustc_parse/src/parser/item.rs | 8 +++++++- src/test/ui/parser/issue-86895.rs | 3 +++ src/test/ui/parser/issue-86895.stderr | 8 ++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/issue-86895.rs create mode 100644 src/test/ui/parser/issue-86895.stderr (limited to 'compiler/rustc_parse/src/parser') diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2daa9e2485b..2ce63d011f4 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1791,7 +1791,13 @@ impl<'a> Parser<'a> { if self.check_keyword(kw::Pub) { let sp = sp_start.to(self.prev_token.span); if let Ok(snippet) = self.span_to_snippet(sp) { - let vis = self.parse_visibility(FollowedByType::No)?; + let vis = match self.parse_visibility(FollowedByType::No) { + Ok(v) => v, + Err(mut d) => { + d.cancel(); + return Err(err); + } + }; let vs = pprust::vis_to_string(&vis); let vs = vs.trim_end(); err.span_suggestion( diff --git a/src/test/ui/parser/issue-86895.rs b/src/test/ui/parser/issue-86895.rs new file mode 100644 index 00000000000..4cd09843107 --- /dev/null +++ b/src/test/ui/parser/issue-86895.rs @@ -0,0 +1,3 @@ +const pub () {} +//~^ ERROR expected one of `async`, `extern`, `fn`, or `unsafe` +pub fn main() {} diff --git a/src/test/ui/parser/issue-86895.stderr b/src/test/ui/parser/issue-86895.stderr new file mode 100644 index 00000000000..575d857c0ed --- /dev/null +++ b/src/test/ui/parser/issue-86895.stderr @@ -0,0 +1,8 @@ +error: expected one of `async`, `extern`, `fn`, or `unsafe`, found keyword `pub` + --> $DIR/issue-86895.rs:1:7 + | +LL | const pub () {} + | ^^^ expected one of `async`, `extern`, `fn`, or `unsafe` + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5