diff options
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/item.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/path.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_parse/src/parser/ty.rs | 21 | ||||
| -rw-r--r-- | src/test/ui/fn/fn-fat-arrow-return.fixed | 18 | ||||
| -rw-r--r-- | src/test/ui/fn/fn-fat-arrow-return.rs | 18 | ||||
| -rw-r--r-- | src/test/ui/fn/fn-fat-arrow-return.stderr | 8 | ||||
| -rw-r--r-- | src/test/ui/fn/fn-fat-arrow-return2.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/fn/fn-fat-arrow-return2.stderr | 14 |
9 files changed, 96 insertions, 6 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 93be478fc8c..790a0c867af 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1,5 +1,5 @@ use super::pat::{GateOr, PARAM_EXPECTED}; -use super::ty::{AllowPlus, RecoverQPath}; +use super::ty::{AllowPlus, RecoverFatArrow, RecoverQPath}; use super::{BlockMode, Parser, PathStyle, Restrictions, TokenType}; use super::{SemiColonMode, SeqSep, TokenExpectType}; use crate::maybe_recover_from_interpolated_ty_qpath; @@ -1647,7 +1647,7 @@ impl<'a> Parser<'a> { self.expect_or()?; args }; - let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes)?; + let output = self.parse_ret_ty(AllowPlus::Yes, RecoverQPath::Yes, RecoverFatArrow::Yes)?; Ok(P(FnDecl { inputs, output })) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 5954b370e6d..9e342a0d681 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1,5 +1,5 @@ use super::diagnostics::{dummy_arg, ConsumeClosingDelim, Error}; -use super::ty::{AllowPlus, RecoverQPath}; +use super::ty::{AllowPlus, RecoverFatArrow, RecoverQPath}; use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; @@ -1648,7 +1648,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P<FnDecl>> { Ok(P(FnDecl { inputs: self.parse_fn_params(req_name)?, - output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes)?, + output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, RecoverFatArrow::Yes)?, })) } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 17e5bcf7605..311a4829fcf 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -1,4 +1,4 @@ -use super::ty::{AllowPlus, RecoverQPath}; +use super::ty::{AllowPlus, RecoverFatArrow, RecoverQPath}; use super::{Parser, TokenType}; use crate::maybe_whole; use rustc_ast::ptr::P; @@ -231,7 +231,8 @@ impl<'a> Parser<'a> { // `(T, U) -> R` let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?; let span = ident.span.to(self.prev_token.span); - let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No)?; + let output = + self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverFatArrow::No)?; ParenthesizedArgs { inputs, output, span }.into() }; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 7a6ebca4e15..ff19c5cfa85 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -43,6 +43,12 @@ pub(super) enum RecoverQPath { No, } +#[derive(PartialEq)] +pub(super) enum RecoverFatArrow { + Yes, + No, +} + // Is `...` (`CVarArgs`) legal at this level of type parsing? #[derive(PartialEq)] enum AllowCVariadic { @@ -87,11 +93,26 @@ impl<'a> Parser<'a> { &mut self, allow_plus: AllowPlus, recover_qpath: RecoverQPath, + recover_fat_arrow: RecoverFatArrow, ) -> PResult<'a, FnRetTy> { Ok(if self.eat(&token::RArrow) { // FIXME(Centril): Can we unconditionally `allow_plus`? let ty = self.parse_ty_common(allow_plus, recover_qpath, AllowCVariadic::No)?; FnRetTy::Ty(ty) + } else if recover_fat_arrow == RecoverFatArrow::Yes && self.token == token::FatArrow { + // Don't `eat` to prevent `=>` from being added as an expected token which isn't + // actually expected and could only confuse users + self.bump(); + self.struct_span_err(self.prev_token.span, "return types are denoted using `->`") + .span_suggestion_short( + self.prev_token.span, + "use `->` instead", + "->".to_string(), + Applicability::MachineApplicable, + ) + .emit(); + let ty = self.parse_ty_common(allow_plus, recover_qpath, AllowCVariadic::No)?; + FnRetTy::Ty(ty) } else { FnRetTy::Default(self.token.span.shrink_to_lo()) }) diff --git a/src/test/ui/fn/fn-fat-arrow-return.fixed b/src/test/ui/fn/fn-fat-arrow-return.fixed new file mode 100644 index 00000000000..0acca85aa67 --- /dev/null +++ b/src/test/ui/fn/fn-fat-arrow-return.fixed @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(unused)] +fn a() -> usize { 0 } +//~^ ERROR return types are denoted using `->` + +fn bar(_: u32) {} + +fn baz() -> *const dyn Fn(u32) { unimplemented!() } + +fn foo() { + match () { + _ if baz() == &bar as &dyn Fn(u32) => (), + () => (), + } +} + +fn main() { +} diff --git a/src/test/ui/fn/fn-fat-arrow-return.rs b/src/test/ui/fn/fn-fat-arrow-return.rs new file mode 100644 index 00000000000..4bdcd70d7fc --- /dev/null +++ b/src/test/ui/fn/fn-fat-arrow-return.rs @@ -0,0 +1,18 @@ +// run-rustfix +#![allow(unused)] +fn a() => usize { 0 } +//~^ ERROR return types are denoted using `->` + +fn bar(_: u32) {} + +fn baz() -> *const dyn Fn(u32) { unimplemented!() } + +fn foo() { + match () { + _ if baz() == &bar as &dyn Fn(u32) => (), + () => (), + } +} + +fn main() { +} diff --git a/src/test/ui/fn/fn-fat-arrow-return.stderr b/src/test/ui/fn/fn-fat-arrow-return.stderr new file mode 100644 index 00000000000..1fcdb18a514 --- /dev/null +++ b/src/test/ui/fn/fn-fat-arrow-return.stderr @@ -0,0 +1,8 @@ +error: return types are denoted using `->` + --> $DIR/fn-fat-arrow-return.rs:3:8 + | +LL | fn a() => usize { 0 } + | ^^ help: use `->` instead + +error: aborting due to previous error + diff --git a/src/test/ui/fn/fn-fat-arrow-return2.rs b/src/test/ui/fn/fn-fat-arrow-return2.rs new file mode 100644 index 00000000000..316fa2cbf02 --- /dev/null +++ b/src/test/ui/fn/fn-fat-arrow-return2.rs @@ -0,0 +1,10 @@ +fn a() => impl Fn() => bool { + //~^ ERROR return types are denoted using `->` + //~| ERROR expected `;` or `{`, found `=>` + unimplemented!() +} + +fn main() { + let foo = |a: bool| => bool { a }; + dbg!(foo(false)); +} diff --git a/src/test/ui/fn/fn-fat-arrow-return2.stderr b/src/test/ui/fn/fn-fat-arrow-return2.stderr new file mode 100644 index 00000000000..a6f9fe3b573 --- /dev/null +++ b/src/test/ui/fn/fn-fat-arrow-return2.stderr @@ -0,0 +1,14 @@ +error: return types are denoted using `->` + --> $DIR/fn-fat-arrow-return2.rs:1:8 + | +LL | fn a() => impl Fn() => bool { + | ^^ help: use `->` instead + +error: expected `;` or `{`, found `=>` + --> $DIR/fn-fat-arrow-return2.rs:1:21 + | +LL | fn a() => impl Fn() => bool { + | ^^ expected `;` or `{` + +error: aborting due to 2 previous errors + |
