diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 743e60d2f3bb2..75cb6eecbc675 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -960,7 +960,7 @@ impl Token { } pub fn is_non_reserved_ident(&self) -> bool { - self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !Ident::is_reserved(id)) + self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !id.is_reserved()) } /// Returns `true` if the token is the identifier `true` or `false`. diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d9f03342e1047..304845acf20e2 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{ DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN, PATTERNS_IN_FNS_WITHOUT_BODY, UNUSED_VISIBILITIES, }; -use rustc_span::{Ident, Span, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use rustc_target::spec::{AbiMap, AbiMapping}; use thin_vec::thin_vec; @@ -256,7 +256,10 @@ impl<'a> AstValidator<'a> { fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option, bool)) { for Param { pat, .. } in &decl.inputs { match pat.kind { - PatKind::Missing | PatKind::Ident(BindingMode::NONE, _, None) | PatKind::Wild => {} + PatKind::Missing + | PatKind::Ident(BindingMode::NONE, _, None) + | PatKind::Wild + | PatKind::Err(ErrorGuaranteed { .. }) => {} PatKind::Ident(BindingMode::MUT, ident, None) => { report_err(pat.span, Some(ident), true) } diff --git a/compiler/rustc_error_codes/src/error_codes/E0642.md b/compiler/rustc_error_codes/src/error_codes/E0642.md index c790aa154bde9..6622a43e99644 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0642.md +++ b/compiler/rustc_error_codes/src/error_codes/E0642.md @@ -1,4 +1,6 @@ -Trait methods currently cannot take patterns as arguments. + + +Trait methods currently cannot take patterns as parameters. Erroneous code example: diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index 4043b9bca61c5..93d180b1ea47b 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1823,16 +1823,17 @@ pub(crate) struct AttributeOnEmptyType { } #[derive(Diagnostic)] -#[diag("patterns aren't allowed in methods without bodies", code = E0642)] -pub(crate) struct PatternMethodParamWithoutBody { +#[diag("parameters can't have complex patterns in {$context}", code = E0642)] +pub(crate) struct ComplexParamPat { #[primary_span] #[suggestion( - "give this argument a name or use an underscore to ignore it", + "give this parameter a name or use an underscore to ignore it", code = "_", applicability = "machine-applicable", style = "verbose" )] pub span: Span, + pub context: &'static str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/asm.rs b/compiler/rustc_parse/src/parser/asm.rs index 3fab234adaad4..677fcb24b240d 100644 --- a/compiler/rustc_parse/src/parser/asm.rs +++ b/compiler/rustc_parse/src/parser/asm.rs @@ -235,8 +235,9 @@ pub fn parse_asm_args<'a>( } // Parse operand names. - let name = if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) { - let (ident, _) = p.token.ident().unwrap(); + let name = if let Some((ident, _)) = p.token.ident() + && p.look_ahead(1, |t| *t == token::Eq) + { p.bump(); p.expect(exp!(Eq))?; allow_templates = false; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 47ac91feefd4b..bd5bb90d27d5f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -29,15 +29,15 @@ use super::{ use crate::errors::{ AddParen, AmbiguousPlus, AsyncMoveBlockIn2015, AsyncUseBlockIn2015, AttributeOnParamType, AwaitSuggestion, BadQPathStage2, BadTypePlus, BadTypePlusSub, ColonAsSemi, - ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg, + ComparisonOperatorsCannotBeChained, ComparisonOperatorsCannotBeChainedSugg, ComplexParamPat, DocCommentDoesNotDocumentAnything, DocCommentOnParamType, DoubleColonInBound, ExpectedIdentifier, ExpectedSemi, ExpectedSemiSugg, GenericParamsWithoutAngleBrackets, GenericParamsWithoutAngleBracketsSugg, HelpIdentifierStartsWithNumber, HelpUseLatestEdition, InInTypo, IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, IncorrectUseOfUse, - MisspelledKw, PatternMethodParamWithoutBody, QuestionMarkInType, QuestionMarkInTypeSugg, - SelfParamNotFirst, StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, - SuggAddMissingLetStmt, SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, - TernaryOperatorSuggestion, UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, + MisspelledKw, QuestionMarkInType, QuestionMarkInTypeSugg, SelfParamNotFirst, + StructLiteralBodyWithoutPath, StructLiteralBodyWithoutPathSugg, SuggAddMissingLetStmt, + SuggEscapeIdentifier, SuggRemoveComma, TernaryOperator, TernaryOperatorSuggestion, + UnexpectedConstInGenericParam, UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets, UseEqInstead, WrapType, }; use crate::exp; @@ -2267,6 +2267,7 @@ impl<'a> Parser<'a> { if matches!(fn_parse_mode.context, crate::parser::item::FnContext::Trait) && (fn_parse_mode.req_name)(ed, IsDotDotDot::No) { + // FIXME: and beyond err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)"); } }; @@ -2385,16 +2386,23 @@ impl<'a> Parser<'a> { } #[cold] - pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (Box, Box)> { - let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; + pub(super) fn recover_complex_param_pat( + &mut self, + context: FnContext, + ) -> PResult<'a, (Box, Box)> { + let pat = self.parse_pat_no_top_alt(Some(Expected::TyOrParamName), None)?; self.expect(exp!(Colon))?; let ty = self.parse_ty()?; - self.dcx().emit_err(PatternMethodParamWithoutBody { span: pat.span }); + let context = match context { + FnContext::FnPtrTy => "function pointer types", + FnContext::Trait => "associated functions in traits in Rust 2015", + _ => unreachable!(), + }; + let guar = self.dcx().emit_err(ComplexParamPat { span: pat.span, context }); - // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. let pat = Box::new(Pat { - kind: PatKind::Wild, + kind: PatKind::Err(guar), span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None, diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 35c271cb70204..ad5a2ea69d4a0 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2608,7 +2608,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let attrs = self.parse_outer_attributes()?; self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| { - let pat = Box::new(this.parse_pat_no_top_alt(Some(Expected::ParameterName), None)?); + let pat = Box::new(this.parse_pat_no_top_alt(Some(Expected::ParamName), None)?); let ty = if this.eat(exp!(Colon)) { this.parse_ty()? } else { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index bd45bbb6a8582..afbc36ee8f0cf 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -4,7 +4,7 @@ use std::mem; use ast::token::IdentIsRaw; use rustc_ast as ast; use rustc_ast::ast::*; -use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; +use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::util::case::Case; use rustc_ast_pretty::pprust; @@ -2687,12 +2687,10 @@ pub(crate) struct FnParseMode { /// FIXME(estebank, xizheyin): Use more variants. #[derive(Clone, Copy, PartialEq, Eq)] pub(crate) enum FnContext { - /// Free context. Free, - /// A Trait context. Trait, - /// An Impl block. Impl, + FnPtrTy, } /// Parsing of functions and methods. @@ -3336,6 +3334,7 @@ impl<'a> Parser<'a> { &mut self, fn_parse_mode: &FnParseMode, first_param: bool, + // FIXME(fmease): rename arg -> param recover_arg_parse: bool, ) -> PResult<'a, Param> { let lo = self.token.span; @@ -3368,6 +3367,7 @@ impl<'a> Parser<'a> { } else { is_name_required }; + let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); let (pat, colon) = this.parse_fn_param_pat_colon()?; @@ -3391,6 +3391,7 @@ impl<'a> Parser<'a> { (pat, this.parse_ty_for_param()?) } else { debug!("parse_param_general ident_to_pat"); + // FIXME: This creates a snapshot in the happy path! let parser_snapshot_before_ty = this.create_snapshot_for_diagnostic(); this.eat_incorrect_doc_comment_for_param_type(); let mut ty = this.parse_ty_for_param(); @@ -3427,7 +3428,7 @@ impl<'a> Parser<'a> { // 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()? + this.recover_complex_param_pat(fn_parse_mode.context)? } Err(err) => return Err(err), } @@ -3590,21 +3591,21 @@ impl<'a> Parser<'a> { Ok(Some(Param::from_self(AttrVec::default(), eself, eself_ident))) } + // FIXME(fmease): Better name. fn is_named_param(&self) -> bool { - let offset = match &self.token.kind { - token::OpenInvisible(origin) => match origin { - InvisibleOrigin::MetaVar(MetaVarKind::Pat(_)) => { - return self.check_noexpect_past_close_delim(&token::Colon); - } - _ => 0, - }, - token::And | token::AndAnd => 1, - _ if self.token.is_keyword(kw::Mut) => 1, - _ => 0, - }; + if let token::OpenInvisible(InvisibleOrigin::MetaVar(MetaVarKind::Pat(_))) = self.token.kind + { + return self.check_noexpect_past_close_delim(&token::Colon); + } + + fn is_param_name(t: &Token) -> bool { + !t.is_non_raw_ident_where(|ident| ident.name != kw::Underscore && ident.is_reserved()) + } + + let offset = if self.token.is_keyword(kw::Mut) { 1 } else { 0 }; - self.look_ahead(offset, |t| t.is_ident()) - && self.look_ahead(offset + 1, |t| t == &token::Colon) + self.look_ahead(offset, is_param_name) + && self.look_ahead(offset + 1, |t| t.kind == token::Colon) } fn recover_self_param(&mut self) -> bool { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 4e6d76fefd9c2..79efa7b9e4056 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -34,20 +34,20 @@ use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; #[derive(PartialEq, Copy, Clone)] pub enum Expected { - ParameterName, - ArgumentName, - Identifier, - BindingPattern, + ParamName, + TyOrParamName, + Ident, + BindingPat, } impl Expected { // FIXME(#100717): migrate users of this to proper localization fn to_string_or_fallback(expected: Option) -> &'static str { match expected { - Some(Expected::ParameterName) => "parameter name", - Some(Expected::ArgumentName) => "argument name", - Some(Expected::Identifier) => "identifier", - Some(Expected::BindingPattern) => "binding pattern", + Some(Expected::ParamName) => "parameter name", + Some(Expected::TyOrParamName) => "type or parameter name", + Some(Expected::Ident) => "identifier", + Some(Expected::BindingPat) => "binding pattern", None => "pattern", } } @@ -319,7 +319,7 @@ impl<'a> Parser<'a> { } self.parse_pat_before_ty( - Some(Expected::ParameterName), + Some(Expected::ParamName), RecoverComma::No, PatternLocation::FunctionParameter, ) @@ -908,7 +908,7 @@ impl<'a> Parser<'a> { // A typoed rest pattern `...`. self.bump(); // `...` - if let Some(Expected::ParameterName) = expected { + if let Some(Expected::ParamName) = expected { // We have `...` in a closure argument, likely meant to be var-arg, which aren't // supported in closures (#146489). PatKind::Err(self.dcx().emit_err(DotDotDotRestPattern { @@ -1092,7 +1092,7 @@ impl<'a> Parser<'a> { } // Parse the pattern we hope to be an identifier. - let mut pat = self.parse_pat_no_top_alt(Some(Expected::Identifier), None)?; + let mut pat = self.parse_pat_no_top_alt(Some(Expected::Ident), None)?; // If we don't have `mut $ident (@ pat)?`, error. if let PatKind::Ident(BindingMode(br @ ByRef::No, m @ Mutability::Not), ..) = &mut pat.kind @@ -1370,7 +1370,7 @@ impl<'a> Parser<'a> { } let sub = if self.eat(exp!(At)) { - Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)) + Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPat), None)?)) } else { None }; @@ -1488,7 +1488,7 @@ impl<'a> Parser<'a> { // We cannot use `parse_pat_ident()` since it will complain `box` // is not an identifier. let sub = if self.eat(exp!(At)) { - Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPattern), None)?)) + Some(Box::new(self.parse_pat_no_top_alt(Some(Expected::BindingPat), None)?)) } else { None }; diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index b5151cf20ab02..f1e822e40c535 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -903,7 +903,7 @@ impl<'a> Parser<'a> { } let mode = crate::parser::item::FnParseMode { req_name: |_, _| false, - context: FnContext::Free, + context: FnContext::FnPtrTy, req_body: false, }; let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?; diff --git a/tests/ui/error-codes/E0642.fixed b/tests/ui/error-codes/E0642.fixed index 499c9b2024137..12a7c3ab59650 100644 --- a/tests/ui/error-codes/E0642.fixed +++ b/tests/ui/error-codes/E0642.fixed @@ -1,5 +1,6 @@ //@ edition:2015 //@ run-rustfix +// FIXME(fmease): Add historical context. #![allow(unused)] // for rustfix @@ -7,14 +8,16 @@ struct S; trait T { - fn foo(_: (i32, i32)); //~ ERROR patterns aren't allowed in methods without bodies - - fn bar(_: (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies - - fn method(_: S) {} //~ ERROR patterns aren't allowed in methods without bodies - - fn f(&ident: &S) {} // ok - fn g(&&ident: &&S) {} // ok + fn foo(_: (i32, i32)); + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn bar(_: (i32, i32)) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn method(_: S) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn f(_: &S) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn g(_: &&S) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 fn h(mut ident: S) {} // ok } diff --git a/tests/ui/error-codes/E0642.rs b/tests/ui/error-codes/E0642.rs index 2b7efbccd8844..4e0620b287a0a 100644 --- a/tests/ui/error-codes/E0642.rs +++ b/tests/ui/error-codes/E0642.rs @@ -1,5 +1,6 @@ //@ edition:2015 //@ run-rustfix +// FIXME(fmease): Add historical context. #![allow(unused)] // for rustfix @@ -7,14 +8,16 @@ struct S; trait T { - fn foo((x, y): (i32, i32)); //~ ERROR patterns aren't allowed in methods without bodies - - fn bar((x, y): (i32, i32)) {} //~ ERROR patterns aren't allowed in methods without bodies - - fn method(S { .. }: S) {} //~ ERROR patterns aren't allowed in methods without bodies - - fn f(&ident: &S) {} // ok - fn g(&&ident: &&S) {} // ok + fn foo((x, y): (i32, i32)); + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn bar((x, y): (i32, i32)) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn method(S { .. }: S) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn f(&ident: &S) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 + fn g(&&ident: &&S) {} + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 fn h(mut ident: S) {} // ok } diff --git a/tests/ui/error-codes/E0642.stderr b/tests/ui/error-codes/E0642.stderr index df0838567c4ce..ead97769a9262 100644 --- a/tests/ui/error-codes/E0642.stderr +++ b/tests/ui/error-codes/E0642.stderr @@ -1,39 +1,63 @@ -error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/E0642.rs:10:12 +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/E0642.rs:11:12 | LL | fn foo((x, y): (i32, i32)); | ^^^^^^ | -help: give this argument a name or use an underscore to ignore it +help: give this parameter a name or use an underscore to ignore it | LL - fn foo((x, y): (i32, i32)); LL + fn foo(_: (i32, i32)); | -error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/E0642.rs:12:12 +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/E0642.rs:13:12 | LL | fn bar((x, y): (i32, i32)) {} | ^^^^^^ | -help: give this argument a name or use an underscore to ignore it +help: give this parameter a name or use an underscore to ignore it | LL - fn bar((x, y): (i32, i32)) {} LL + fn bar(_: (i32, i32)) {} | -error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/E0642.rs:14:15 +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/E0642.rs:15:15 | LL | fn method(S { .. }: S) {} | ^^^^^^^^ | -help: give this argument a name or use an underscore to ignore it +help: give this parameter a name or use an underscore to ignore it | LL - fn method(S { .. }: S) {} LL + fn method(_: S) {} | -error: aborting due to 3 previous errors +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/E0642.rs:17:10 + | +LL | fn f(&ident: &S) {} + | ^^^^^^ + | +help: give this parameter a name or use an underscore to ignore it + | +LL - fn f(&ident: &S) {} +LL + fn f(_: &S) {} + | + +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/E0642.rs:19:10 + | +LL | fn g(&&ident: &&S) {} + | ^^^^^^^ + | +help: give this parameter a name or use an underscore to ignore it + | +LL - fn g(&&ident: &&S) {} +LL + fn g(_: &&S) {} + | + +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0642`. diff --git a/tests/ui/macros/no-patterns-in-args-macro.rs b/tests/ui/macros/no-patterns-in-args-macro.rs index b5109f9c28696..d8c56231405af 100644 --- a/tests/ui/macros/no-patterns-in-args-macro.rs +++ b/tests/ui/macros/no-patterns-in-args-macro.rs @@ -1,3 +1,6 @@ +// FIXME(fmease): Rename file name (e.g., `arg` -> `param`). +// FIXME(fmease): Add description. + macro_rules! m { ($pat: pat) => { trait Tr { diff --git a/tests/ui/macros/no-patterns-in-args-macro.stderr b/tests/ui/macros/no-patterns-in-args-macro.stderr index 0016c7953f344..dd196ad02e83e 100644 --- a/tests/ui/macros/no-patterns-in-args-macro.stderr +++ b/tests/ui/macros/no-patterns-in-args-macro.stderr @@ -1,17 +1,17 @@ error[E0642]: patterns aren't allowed in functions without bodies - --> $DIR/no-patterns-in-args-macro.rs:20:8 + --> $DIR/no-patterns-in-args-macro.rs:23:8 | LL | m!((bad, pat)); | ^^^^^^^^^^ pattern not allowed in function without body error[E0561]: patterns aren't allowed in function pointer types - --> $DIR/no-patterns-in-args-macro.rs:20:8 + --> $DIR/no-patterns-in-args-macro.rs:23:8 | LL | m!((bad, pat)); | ^^^^^^^^^^ error[E0130]: patterns aren't allowed in foreign function declarations - --> $DIR/no-patterns-in-args-macro.rs:20:8 + --> $DIR/no-patterns-in-args-macro.rs:23:8 | LL | m!((bad, pat)); | ^^^^^^^^^^ pattern not allowed in foreign function diff --git a/tests/ui/parser/issues/error-pattern-issue-50571.rs b/tests/ui/parser/issues/error-pattern-issue-50571.rs index 0c2ce6052cb80..d5c4758d831f8 100644 --- a/tests/ui/parser/issues/error-pattern-issue-50571.rs +++ b/tests/ui/parser/issues/error-pattern-issue-50571.rs @@ -1,11 +1,10 @@ // There is a regression introduced for issue #143828 //@ edition: 2015 -#![allow(dead_code)] trait Foo { fn foo([a, b]: [i32; 2]) {} - //~^ ERROR: expected `;` or `]`, found `,` - //~| ERROR: patterns aren't allowed in methods without bodies + //~^ ERROR expected `;` or `]`, found `,` + //~| ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 } fn main() {} diff --git a/tests/ui/parser/issues/error-pattern-issue-50571.stderr b/tests/ui/parser/issues/error-pattern-issue-50571.stderr index dac4b5309d23a..cbdbdfb7d3a06 100644 --- a/tests/ui/parser/issues/error-pattern-issue-50571.stderr +++ b/tests/ui/parser/issues/error-pattern-issue-50571.stderr @@ -1,5 +1,5 @@ error: expected `;` or `]`, found `,` - --> $DIR/error-pattern-issue-50571.rs:6:14 + --> $DIR/error-pattern-issue-50571.rs:5:14 | LL | fn foo([a, b]: [i32; 2]) {} | ^ expected `;` or `]` @@ -10,13 +10,13 @@ LL - fn foo([a, b]: [i32; 2]) {} LL + fn foo([a; b]: [i32; 2]) {} | -error[E0642]: patterns aren't allowed in methods without bodies - --> $DIR/error-pattern-issue-50571.rs:6:12 +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/error-pattern-issue-50571.rs:5:12 | LL | fn foo([a, b]: [i32; 2]) {} | ^^^^^^ | -help: give this argument a name or use an underscore to ignore it +help: give this parameter a name or use an underscore to ignore it | LL - fn foo([a, b]: [i32; 2]) {} LL + fn foo(_: [i32; 2]) {} diff --git a/tests/ui/pattern/no-patterns-in-args-2.rs b/tests/ui/pattern/no-patterns-in-args-2.rs index f1ed463a93a1f..d10286480bdc4 100644 --- a/tests/ui/pattern/no-patterns-in-args-2.rs +++ b/tests/ui/pattern/no-patterns-in-args-2.rs @@ -1,10 +1,13 @@ //@ edition:2015 +// FIXME(fmease): Rename file name (e.g., `arg` -> `param`). +// FIXME(fmease): Add historical context. #![deny(patterns_in_fns_without_body)] trait Tr { fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in functions without bodies //~^ WARN was previously accepted - fn f2(&arg: u8); //~ ERROR patterns aren't allowed in functions without bodies + fn f2(&arg: u8); + //~^ ERROR parameters can't have complex patterns in associated functions in traits in Rust 2015 fn g1(arg: u8); // OK fn g2(_: u8); // OK #[allow(anonymous_parameters)] diff --git a/tests/ui/pattern/no-patterns-in-args-2.stderr b/tests/ui/pattern/no-patterns-in-args-2.stderr index 3990f23038714..62dd5397275c8 100644 --- a/tests/ui/pattern/no-patterns-in-args-2.stderr +++ b/tests/ui/pattern/no-patterns-in-args-2.stderr @@ -1,11 +1,17 @@ -error[E0642]: patterns aren't allowed in functions without bodies - --> $DIR/no-patterns-in-args-2.rs:7:11 +error[E0642]: parameters can't have complex patterns in associated functions in traits in Rust 2015 + --> $DIR/no-patterns-in-args-2.rs:9:11 | LL | fn f2(&arg: u8); - | ^^^^ pattern not allowed in function without body + | ^^^^ + | +help: give this parameter a name or use an underscore to ignore it + | +LL - fn f2(&arg: u8); +LL + fn f2(_: u8); + | error: patterns aren't allowed in functions without bodies - --> $DIR/no-patterns-in-args-2.rs:5:11 + --> $DIR/no-patterns-in-args-2.rs:7:11 | LL | fn f1(mut arg: u8); | ^^^^^^^ help: remove `mut` from the parameter: `arg` @@ -13,7 +19,7 @@ LL | fn f1(mut arg: u8); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #35203 note: the lint level is defined here - --> $DIR/no-patterns-in-args-2.rs:2:9 + --> $DIR/no-patterns-in-args-2.rs:4:9 | LL | #![deny(patterns_in_fns_without_body)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/pattern/no-patterns-in-args.rs b/tests/ui/pattern/no-patterns-in-args.rs index 54836b0a3f538..4c338d3aa6b74 100644 --- a/tests/ui/pattern/no-patterns-in-args.rs +++ b/tests/ui/pattern/no-patterns-in-args.rs @@ -1,14 +1,18 @@ +// FIXME(fmease): Rename file name (e.g., `arg` -> `param`). +// FIXME(fmease): Add historical context. + extern "C" { fn f1(mut arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations fn f2(&arg: u8); //~ ERROR patterns aren't allowed in foreign function declarations fn f3(arg @ _: u8); //~ ERROR patterns aren't allowed in foreign function declarations fn g1(arg: u8); // OK fn g2(_: u8); // OK -// fn g3(u8); // Not yet + fn g3(u8); //~ ERROR expected one of } type A1 = fn(mut arg: u8); //~ ERROR patterns aren't allowed in function pointer types -type A2 = fn(&arg: u8); //~ ERROR patterns aren't allowed in function pointer types +type A2 = fn(&arg: u8); +//~^ ERROR parameters can't have complex patterns in function pointer types type B1 = fn(arg: u8); // OK type B2 = fn(_: u8); // OK type B3 = fn(u8); // OK diff --git a/tests/ui/pattern/no-patterns-in-args.stderr b/tests/ui/pattern/no-patterns-in-args.stderr index 1c2ce86646787..e6faad6155816 100644 --- a/tests/ui/pattern/no-patterns-in-args.stderr +++ b/tests/ui/pattern/no-patterns-in-args.stderr @@ -1,34 +1,55 @@ +error: expected one of `:`, `@`, or `|`, found `)` + --> $DIR/no-patterns-in-args.rs:10:13 + | +LL | fn g3(u8); + | ^ expected one of `:`, `@`, or `|` + | +help: if this is a parameter name, give it a type + | +LL | fn g3(u8: TypeName); + | ++++++++++ +help: if this is a type, explicitly ignore the parameter name + | +LL | fn g3(_: u8); + | ++ + +error[E0642]: parameters can't have complex patterns in function pointer types + --> $DIR/no-patterns-in-args.rs:14:14 + | +LL | type A2 = fn(&arg: u8); + | ^^^^ + | +help: give this parameter a name or use an underscore to ignore it + | +LL - type A2 = fn(&arg: u8); +LL + type A2 = fn(_: u8); + | + error[E0130]: patterns aren't allowed in foreign function declarations - --> $DIR/no-patterns-in-args.rs:2:11 + --> $DIR/no-patterns-in-args.rs:5:11 | LL | fn f1(mut arg: u8); | ^^^^^^^ pattern not allowed in foreign function error[E0130]: patterns aren't allowed in foreign function declarations - --> $DIR/no-patterns-in-args.rs:3:11 + --> $DIR/no-patterns-in-args.rs:6:11 | LL | fn f2(&arg: u8); | ^^^^ pattern not allowed in foreign function error[E0130]: patterns aren't allowed in foreign function declarations - --> $DIR/no-patterns-in-args.rs:4:11 + --> $DIR/no-patterns-in-args.rs:7:11 | LL | fn f3(arg @ _: u8); | ^^^^^^^ pattern not allowed in foreign function error[E0561]: patterns aren't allowed in function pointer types - --> $DIR/no-patterns-in-args.rs:10:14 + --> $DIR/no-patterns-in-args.rs:13:14 | LL | type A1 = fn(mut arg: u8); | ^^^^^^^ -error[E0561]: patterns aren't allowed in function pointer types - --> $DIR/no-patterns-in-args.rs:11:14 - | -LL | type A2 = fn(&arg: u8); - | ^^^^ - -error: aborting due to 5 previous errors +error: aborting due to 6 previous errors -Some errors have detailed explanations: E0130, E0561. +Some errors have detailed explanations: E0130, E0561, E0642. For more information about an error, try `rustc --explain E0130`.