Rollup merge of #145378 - xizheyin:144968, r=davidtwco
Add `FnContext` in parser for diagnostic Fixes rust-lang/rust#144968 Inspired by https://github.com/rust-lang/rust/issues/144968#issuecomment-3156094581, I implemented `FnContext` to indicate whether a function should have a self parameter, for example, whether the function is a trait method, whether it is in an impl block. And I removed the outdated note. I made two commits to show the difference. cc ``@estebank`` ``@djc`` r? compiler
This commit is contained in:
@@ -11,6 +11,7 @@ use tracing::debug;
|
|||||||
use super::{
|
use super::{
|
||||||
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos,
|
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos,
|
||||||
};
|
};
|
||||||
|
use crate::parser::FnContext;
|
||||||
use crate::{errors, exp, fluent_generated as fluent};
|
use crate::{errors, exp, fluent_generated as fluent};
|
||||||
|
|
||||||
// Public for rustfmt usage
|
// Public for rustfmt usage
|
||||||
@@ -200,7 +201,7 @@ impl<'a> Parser<'a> {
|
|||||||
AttrWrapper::empty(),
|
AttrWrapper::empty(),
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
FnParseMode { req_name: |_| true, req_body: true },
|
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true },
|
||||||
ForceCollect::No,
|
ForceCollect::No,
|
||||||
) {
|
) {
|
||||||
Ok(Some(item)) => {
|
Ok(Some(item)) => {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ use crate::errors::{
|
|||||||
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
|
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
|
||||||
UseEqInstead, WrapType,
|
UseEqInstead, WrapType,
|
||||||
};
|
};
|
||||||
|
use crate::parser::FnContext;
|
||||||
use crate::parser::attr::InnerAttrPolicy;
|
use crate::parser::attr::InnerAttrPolicy;
|
||||||
use crate::{exp, fluent_generated as fluent};
|
use crate::{exp, fluent_generated as fluent};
|
||||||
|
|
||||||
@@ -2246,6 +2247,7 @@ impl<'a> Parser<'a> {
|
|||||||
pat: Box<ast::Pat>,
|
pat: Box<ast::Pat>,
|
||||||
require_name: bool,
|
require_name: bool,
|
||||||
first_param: bool,
|
first_param: bool,
|
||||||
|
fn_parse_mode: &crate::parser::item::FnParseMode,
|
||||||
) -> Option<Ident> {
|
) -> Option<Ident> {
|
||||||
// If we find a pattern followed by an identifier, it could be an (incorrect)
|
// If we find a pattern followed by an identifier, it could be an (incorrect)
|
||||||
// C-style parameter declaration.
|
// C-style parameter declaration.
|
||||||
@@ -2268,7 +2270,14 @@ impl<'a> Parser<'a> {
|
|||||||
|| self.token == token::Lt
|
|| self.token == token::Lt
|
||||||
|| self.token == token::CloseParen)
|
|| 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) =
|
let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
|
||||||
match pat.kind {
|
match pat.kind {
|
||||||
@@ -2305,7 +2314,7 @@ impl<'a> Parser<'a> {
|
|||||||
"_: ".to_string(),
|
"_: ".to_string(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
err.note(rfc_note);
|
maybe_emit_anon_params_note(self, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
return None;
|
return None;
|
||||||
@@ -2313,7 +2322,13 @@ impl<'a> Parser<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
|
// `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(
|
err.span_suggestion_verbose(
|
||||||
self_span,
|
self_span,
|
||||||
"if this is a `self` type, give it a parameter name",
|
"if this is a `self` type, give it a parameter name",
|
||||||
@@ -2337,7 +2352,7 @@ impl<'a> Parser<'a> {
|
|||||||
type_sugg,
|
type_sugg,
|
||||||
Applicability::MachineApplicable,
|
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.
|
// 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) };
|
return if self.token == token::Lt { None } else { Some(ident) };
|
||||||
|
|||||||
@@ -116,7 +116,8 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Box<Item>>> {
|
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))
|
self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(Box::new))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,7 +976,8 @@ impl<'a> Parser<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
force_collect: ForceCollect,
|
force_collect: ForceCollect,
|
||||||
) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
|
) -> 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)
|
self.parse_assoc_item(fn_parse_mode, force_collect)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,8 +985,11 @@ impl<'a> Parser<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
force_collect: ForceCollect,
|
force_collect: ForceCollect,
|
||||||
) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
|
) -> PResult<'a, Option<Option<Box<AssocItem>>>> {
|
||||||
let fn_parse_mode =
|
let fn_parse_mode = FnParseMode {
|
||||||
FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false };
|
req_name: |edition| edition >= Edition::Edition2018,
|
||||||
|
context: FnContext::Trait,
|
||||||
|
req_body: false,
|
||||||
|
};
|
||||||
self.parse_assoc_item(fn_parse_mode, force_collect)
|
self.parse_assoc_item(fn_parse_mode, force_collect)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1261,7 +1266,8 @@ impl<'a> Parser<'a> {
|
|||||||
&mut self,
|
&mut self,
|
||||||
force_collect: ForceCollect,
|
force_collect: ForceCollect,
|
||||||
) -> PResult<'a, Option<Option<Box<ForeignItem>>>> {
|
) -> 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(
|
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
|
||||||
|Item { attrs, id, span, vis, kind, tokens }| {
|
|Item { attrs, id, span, vis, kind, tokens }| {
|
||||||
let kind = match ForeignItemKind::try_from(kind) {
|
let kind = match ForeignItemKind::try_from(kind) {
|
||||||
@@ -2135,7 +2141,8 @@ impl<'a> Parser<'a> {
|
|||||||
let inherited_vis =
|
let inherited_vis =
|
||||||
Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
|
Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
|
||||||
// We use `parse_fn` to get a span for the function
|
// 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(
|
match self.parse_fn(
|
||||||
&mut AttrVec::new(),
|
&mut AttrVec::new(),
|
||||||
fn_parse_mode,
|
fn_parse_mode,
|
||||||
@@ -2403,6 +2410,9 @@ pub(crate) struct FnParseMode {
|
|||||||
/// * The span is from Edition 2015. In particular, you can get a
|
/// * The span is from Edition 2015. In particular, you can get a
|
||||||
/// 2015 span inside a 2021 crate using macros.
|
/// 2015 span inside a 2021 crate using macros.
|
||||||
pub(super) req_name: ReqName,
|
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
|
/// If this flag is set to `true`, then plain, semicolon-terminated function
|
||||||
/// prototypes are not allowed here.
|
/// prototypes are not allowed here.
|
||||||
///
|
///
|
||||||
@@ -2424,6 +2434,18 @@ pub(crate) struct FnParseMode {
|
|||||||
pub(super) req_body: bool,
|
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.
|
/// Parsing of functions and methods.
|
||||||
impl<'a> Parser<'a> {
|
impl<'a> Parser<'a> {
|
||||||
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
|
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
|
||||||
@@ -2439,11 +2461,8 @@ impl<'a> Parser<'a> {
|
|||||||
let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
|
let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
|
||||||
let ident = self.parse_ident()?; // `foo`
|
let ident = self.parse_ident()?; // `foo`
|
||||||
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
|
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
|
||||||
let decl = match self.parse_fn_decl(
|
let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)
|
||||||
fn_parse_mode.req_name,
|
{
|
||||||
AllowPlus::Yes,
|
|
||||||
RecoverReturnSign::Yes,
|
|
||||||
) {
|
|
||||||
Ok(decl) => decl,
|
Ok(decl) => decl,
|
||||||
Err(old_err) => {
|
Err(old_err) => {
|
||||||
// If we see `for Ty ...` then user probably meant `impl` item.
|
// If we see `for Ty ...` then user probably meant `impl` item.
|
||||||
@@ -2961,18 +2980,21 @@ impl<'a> Parser<'a> {
|
|||||||
/// Parses the parameter list and result type of a function declaration.
|
/// Parses the parameter list and result type of a function declaration.
|
||||||
pub(super) fn parse_fn_decl(
|
pub(super) fn parse_fn_decl(
|
||||||
&mut self,
|
&mut self,
|
||||||
req_name: ReqName,
|
fn_parse_mode: &FnParseMode,
|
||||||
ret_allow_plus: AllowPlus,
|
ret_allow_plus: AllowPlus,
|
||||||
recover_return_sign: RecoverReturnSign,
|
recover_return_sign: RecoverReturnSign,
|
||||||
) -> PResult<'a, Box<FnDecl>> {
|
) -> PResult<'a, Box<FnDecl>> {
|
||||||
Ok(Box::new(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)?,
|
output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
/// 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;
|
let mut first_param = true;
|
||||||
// Parse the arguments, starting out with `self` being allowed...
|
// Parse the arguments, starting out with `self` being allowed...
|
||||||
if self.token != TokenKind::OpenParen
|
if self.token != TokenKind::OpenParen
|
||||||
@@ -2988,7 +3010,7 @@ impl<'a> Parser<'a> {
|
|||||||
let (mut params, _) = self.parse_paren_comma_seq(|p| {
|
let (mut params, _) = self.parse_paren_comma_seq(|p| {
|
||||||
p.recover_vcs_conflict_marker();
|
p.recover_vcs_conflict_marker();
|
||||||
let snapshot = p.create_snapshot_for_diagnostic();
|
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();
|
let guar = e.emit();
|
||||||
// When parsing a param failed, we should check to make the span of the param
|
// When parsing a param failed, we should check to make the span of the param
|
||||||
// not contain '(' before it.
|
// not contain '(' before it.
|
||||||
@@ -3019,7 +3041,7 @@ impl<'a> Parser<'a> {
|
|||||||
/// - `recover_arg_parse` is used to recover from a failed argument parse.
|
/// - `recover_arg_parse` is used to recover from a failed argument parse.
|
||||||
pub(super) fn parse_param_general(
|
pub(super) fn parse_param_general(
|
||||||
&mut self,
|
&mut self,
|
||||||
req_name: ReqName,
|
fn_parse_mode: &FnParseMode,
|
||||||
first_param: bool,
|
first_param: bool,
|
||||||
recover_arg_parse: bool,
|
recover_arg_parse: bool,
|
||||||
) -> PResult<'a, Param> {
|
) -> PResult<'a, Param> {
|
||||||
@@ -3035,16 +3057,22 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let is_name_required = match this.token.kind {
|
let is_name_required = match this.token.kind {
|
||||||
token::DotDotDot => false,
|
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() {
|
let (pat, ty) = if is_name_required || this.is_named_param() {
|
||||||
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
|
||||||
let (pat, colon) = this.parse_fn_param_pat_colon()?;
|
let (pat, colon) = this.parse_fn_param_pat_colon()?;
|
||||||
if !colon {
|
if !colon {
|
||||||
let mut err = this.unexpected().unwrap_err();
|
let mut err = this.unexpected().unwrap_err();
|
||||||
return if let Some(ident) =
|
return if let Some(ident) = this.parameter_without_type(
|
||||||
this.parameter_without_type(&mut err, pat, is_name_required, first_param)
|
&mut err,
|
||||||
{
|
pat,
|
||||||
|
is_name_required,
|
||||||
|
first_param,
|
||||||
|
fn_parse_mode,
|
||||||
|
) {
|
||||||
let guar = err.emit();
|
let guar = err.emit();
|
||||||
Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
|
Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ use std::{fmt, mem, slice};
|
|||||||
use attr_wrapper::{AttrWrapper, UsePreAttrPos};
|
use attr_wrapper::{AttrWrapper, UsePreAttrPos};
|
||||||
pub use diagnostics::AttemptLocalParseRecovery;
|
pub use diagnostics::AttemptLocalParseRecovery;
|
||||||
pub(crate) use expr::ForbiddenLetReason;
|
pub(crate) use expr::ForbiddenLetReason;
|
||||||
pub(crate) use item::FnParseMode;
|
pub(crate) use item::{FnContext, FnParseMode};
|
||||||
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
|
||||||
use path::PathStyle;
|
use path::PathStyle;
|
||||||
use rustc_ast::token::{
|
use rustc_ast::token::{
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ use crate::errors::{
|
|||||||
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
|
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
|
||||||
};
|
};
|
||||||
use crate::exp;
|
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.
|
/// Specifies how to parse a path.
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
@@ -399,7 +401,13 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
let dcx = self.dcx();
|
let dcx = self.dcx();
|
||||||
let parse_params_result = self.parse_paren_comma_seq(|p| {
|
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| {
|
param.map(move |param| {
|
||||||
if !matches!(param.pat.kind, PatKind::Missing) {
|
if !matches!(param.pat.kind, PatKind::Missing) {
|
||||||
dcx.emit_err(FnPathFoundNamedParams {
|
dcx.emit_err(FnPathFoundNamedParams {
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ use super::diagnostics::AttemptLocalParseRecovery;
|
|||||||
use super::pat::{PatternLocation, RecoverComma};
|
use super::pat::{PatternLocation, RecoverComma};
|
||||||
use super::path::PathStyle;
|
use super::path::PathStyle;
|
||||||
use super::{
|
use super::{
|
||||||
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
|
AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, Restrictions,
|
||||||
Trailing, UsePreAttrPos,
|
SemiColonMode, Trailing, UsePreAttrPos,
|
||||||
};
|
};
|
||||||
use crate::errors::{self, MalformedLoopLabel};
|
use crate::errors::{self, MalformedLoopLabel};
|
||||||
use crate::exp;
|
use crate::exp;
|
||||||
@@ -153,7 +153,7 @@ impl<'a> Parser<'a> {
|
|||||||
attrs.clone(), // FIXME: unwanted clone of attrs
|
attrs.clone(), // FIXME: unwanted clone of attrs
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
FnParseMode { req_name: |_| true, req_body: true },
|
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true },
|
||||||
force_collect,
|
force_collect,
|
||||||
)? {
|
)? {
|
||||||
self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item)))
|
self.mk_stmt(lo.to(item.span), StmtKind::Item(Box::new(item)))
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ use crate::errors::{
|
|||||||
NestedCVariadicType, ReturnTypesUseThinArrow,
|
NestedCVariadicType, ReturnTypesUseThinArrow,
|
||||||
};
|
};
|
||||||
use crate::parser::item::FrontMatterParsingMode;
|
use crate::parser::item::FrontMatterParsingMode;
|
||||||
|
use crate::parser::{FnContext, FnParseMode};
|
||||||
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
|
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
|
||||||
|
|
||||||
/// Signals whether parsing a type should allow `+`.
|
/// Signals whether parsing a type should allow `+`.
|
||||||
@@ -769,7 +770,12 @@ impl<'a> Parser<'a> {
|
|||||||
if self.may_recover() && self.token == TokenKind::Lt {
|
if self.may_recover() && self.token == TokenKind::Lt {
|
||||||
self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
|
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);
|
let decl_span = span_start.to(self.prev_token.span);
|
||||||
Ok(TyKind::FnPtr(Box::new(FnPtrTy {
|
Ok(TyKind::FnPtr(Box::new(FnPtrTy {
|
||||||
@@ -1314,7 +1320,8 @@ impl<'a> Parser<'a> {
|
|||||||
self.bump();
|
self.bump();
|
||||||
let args_lo = self.token.span;
|
let args_lo = self.token.span;
|
||||||
let snapshot = self.create_snapshot_for_diagnostic();
|
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) => {
|
Ok(decl) => {
|
||||||
self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
|
self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
|
||||||
Some(ast::Path {
|
Some(ast::Path {
|
||||||
@@ -1400,8 +1407,9 @@ impl<'a> Parser<'a> {
|
|||||||
|
|
||||||
// Parse `(T, U) -> R`.
|
// Parse `(T, U) -> R`.
|
||||||
let inputs_lo = self.token.span;
|
let inputs_lo = self.token.span;
|
||||||
|
let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
|
||||||
let inputs: ThinVec<_> =
|
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 inputs_span = inputs_lo.to(self.prev_token.span);
|
||||||
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
|
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
|
||||||
let args = ast::ParenthesizedArgs {
|
let args = ast::ParenthesizedArgs {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ fn pattern((i32, i32) (a, b)) {}
|
|||||||
fn fizz(i32) {}
|
fn fizz(i32) {}
|
||||||
//~^ ERROR expected one of `:`, `@`
|
//~^ ERROR expected one of `:`, `@`
|
||||||
//~| HELP if this is a parameter name, give it a type
|
//~| 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
|
//~| HELP if this is a type, explicitly ignore the parameter name
|
||||||
|
|
||||||
fn missing_colon(quux S) {}
|
fn missing_colon(quux S) {}
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
|
|||||||
LL | fn fizz(i32) {}
|
LL | fn fizz(i32) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
|
||||||
LL | fn fizz(i32: TypeName) {}
|
LL | fn fizz(i32: TypeName) {}
|
||||||
@@ -49,7 +44,7 @@ LL | fn fizz(_: i32) {}
|
|||||||
| ++
|
| ++
|
||||||
|
|
||||||
error: expected one of `:`, `@`, or `|`, found `S`
|
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) {}
|
LL | fn missing_colon(quux S) {}
|
||||||
| -----^
|
| -----^
|
||||||
|
|||||||
@@ -16,11 +16,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
|
|||||||
LL | fn test(&'a str) {
|
LL | fn test(&'a str) {
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
|
||||||
LL - fn test(&'a str) {
|
LL - fn test(&'a str) {
|
||||||
|
|||||||
@@ -4,11 +4,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
|
|||||||
LL | fn foo(x) {
|
LL | fn foo(x) {
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
|
||||||
LL | fn foo(x: TypeName) {
|
LL | fn foo(x: TypeName) {
|
||||||
|
|||||||
@@ -4,11 +4,6 @@ error: expected one of `:`, `@`, or `|`, found `<`
|
|||||||
LL | fn a(B<) {}
|
LL | fn a(B<) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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 a(self: B<) {}
|
|
||||||
| +++++
|
|
||||||
help: if this is a type, explicitly ignore the parameter name
|
help: if this is a type, explicitly ignore the parameter name
|
||||||
|
|
|
|
||||||
LL | fn a(_: B<) {}
|
LL | fn a(_: B<) {}
|
||||||
|
|||||||
25
tests/ui/parser/suggest-self-in-bare-function.rs
Normal file
25
tests/ui/parser/suggest-self-in-bare-function.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// We should not suggest `self` in bare functions.
|
||||||
|
// And a note for RFC 1685 should not be shown.
|
||||||
|
// See #144968
|
||||||
|
|
||||||
|
//@ edition:2018
|
||||||
|
|
||||||
|
fn is_even(value) -> bool { //~ ERROR expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
value % 2 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn is_even(value) -> bool { //~ ERROR expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
value % 2 == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait T {
|
||||||
|
fn is_even(value) -> bool { //~ ERROR expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
value % 2 == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
56
tests/ui/parser/suggest-self-in-bare-function.stderr
Normal file
56
tests/ui/parser/suggest-self-in-bare-function.stderr
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
error: expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
--> $DIR/suggest-self-in-bare-function.rs:7:17
|
||||||
|
|
|
||||||
|
LL | fn is_even(value) -> bool {
|
||||||
|
| ^ expected one of `:`, `@`, or `|`
|
||||||
|
|
|
||||||
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
||||||
|
LL | fn is_even(value: TypeName) -> bool {
|
||||||
|
| ++++++++++
|
||||||
|
help: if this is a type, explicitly ignore the parameter name
|
||||||
|
|
|
||||||
|
LL | fn is_even(_: value) -> bool {
|
||||||
|
| ++
|
||||||
|
|
||||||
|
error: expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
--> $DIR/suggest-self-in-bare-function.rs:14:21
|
||||||
|
|
|
||||||
|
LL | fn is_even(value) -> bool {
|
||||||
|
| ^ expected one of `:`, `@`, or `|`
|
||||||
|
|
|
||||||
|
help: if this is a `self` type, give it a parameter name
|
||||||
|
|
|
||||||
|
LL | fn is_even(self: value) -> bool {
|
||||||
|
| +++++
|
||||||
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
||||||
|
LL | fn is_even(value: TypeName) -> bool {
|
||||||
|
| ++++++++++
|
||||||
|
help: if this is a type, explicitly ignore the parameter name
|
||||||
|
|
|
||||||
|
LL | fn is_even(_: value) -> bool {
|
||||||
|
| ++
|
||||||
|
|
||||||
|
error: expected one of `:`, `@`, or `|`, found `)`
|
||||||
|
--> $DIR/suggest-self-in-bare-function.rs:20:21
|
||||||
|
|
|
||||||
|
LL | fn is_even(value) -> bool {
|
||||||
|
| ^ 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 is_even(self: value) -> bool {
|
||||||
|
| +++++
|
||||||
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
||||||
|
LL | fn is_even(value: TypeName) -> bool {
|
||||||
|
| ++++++++++
|
||||||
|
help: if this is a type, explicitly ignore the parameter name
|
||||||
|
|
|
||||||
|
LL | fn is_even(_: value) -> bool {
|
||||||
|
| ++
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
@@ -4,11 +4,6 @@ error: expected one of `:`, `@`, or `|`, found `<`
|
|||||||
LL | fn foo(Option<i32>, String) {}
|
LL | fn foo(Option<i32>, String) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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: Option<i32>, String) {}
|
|
||||||
| +++++
|
|
||||||
help: if this is a type, explicitly ignore the parameter name
|
help: if this is a type, explicitly ignore the parameter name
|
||||||
|
|
|
|
||||||
LL | fn foo(_: Option<i32>, String) {}
|
LL | fn foo(_: Option<i32>, String) {}
|
||||||
@@ -20,7 +15,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
|
|||||||
LL | fn foo(Option<i32>, String) {}
|
LL | fn foo(Option<i32>, String) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ expected one of `:`, `@`, or `|`
|
||||||
|
|
|
|
||||||
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
|
|
||||||
help: if this is a parameter name, give it a type
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
|
||||||
LL | fn foo(Option<i32>, String: TypeName) {}
|
LL | fn foo(Option<i32>, String: TypeName) {}
|
||||||
@@ -36,11 +30,6 @@ error: expected one of `:`, `@`, or `|`, found `,`
|
|||||||
LL | fn bar(x, y: usize) {}
|
LL | fn bar(x, y: usize) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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 bar(self: x, y: usize) {}
|
|
||||||
| +++++
|
|
||||||
help: if this is a parameter name, give it a type
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
|
||||||
LL | fn bar(x: TypeName, y: usize) {}
|
LL | fn bar(x: TypeName, y: usize) {}
|
||||||
|
|||||||
@@ -4,11 +4,6 @@ error: expected one of `:`, `@`, or `|`, found `<`
|
|||||||
LL | pub fn foo(Box<Self>) { }
|
LL | pub fn foo(Box<Self>) { }
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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 | pub fn foo(self: Box<Self>) { }
|
|
||||||
| +++++
|
|
||||||
help: if this is a type, explicitly ignore the parameter name
|
help: if this is a type, explicitly ignore the parameter name
|
||||||
|
|
|
|
||||||
LL | pub fn foo(_: Box<Self>) { }
|
LL | pub fn foo(_: Box<Self>) { }
|
||||||
@@ -20,7 +15,6 @@ error: expected one of `:`, `@`, or `|`, found `<`
|
|||||||
LL | fn bar(Box<Self>) { }
|
LL | fn bar(Box<Self>) { }
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ 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
|
help: if this is a `self` type, give it a parameter name
|
||||||
|
|
|
|
||||||
LL | fn bar(self: Box<Self>) { }
|
LL | fn bar(self: Box<Self>) { }
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ error: expected one of `:`, `@`, or `|`, found `)`
|
|||||||
LL | fn foo<'a>(_: impl 'a Sized) {}
|
LL | fn foo<'a>(_: impl 'a Sized) {}
|
||||||
| ^ expected one of `:`, `@`, or `|`
|
| ^ expected one of `:`, `@`, or `|`
|
||||||
|
|
|
|
||||||
= note: anonymous parameters are removed in the 2018 edition (see RFC 1685)
|
|
||||||
help: if this is a parameter name, give it a type
|
help: if this is a parameter name, give it a type
|
||||||
|
|
|
|
||||||
LL | fn foo<'a>(_: impl 'a Sized: TypeName) {}
|
LL | fn foo<'a>(_: impl 'a Sized: TypeName) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user