From 896cf8029c6a87b920e05dd569482dad6adbddfc Mon Sep 17 00:00:00 2001 From: xizheyin Date: Mon, 5 May 2025 22:56:03 +0800 Subject: [PATCH 1/2] Add ui test fn-trait-use-named-params Signed-off-by: xizheyin --- .../fn-trait-use-named-params-issue-140169.rs | 6 ++++++ ...trait-use-named-params-issue-140169.stderr | 20 +++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/fn/fn-trait-use-named-params-issue-140169.rs create mode 100644 tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr diff --git a/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs b/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs new file mode 100644 index 0000000000000..fae5f6c15193b --- /dev/null +++ b/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs @@ -0,0 +1,6 @@ +fn g(_: fn(a: u8)) {} +fn x(_: impl Fn(u8, vvvv: u8)) {} //~ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` +fn y(_: impl Fn(aaaa: u8, u8)) {} //~ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` +fn z(_: impl Fn(aaaa: u8, vvvv: u8)) {} //~ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + +fn main(){} diff --git a/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr b/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr new file mode 100644 index 0000000000000..e599afb1345f2 --- /dev/null +++ b/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr @@ -0,0 +1,20 @@ +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + --> $DIR/fn-trait-use-named-params-issue-140169.rs:2:25 + | +LL | fn x(_: impl Fn(u8, vvvv: u8)) {} + | ^ expected one of 7 possible tokens + +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + --> $DIR/fn-trait-use-named-params-issue-140169.rs:3:21 + | +LL | fn y(_: impl Fn(aaaa: u8, u8)) {} + | ^ expected one of 7 possible tokens + +error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` + --> $DIR/fn-trait-use-named-params-issue-140169.rs:4:21 + | +LL | fn z(_: impl Fn(aaaa: u8, vvvv: u8)) {} + | ^ expected one of 7 possible tokens + +error: aborting due to 3 previous errors + From b922da3586ce01a4bf174db09624a1d0a424d5d9 Mon Sep 17 00:00:00 2001 From: xizheyin Date: Tue, 6 May 2025 15:45:04 +0800 Subject: [PATCH 2/2] Use `parse_param_general` when parsing `(T, U)->R` in `parse_path_segment` Signed-off-by: xizheyin Co-authored-by: Vadim Petrochenkov --- compiler/rustc_parse/messages.ftl | 10 +++++ compiler/rustc_parse/src/errors.rs | 24 ++++++++++ compiler/rustc_parse/src/parser/item.rs | 15 +++++-- compiler/rustc_parse/src/parser/path.rs | 29 +++++++++++- .../fn-trait-use-named-params-issue-140169.rs | 14 ++++-- ...trait-use-named-params-issue-140169.stderr | 44 ++++++++++++------ ...hesized-type-arguments-ice-issue-122345.rs | 8 ++-- ...zed-type-arguments-ice-issue-122345.stderr | 45 +++++++++++++++---- .../issues/issue-103748-ICE-wrong-braces.rs | 5 +-- .../issue-103748-ICE-wrong-braces.stderr | 39 ++-------------- 10 files changed, 158 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index ac4f7ed64e22f..907368178505c 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -702,6 +702,16 @@ parse_parenthesized_lifetime_suggestion = remove the parentheses parse_path_double_colon = path separator must be a double colon .suggestion = use a double colon instead + +parse_path_found_attribute_in_params = `Trait(...)` syntax does not support attributes in parameters + .suggestion = remove the attributes + +parse_path_found_c_variadic_params = `Trait(...)` syntax does not support c_variadic parameters + .suggestion = remove the `...` + +parse_path_found_named_params = `Trait(...)` syntax does not support named parameters + .suggestion = remove the parameter name + parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies .suggestion = give this argument a name or use an underscore to ignore it diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 6a6fb0eb9b5ba..7bd78f77fa632 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1591,6 +1591,30 @@ pub(crate) struct ExpectedFnPathFoundFnKeyword { pub fn_token_span: Span, } +#[derive(Diagnostic)] +#[diag(parse_path_found_named_params)] +pub(crate) struct FnPathFoundNamedParams { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub named_param_span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_path_found_c_variadic_params)] +pub(crate) struct PathFoundCVariadicParams { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(parse_path_found_attribute_in_params)] +pub(crate) struct PathFoundAttributeInParams { + #[primary_span] + #[suggestion(applicability = "machine-applicable", code = "")] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_path_double_colon)] pub(crate) struct PathSingleColon { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 4be8a90368d29..babc55ccc0f9e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2894,7 +2894,7 @@ impl<'a> Parser<'a> { let (mut params, _) = self.parse_paren_comma_seq(|p| { p.recover_vcs_conflict_marker(); let snapshot = p.create_snapshot_for_diagnostic(); - let param = p.parse_param_general(req_name, first_param).or_else(|e| { + let param = p.parse_param_general(req_name, first_param, true).or_else(|e| { let guar = e.emit(); // When parsing a param failed, we should check to make the span of the param // not contain '(' before it. @@ -2922,7 +2922,13 @@ impl<'a> Parser<'a> { /// Parses a single function parameter. /// /// - `self` is syntactically allowed when `first_param` holds. - fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResult<'a, Param> { + /// - `recover_arg_parse` is used to recover from a failed argument parse. + pub(super) fn parse_param_general( + &mut self, + req_name: ReqName, + first_param: bool, + recover_arg_parse: bool, + ) -> PResult<'a, Param> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { @@ -2990,12 +2996,13 @@ impl<'a> Parser<'a> { // If this is a C-variadic argument and we hit an error, return the error. Err(err) if this.token == token::DotDotDot => return Err(err), Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err), - // Recover from attempting to parse the argument as a type without pattern. - Err(err) => { + Err(err) if recover_arg_parse => { + // Recover from attempting to parse the argument as a type without pattern. err.cancel(); this.restore_snapshot(parser_snapshot_before_ty); this.recover_arg_parse()? } + Err(err) => return Err(err), } }; diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 1093e4f4af0a5..9bce2fa74caa2 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -15,7 +15,11 @@ use tracing::debug; use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign}; use super::{Parser, Restrictions, TokenType}; -use crate::errors::{self, PathSingleColon, PathTripleColon}; +use crate::ast::{PatKind, TyKind}; +use crate::errors::{ + self, FnPathFoundNamedParams, PathFoundAttributeInParams, PathFoundCVariadicParams, + PathSingleColon, PathTripleColon, +}; use crate::exp; use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma}; @@ -396,7 +400,28 @@ impl<'a> Parser<'a> { snapshot = Some(self.create_snapshot_for_diagnostic()); } - let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) { + let dcx = self.dcx(); + let parse_params_result = self.parse_paren_comma_seq(|p| { + let param = p.parse_param_general(|_| false, false, false); + param.map(move |param| { + if !matches!(param.pat.kind, PatKind::Missing) { + dcx.emit_err(FnPathFoundNamedParams { + named_param_span: param.pat.span, + }); + } + if matches!(param.ty.kind, TyKind::CVarArgs) { + dcx.emit_err(PathFoundCVariadicParams { span: param.pat.span }); + } + if !param.attrs.is_empty() { + dcx.emit_err(PathFoundAttributeInParams { + span: param.attrs[0].span, + }); + } + param.ty + }) + }); + + let (inputs, _) = match parse_params_result { Ok(output) => output, Err(mut error) if prev_token_before_parsing == token::PathSep => { error.span_label( diff --git a/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs b/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs index fae5f6c15193b..218450abd4998 100644 --- a/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs +++ b/tests/ui/fn/fn-trait-use-named-params-issue-140169.rs @@ -1,6 +1,12 @@ -fn g(_: fn(a: u8)) {} -fn x(_: impl Fn(u8, vvvv: u8)) {} //~ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` -fn y(_: impl Fn(aaaa: u8, u8)) {} //~ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` -fn z(_: impl Fn(aaaa: u8, vvvv: u8)) {} //~ ERROR expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` +fn f1(_: fn(a: u8)) {} +fn f2(_: impl Fn(u8, vvvv: u8)) {} //~ ERROR `Trait(...)` syntax does not support named parameters +fn f3(_: impl Fn(aaaa: u8, u8)) {} //~ ERROR `Trait(...)` syntax does not support named parameters +fn f4(_: impl Fn(aaaa: u8, vvvv: u8)) {} +//~^ ERROR `Trait(...)` syntax does not support named parameters +//~| ERROR `Trait(...)` syntax does not support named parameters +fn f5(_: impl Fn(u8, ...)) {} +//~^ ERROR `Trait(...)` syntax does not support c_variadic parameters +fn f6(_: impl Fn(u8, #[allow(unused_attributes)] u8)) {} +//~^ ERROR `Trait(...)` syntax does not support attributes in parameters fn main(){} diff --git a/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr b/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr index e599afb1345f2..b72d5b7b3bc48 100644 --- a/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr +++ b/tests/ui/fn/fn-trait-use-named-params-issue-140169.stderr @@ -1,20 +1,38 @@ -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - --> $DIR/fn-trait-use-named-params-issue-140169.rs:2:25 +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:2:22 | -LL | fn x(_: impl Fn(u8, vvvv: u8)) {} - | ^ expected one of 7 possible tokens +LL | fn f2(_: impl Fn(u8, vvvv: u8)) {} + | ^^^^ help: remove the parameter name -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - --> $DIR/fn-trait-use-named-params-issue-140169.rs:3:21 +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:3:18 | -LL | fn y(_: impl Fn(aaaa: u8, u8)) {} - | ^ expected one of 7 possible tokens +LL | fn f3(_: impl Fn(aaaa: u8, u8)) {} + | ^^^^ help: remove the parameter name -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - --> $DIR/fn-trait-use-named-params-issue-140169.rs:4:21 +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:4:18 | -LL | fn z(_: impl Fn(aaaa: u8, vvvv: u8)) {} - | ^ expected one of 7 possible tokens +LL | fn f4(_: impl Fn(aaaa: u8, vvvv: u8)) {} + | ^^^^ help: remove the parameter name -error: aborting due to 3 previous errors +error: `Trait(...)` syntax does not support named parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:4:28 + | +LL | fn f4(_: impl Fn(aaaa: u8, vvvv: u8)) {} + | ^^^^ help: remove the parameter name + +error: `Trait(...)` syntax does not support c_variadic parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:7:22 + | +LL | fn f5(_: impl Fn(u8, ...)) {} + | ^^^ help: remove the `...` + +error: `Trait(...)` syntax does not support attributes in parameters + --> $DIR/fn-trait-use-named-params-issue-140169.rs:9:22 + | +LL | fn f6(_: impl Fn(u8, #[allow(unused_attributes)] u8)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the attributes + +error: aborting due to 6 previous errors diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs index 6bfe16ae37d27..db25ce440893d 100644 --- a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs @@ -2,8 +2,10 @@ fn main() { unsafe { - dealloc(ptr2, Layout::(x: !)(1, 1)); //~ ERROR: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - //~^ ERROR: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` - //~| NOTE while parsing this parenthesized list of type arguments starting here + dealloc(ptr2, Layout::(x: !)(1, 1)); //~ ERROR `Trait(...)` syntax does not support named parameters + //~^ ERROR cannot find function `dealloc` in this scope [E0425] + //~| ERROR cannot find value `ptr2` in this scope [E0425] + //~| ERROR the `!` type is experimental [E0658] + //~| ERROR cannot find function, tuple struct or tuple variant `Layout` in this scope [E0425] } } diff --git a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr index c12bf7f9e3f0a..a083883af219f 100644 --- a/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr +++ b/tests/ui/parser/diagnostics-parenthesized-type-arguments-ice-issue-122345.stderr @@ -1,16 +1,43 @@ -error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `:` - --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:33 +error: `Trait(...)` syntax does not support named parameters + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:32 | LL | dealloc(ptr2, Layout::(x: !)(1, 1)); - | --- ^ expected one of 7 possible tokens - | | - | while parsing this parenthesized list of type arguments starting here + | ^ help: remove the parameter name -error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` - --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:43 +error[E0425]: cannot find function `dealloc` in this scope + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:9 | LL | dealloc(ptr2, Layout::(x: !)(1, 1)); - | ^ expected one of `.`, `;`, `?`, `}`, or an operator + | ^^^^^^^ not found in this scope + | +help: consider importing this function + | +LL + use std::alloc::dealloc; + | + +error[E0425]: cannot find value `ptr2` in this scope + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:17 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^^^^ not found in this scope + +error[E0658]: the `!` type is experimental + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:35 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^ + | + = note: see issue #35121 for more information + = help: add `#![feature(never_type)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0425]: cannot find function, tuple struct or tuple variant `Layout` in this scope + --> $DIR/diagnostics-parenthesized-type-arguments-ice-issue-122345.rs:5:23 + | +LL | dealloc(ptr2, Layout::(x: !)(1, 1)); + | ^^^^^^ not found in this scope -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors +Some errors have detailed explanations: E0425, E0658. +For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs index 1c28c0632fa84..60dd88e65400a 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.rs @@ -2,7 +2,4 @@ struct Apple((Apple, Option(Banana ? Citron))); //~^ ERROR invalid `?` in type -//~| ERROR expected one of `)` or `,`, found `Citron` -//~| ERROR cannot find type `Citron` in this scope [E0412] -//~| ERROR parenthesized type parameters may only be used with a `Fn` trait [E0214] -//~| ERROR `Apple` has infinite size +//~| ERROR unexpected token: `Citron` diff --git a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr index 97a73b4fd5ed3..c92535c3906bc 100644 --- a/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr +++ b/tests/ui/parser/issues/issue-103748-ICE-wrong-braces.stderr @@ -10,44 +10,11 @@ LL - struct Apple((Apple, Option(Banana ? Citron))); LL + struct Apple((Apple, Option(Option Citron))); | -error: expected one of `)` or `,`, found `Citron` +error: unexpected token: `Citron` --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 | LL | struct Apple((Apple, Option(Banana ? Citron))); - | -^^^^^^ expected one of `)` or `,` - | | - | help: missing `,` + | ^^^^^^ unexpected token after this -error[E0412]: cannot find type `Citron` in this scope - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:38 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^ not found in this scope - -error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:22 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^^^^^^^^^^^^^^^^^^ only `Fn` traits may use parentheses - | -help: use angle brackets instead - | -LL - struct Apple((Apple, Option(Banana ? Citron))); -LL + struct Apple((Apple, Option)); - | - -error[E0072]: recursive type `Apple` has infinite size - --> $DIR/issue-103748-ICE-wrong-braces.rs:3:1 - | -LL | struct Apple((Apple, Option(Banana ? Citron))); - | ^^^^^^^^^^^^ ----- recursive without indirection - | -help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to break the cycle - | -LL | struct Apple((Box, Option(Banana ? Citron))); - | ++++ + - -error: aborting due to 5 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0072, E0214, E0412. -For more information about an error, try `rustc --explain E0072`.