Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion compiler/rustc_parse/src/parser/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use tracing::debug;
use super::{
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos,
};
use crate::parser::FnContext;
use crate::{errors, exp, fluent_generated as fluent};

// Public for rustfmt usage
Expand Down Expand Up @@ -200,7 +201,7 @@ impl<'a> Parser<'a> {
AttrWrapper::empty(),
true,
false,
FnParseMode { req_name: |_| true, req_body: true },
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true },
ForceCollect::No,
) {
Ok(Some(item)) => {
Expand Down
23 changes: 19 additions & 4 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use crate::errors::{
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
UseEqInstead, WrapType,
};
use crate::parser::FnContext;
use crate::parser::attr::InnerAttrPolicy;
use crate::{exp, fluent_generated as fluent};

Expand Down Expand Up @@ -2246,6 +2247,7 @@ impl<'a> Parser<'a> {
pat: Box<ast::Pat>,
require_name: bool,
first_param: bool,
fn_parse_mode: &crate::parser::item::FnParseMode,
) -> Option<Ident> {
// If we find a pattern followed by an identifier, it could be an (incorrect)
// C-style parameter declaration.
Expand All @@ -2268,7 +2270,14 @@ impl<'a> Parser<'a> {
|| self.token == token::Lt
|| self.token == token::CloseParen)
{
let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
let maybe_emit_anon_params_note = |this: &mut Self, err: &mut Diag<'_>| {
let ed = this.token.span.with_neighbor(this.prev_token.span).edition();
if matches!(fn_parse_mode.context, crate::parser::item::FnContext::Trait)
&& (fn_parse_mode.req_name)(ed)
{
err.note("anonymous parameters are removed in the 2018 edition (see RFC 1685)");
}
};

let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
match pat.kind {
Expand Down Expand Up @@ -2305,15 +2314,21 @@ impl<'a> Parser<'a> {
"_: ".to_string(),
Applicability::MachineApplicable,
);
err.note(rfc_note);
maybe_emit_anon_params_note(self, err);
}

return None;
}
};

// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
if first_param {
if first_param
// Only when the fn is a method, we emit this suggestion.
&& matches!(
fn_parse_mode.context,
FnContext::Trait | FnContext::Impl
)
{
err.span_suggestion_verbose(
self_span,
"if this is a `self` type, give it a parameter name",
Expand All @@ -2337,7 +2352,7 @@ impl<'a> Parser<'a> {
type_sugg,
Applicability::MachineApplicable,
);
err.note(rfc_note);
maybe_emit_anon_params_note(self, err);

// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
return if self.token == token::Lt { None } else { Some(ident) };
Expand Down
68 changes: 48 additions & 20 deletions compiler/rustc_parse/src/parser/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ impl<'a> Parser<'a> {

impl<'a> Parser<'a> {
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> {
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
let fn_parse_mode =
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true };
self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new))
}

Expand Down Expand Up @@ -975,16 +976,20 @@ impl<'a> Parser<'a> {
&mut self,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
let fn_parse_mode =
FnParseMode { req_name: |_| true, context: FnContext::Impl, req_body: true };
self.parse_assoc_item(fn_parse_mode, force_collect)
}

pub fn parse_trait_item(
&mut self,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
let fn_parse_mode =
FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false };
let fn_parse_mode = FnParseMode {
req_name: |edition| edition >= Edition::Edition2018,
context: FnContext::Trait,
req_body: false,
};
self.parse_assoc_item(fn_parse_mode, force_collect)
}

Expand Down Expand Up @@ -1261,7 +1266,8 @@ impl<'a> Parser<'a> {
&mut self,
force_collect: ForceCollect,
) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
let fn_parse_mode =
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: false };
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
|Item { attrs, id, span, vis, kind, tokens }| {
let kind = match ForeignItemKind::try_from(kind) {
Expand Down Expand Up @@ -2135,7 +2141,8 @@ impl<'a> Parser<'a> {
let inherited_vis =
Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
// We use `parse_fn` to get a span for the function
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
let fn_parse_mode =
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true };
match self.parse_fn(
&mut AttrVec::new(),
fn_parse_mode,
Expand Down Expand Up @@ -2403,6 +2410,9 @@ pub(crate) struct FnParseMode {
/// * The span is from Edition 2015. In particular, you can get a
/// 2015 span inside a 2021 crate using macros.
pub(super) req_name: ReqName,
/// The context in which this function is parsed, used for diagnostics.
/// This indicates the fn is a free function or method and so on.
pub(super) context: FnContext,
/// If this flag is set to `true`, then plain, semicolon-terminated function
/// prototypes are not allowed here.
///
Expand All @@ -2424,6 +2434,18 @@ pub(crate) struct FnParseMode {
pub(super) req_body: bool,
}

/// The context in which a function is parsed.
/// 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,
}

/// Parsing of functions and methods.
impl<'a> Parser<'a> {
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
Expand All @@ -2439,11 +2461,8 @@ impl<'a> Parser<'a> {
let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
let ident = self.parse_ident()?; // `foo`
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
let decl = match self.parse_fn_decl(
fn_parse_mode.req_name,
AllowPlus::Yes,
RecoverReturnSign::Yes,
) {
let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)
{
Ok(decl) => decl,
Err(old_err) => {
// If we see `for Ty ...` then user probably meant `impl` item.
Expand Down Expand Up @@ -2961,18 +2980,21 @@ impl<'a> Parser<'a> {
/// Parses the parameter list and result type of a function declaration.
pub(super) fn parse_fn_decl(
&mut self,
req_name: ReqName,
fn_parse_mode: &FnParseMode,
ret_allow_plus: AllowPlus,
recover_return_sign: RecoverReturnSign,
) -> PResult<'a, Box<FnDecl>> {
Ok(Box::new(FnDecl {
inputs: self.parse_fn_params(req_name)?,
inputs: self.parse_fn_params(fn_parse_mode)?,
output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
}))
}

/// Parses the parameter list of a function, including the `(` and `)` delimiters.
pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> {
pub(super) fn parse_fn_params(
&mut self,
fn_parse_mode: &FnParseMode,
) -> PResult<'a, ThinVec<Param>> {
let mut first_param = true;
// Parse the arguments, starting out with `self` being allowed...
if self.token != TokenKind::OpenParen
Expand All @@ -2988,7 +3010,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, true).or_else(|e| {
let param = p.parse_param_general(fn_parse_mode, 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.
Expand Down Expand Up @@ -3019,7 +3041,7 @@ impl<'a> Parser<'a> {
/// - `recover_arg_parse` is used to recover from a failed argument parse.
pub(super) fn parse_param_general(
&mut self,
req_name: ReqName,
fn_parse_mode: &FnParseMode,
first_param: bool,
recover_arg_parse: bool,
) -> PResult<'a, Param> {
Expand All @@ -3035,16 +3057,22 @@ impl<'a> Parser<'a> {

let is_name_required = match this.token.kind {
token::DotDotDot => false,
_ => req_name(this.token.span.with_neighbor(this.prev_token.span).edition()),
_ => (fn_parse_mode.req_name)(
this.token.span.with_neighbor(this.prev_token.span).edition(),
),
};
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()?;
if !colon {
let mut err = this.unexpected().unwrap_err();
return if let Some(ident) =
this.parameter_without_type(&mut err, pat, is_name_required, first_param)
{
return if let Some(ident) = this.parameter_without_type(
&mut err,
pat,
is_name_required,
first_param,
fn_parse_mode,
) {
let guar = err.emit();
Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
} else {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_parse/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::{fmt, mem, slice};
use attr_wrapper::{AttrWrapper, UsePreAttrPos};
pub use diagnostics::AttemptLocalParseRecovery;
pub(crate) use expr::ForbiddenLetReason;
pub(crate) use item::FnParseMode;
pub(crate) use item::{FnContext, FnParseMode};
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
use path::PathStyle;
use rustc_ast::token::{
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_parse/src/parser/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ use crate::errors::{
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
};
use crate::exp;
use crate::parser::{CommaRecoveryMode, ExprKind, RecoverColon, RecoverComma};
use crate::parser::{
CommaRecoveryMode, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
};

/// Specifies how to parse a path.
#[derive(Copy, Clone, PartialEq)]
Expand Down Expand Up @@ -399,7 +401,13 @@ impl<'a> Parser<'a> {

let dcx = self.dcx();
let parse_params_result = self.parse_paren_comma_seq(|p| {
let param = p.parse_param_general(|_| false, false, false);
// Inside parenthesized type arguments, we want types only, not names.
let mode = FnParseMode {
context: FnContext::Free,
req_name: |_| false,
req_body: false,
};
let param = p.parse_param_general(&mode, false, false);
param.map(move |param| {
if !matches!(param.pat.kind, PatKind::Missing) {
dcx.emit_err(FnPathFoundNamedParams {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_parse/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ use super::diagnostics::AttemptLocalParseRecovery;
use super::pat::{PatternLocation, RecoverComma};
use super::path::PathStyle;
use super::{
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
Trailing, UsePreAttrPos,
AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, Restrictions,
SemiColonMode, Trailing, UsePreAttrPos,
};
use crate::errors::{self, MalformedLoopLabel};
use crate::exp;
Expand Down Expand Up @@ -153,7 +153,7 @@ impl<'a> Parser<'a> {
attrs.clone(), // FIXME: unwanted clone of attrs
false,
true,
FnParseMode { req_name: |_| true, req_body: true },
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true },
force_collect,
)? {
self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item)))
Expand Down
14 changes: 11 additions & 3 deletions compiler/rustc_parse/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::errors::{
NestedCVariadicType, ReturnTypesUseThinArrow,
};
use crate::parser::item::FrontMatterParsingMode;
use crate::parser::{FnContext, FnParseMode};
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};

/// Signals whether parsing a type should allow `+`.
Expand Down Expand Up @@ -769,7 +770,12 @@ impl<'a> Parser<'a> {
if self.may_recover() && self.token == TokenKind::Lt {
self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
}
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
let mode = crate::parser::item::FnParseMode {
req_name: |_| false,
context: FnContext::Free,
req_body: false,
};
let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;

let decl_span = span_start.to(self.prev_token.span);
Ok(TyKind::FnPtr(Box::new(FnPtrTy {
Expand Down Expand Up @@ -1314,7 +1320,8 @@ impl<'a> Parser<'a> {
self.bump();
let args_lo = self.token.span;
let snapshot = self.create_snapshot_for_diagnostic();
match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
Ok(decl) => {
self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
Some(ast::Path {
Expand Down Expand Up @@ -1400,8 +1407,9 @@ impl<'a> Parser<'a> {

// Parse `(T, U) -> R`.
let inputs_lo = self.token.span;
let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
let inputs: ThinVec<_> =
self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
self.parse_fn_params(&mode)?.into_iter().map(|input| input.ty).collect();
let inputs_span = inputs_lo.to(self.prev_token.span);
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
let args = ast::ParenthesizedArgs {
Expand Down
1 change: 0 additions & 1 deletion tests/ui/parser/inverted-parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ fn pattern((i32, i32) (a, b)) {}
fn fizz(i32) {}
//~^ ERROR expected one of `:`, `@`
//~| HELP if this is a parameter name, give it a type
//~| HELP if this is a `self` type, give it a parameter name
//~| HELP if this is a type, explicitly ignore the parameter name

fn missing_colon(quux S) {}
Expand Down
7 changes: 1 addition & 6 deletions tests/ui/parser/inverted-parameters.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
LL | fn fizz(i32) {}
| ^ expected one of `:`, `@`, or `|`
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a `self` type, give it a parameter name
|
LL | fn fizz(self: i32) {}
| +++++
help: if this is a parameter name, give it a type
|
LL | fn fizz(i32: TypeName) {}
Expand All @@ -49,7 +44,7 @@ LL | fn fizz(_: i32) {}
| ++

error: expected one of `:`, `@`, or `|`, found `S`
--> $DIR/inverted-parameters.rs:29:23
--> $DIR/inverted-parameters.rs:28:23
|
LL | fn missing_colon(quux S) {}
| -----^
Expand Down
5 changes: 0 additions & 5 deletions tests/ui/parser/lifetime-in-pattern.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
LL | fn test(&'a str) {
| ^ expected one of `:`, `@`, or `|`
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a `self` type, give it a parameter name
|
LL | fn test(self: &'a str) {
| +++++
help: if this is a parameter name, give it a type
|
LL - fn test(&'a str) {
Expand Down
5 changes: 0 additions & 5 deletions tests/ui/parser/omitted-arg-in-item-fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
LL | fn foo(x) {
| ^ expected one of `:`, `@`, or `|`
|
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
help: if this is a `self` type, give it a parameter name
|
LL | fn foo(self: x) {
| +++++
help: if this is a parameter name, give it a type
|
LL | fn foo(x: TypeName) {
Expand Down
Loading
Loading