Skip to content

Commit 7d2c376

Browse files
committed
Add FnContext in parser for diagnostic
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
1 parent 734639d commit 7d2c376

19 files changed

+86
-92
lines changed

compiler/rustc_parse/src/parser/attr.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use tracing::debug;
1111
use super::{
1212
AttrWrapper, Capturing, FnParseMode, ForceCollect, Parser, PathStyle, Trailing, UsePreAttrPos,
1313
};
14+
use crate::parser::FnContext;
1415
use crate::{errors, exp, fluent_generated as fluent};
1516

1617
// Public for rustfmt usage
@@ -200,7 +201,7 @@ impl<'a> Parser<'a> {
200201
AttrWrapper::empty(),
201202
true,
202203
false,
203-
FnParseMode { req_name: |_| true, req_body: true },
204+
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true },
204205
ForceCollect::No,
205206
) {
206207
Ok(Some(item)) => {

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ use crate::errors::{
4545
UnexpectedConstParamDeclaration, UnexpectedConstParamDeclarationSugg, UnmatchedAngleBrackets,
4646
UseEqInstead, WrapType,
4747
};
48+
use crate::parser::FnContext;
4849
use crate::parser::attr::InnerAttrPolicy;
4950
use crate::{exp, fluent_generated as fluent};
5051

@@ -2247,6 +2248,7 @@ impl<'a> Parser<'a> {
22472248
pat: P<ast::Pat>,
22482249
require_name: bool,
22492250
first_param: bool,
2251+
fn_parse_mode: &crate::parser::item::FnParseMode,
22502252
) -> Option<Ident> {
22512253
// If we find a pattern followed by an identifier, it could be an (incorrect)
22522254
// C-style parameter declaration.
@@ -2269,8 +2271,6 @@ impl<'a> Parser<'a> {
22692271
|| self.token == token::Lt
22702272
|| self.token == token::CloseParen)
22712273
{
2272-
let rfc_note = "anonymous parameters are removed in the 2018 edition (see RFC 1685)";
2273-
22742274
let (ident, self_sugg, param_sugg, type_sugg, self_span, param_span, type_span) =
22752275
match pat.kind {
22762276
PatKind::Ident(_, ident, _) => (
@@ -2306,15 +2306,20 @@ impl<'a> Parser<'a> {
23062306
"_: ".to_string(),
23072307
Applicability::MachineApplicable,
23082308
);
2309-
err.note(rfc_note);
23102309
}
23112310

23122311
return None;
23132312
}
23142313
};
23152314

23162315
// `fn foo(a, b) {}`, `fn foo(a<x>, b<y>) {}` or `fn foo(usize, usize) {}`
2317-
if first_param {
2316+
if first_param
2317+
// Only when the fn is a method, we emit this suggestion.
2318+
&& matches!(
2319+
fn_parse_mode.context,
2320+
FnContext::Trait | FnContext::Impl
2321+
)
2322+
{
23182323
err.span_suggestion_verbose(
23192324
self_span,
23202325
"if this is a `self` type, give it a parameter name",
@@ -2338,7 +2343,6 @@ impl<'a> Parser<'a> {
23382343
type_sugg,
23392344
Applicability::MachineApplicable,
23402345
);
2341-
err.note(rfc_note);
23422346

23432347
// Don't attempt to recover by using the `X` in `X<Y>` as the parameter name.
23442348
return if self.token == token::Lt { None } else { Some(ident) };

compiler/rustc_parse/src/parser/item.rs

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ impl<'a> Parser<'a> {
117117

118118
impl<'a> Parser<'a> {
119119
pub fn parse_item(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<P<Item>>> {
120-
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
120+
let fn_parse_mode =
121+
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true };
121122
self.parse_item_(fn_parse_mode, force_collect).map(|i| i.map(P))
122123
}
123124

@@ -952,16 +953,20 @@ impl<'a> Parser<'a> {
952953
&mut self,
953954
force_collect: ForceCollect,
954955
) -> PResult<'a, Option<Option<P<AssocItem>>>> {
955-
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
956+
let fn_parse_mode =
957+
FnParseMode { req_name: |_| true, context: FnContext::Impl, req_body: true };
956958
self.parse_assoc_item(fn_parse_mode, force_collect)
957959
}
958960

959961
pub fn parse_trait_item(
960962
&mut self,
961963
force_collect: ForceCollect,
962964
) -> PResult<'a, Option<Option<P<AssocItem>>>> {
963-
let fn_parse_mode =
964-
FnParseMode { req_name: |edition| edition >= Edition::Edition2018, req_body: false };
965+
let fn_parse_mode = FnParseMode {
966+
req_name: |edition| edition >= Edition::Edition2018,
967+
context: FnContext::Trait,
968+
req_body: false,
969+
};
965970
self.parse_assoc_item(fn_parse_mode, force_collect)
966971
}
967972

@@ -1238,7 +1243,8 @@ impl<'a> Parser<'a> {
12381243
&mut self,
12391244
force_collect: ForceCollect,
12401245
) -> PResult<'a, Option<Option<P<ForeignItem>>>> {
1241-
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: false };
1246+
let fn_parse_mode =
1247+
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: false };
12421248
Ok(self.parse_item_(fn_parse_mode, force_collect)?.map(
12431249
|Item { attrs, id, span, vis, kind, tokens }| {
12441250
let kind = match ForeignItemKind::try_from(kind) {
@@ -2110,7 +2116,8 @@ impl<'a> Parser<'a> {
21102116
let inherited_vis =
21112117
Visibility { span: DUMMY_SP, kind: VisibilityKind::Inherited, tokens: None };
21122118
// We use `parse_fn` to get a span for the function
2113-
let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
2119+
let fn_parse_mode =
2120+
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true };
21142121
match self.parse_fn(
21152122
&mut AttrVec::new(),
21162123
fn_parse_mode,
@@ -2378,6 +2385,9 @@ pub(crate) struct FnParseMode {
23782385
/// * The span is from Edition 2015. In particular, you can get a
23792386
/// 2015 span inside a 2021 crate using macros.
23802387
pub(super) req_name: ReqName,
2388+
/// The context in which this function is parsed, used for diagnostics.
2389+
/// This indicates the fn is a free function or method and so on.
2390+
pub(super) context: FnContext,
23812391
/// If this flag is set to `true`, then plain, semicolon-terminated function
23822392
/// prototypes are not allowed here.
23832393
///
@@ -2399,6 +2409,18 @@ pub(crate) struct FnParseMode {
23992409
pub(super) req_body: bool,
24002410
}
24012411

2412+
/// The context in which a function is parsed.
2413+
/// FIXME(estebank, xizheyin): Use more variants.
2414+
#[derive(Clone, Copy, PartialEq, Eq)]
2415+
pub(crate) enum FnContext {
2416+
/// Free context.
2417+
Free,
2418+
/// A Trait context.
2419+
Trait,
2420+
/// An Impl block.
2421+
Impl,
2422+
}
2423+
24022424
/// Parsing of functions and methods.
24032425
impl<'a> Parser<'a> {
24042426
/// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
@@ -2414,11 +2436,8 @@ impl<'a> Parser<'a> {
24142436
let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
24152437
let ident = self.parse_ident()?; // `foo`
24162438
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
2417-
let decl = match self.parse_fn_decl(
2418-
fn_parse_mode.req_name,
2419-
AllowPlus::Yes,
2420-
RecoverReturnSign::Yes,
2421-
) {
2439+
let decl = match self.parse_fn_decl(&fn_parse_mode, AllowPlus::Yes, RecoverReturnSign::Yes)
2440+
{
24222441
Ok(decl) => decl,
24232442
Err(old_err) => {
24242443
// If we see `for Ty ...` then user probably meant `impl` item.
@@ -2936,18 +2955,21 @@ impl<'a> Parser<'a> {
29362955
/// Parses the parameter list and result type of a function declaration.
29372956
pub(super) fn parse_fn_decl(
29382957
&mut self,
2939-
req_name: ReqName,
2958+
fn_parse_mode: &FnParseMode,
29402959
ret_allow_plus: AllowPlus,
29412960
recover_return_sign: RecoverReturnSign,
29422961
) -> PResult<'a, P<FnDecl>> {
29432962
Ok(P(FnDecl {
2944-
inputs: self.parse_fn_params(req_name)?,
2963+
inputs: self.parse_fn_params(fn_parse_mode)?,
29452964
output: self.parse_ret_ty(ret_allow_plus, RecoverQPath::Yes, recover_return_sign)?,
29462965
}))
29472966
}
29482967

29492968
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
2950-
pub(super) fn parse_fn_params(&mut self, req_name: ReqName) -> PResult<'a, ThinVec<Param>> {
2969+
pub(super) fn parse_fn_params(
2970+
&mut self,
2971+
fn_parse_mode: &FnParseMode,
2972+
) -> PResult<'a, ThinVec<Param>> {
29512973
let mut first_param = true;
29522974
// Parse the arguments, starting out with `self` being allowed...
29532975
if self.token != TokenKind::OpenParen
@@ -2963,7 +2985,7 @@ impl<'a> Parser<'a> {
29632985
let (mut params, _) = self.parse_paren_comma_seq(|p| {
29642986
p.recover_vcs_conflict_marker();
29652987
let snapshot = p.create_snapshot_for_diagnostic();
2966-
let param = p.parse_param_general(req_name, first_param, true).or_else(|e| {
2988+
let param = p.parse_param_general(fn_parse_mode, first_param, true).or_else(|e| {
29672989
let guar = e.emit();
29682990
// When parsing a param failed, we should check to make the span of the param
29692991
// not contain '(' before it.
@@ -2994,7 +3016,7 @@ impl<'a> Parser<'a> {
29943016
/// - `recover_arg_parse` is used to recover from a failed argument parse.
29953017
pub(super) fn parse_param_general(
29963018
&mut self,
2997-
req_name: ReqName,
3019+
fn_parse_mode: &FnParseMode,
29983020
first_param: bool,
29993021
recover_arg_parse: bool,
30003022
) -> PResult<'a, Param> {
@@ -3010,16 +3032,22 @@ impl<'a> Parser<'a> {
30103032

30113033
let is_name_required = match this.token.kind {
30123034
token::DotDotDot => false,
3013-
_ => req_name(this.token.span.with_neighbor(this.prev_token.span).edition()),
3035+
_ => (fn_parse_mode.req_name)(
3036+
this.token.span.with_neighbor(this.prev_token.span).edition(),
3037+
),
30143038
};
30153039
let (pat, ty) = if is_name_required || this.is_named_param() {
30163040
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
30173041
let (pat, colon) = this.parse_fn_param_pat_colon()?;
30183042
if !colon {
30193043
let mut err = this.unexpected().unwrap_err();
3020-
return if let Some(ident) =
3021-
this.parameter_without_type(&mut err, pat, is_name_required, first_param)
3022-
{
3044+
return if let Some(ident) = this.parameter_without_type(
3045+
&mut err,
3046+
pat,
3047+
is_name_required,
3048+
first_param,
3049+
fn_parse_mode,
3050+
) {
30233051
let guar = err.emit();
30243052
Ok((dummy_arg(ident, guar), Trailing::No, UsePreAttrPos::No))
30253053
} else {

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::{fmt, mem, slice};
2222
use attr_wrapper::{AttrWrapper, UsePreAttrPos};
2323
pub use diagnostics::AttemptLocalParseRecovery;
2424
pub(crate) use expr::ForbiddenLetReason;
25-
pub(crate) use item::FnParseMode;
25+
pub(crate) use item::{FnContext, FnParseMode};
2626
pub use pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
2727
use path::PathStyle;
2828
use rustc_ast::ptr::P;

compiler/rustc_parse/src/parser/path.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use crate::errors::{
2121
PathFoundAttributeInParams, PathFoundCVariadicParams, PathSingleColon, PathTripleColon,
2222
};
2323
use crate::exp;
24-
use crate::parser::{CommaRecoveryMode, ExprKind, RecoverColon, RecoverComma};
24+
use crate::parser::{
25+
CommaRecoveryMode, ExprKind, FnContext, FnParseMode, RecoverColon, RecoverComma,
26+
};
2527

2628
/// Specifies how to parse a path.
2729
#[derive(Copy, Clone, PartialEq)]
@@ -400,7 +402,13 @@ impl<'a> Parser<'a> {
400402

401403
let dcx = self.dcx();
402404
let parse_params_result = self.parse_paren_comma_seq(|p| {
403-
let param = p.parse_param_general(|_| false, false, false);
405+
// Inside parenthesized type arguments, we want types only, not names.
406+
let mode = FnParseMode {
407+
context: FnContext::Free,
408+
req_name: |_| false,
409+
req_body: false,
410+
};
411+
let param = p.parse_param_general(&mode, false, false);
404412
param.map(move |param| {
405413
if !matches!(param.pat.kind, PatKind::Missing) {
406414
dcx.emit_err(FnPathFoundNamedParams {

compiler/rustc_parse/src/parser/stmt.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use super::diagnostics::AttemptLocalParseRecovery;
2020
use super::pat::{PatternLocation, RecoverComma};
2121
use super::path::PathStyle;
2222
use super::{
23-
AttrWrapper, BlockMode, FnParseMode, ForceCollect, Parser, Restrictions, SemiColonMode,
24-
Trailing, UsePreAttrPos,
23+
AttrWrapper, BlockMode, FnContext, FnParseMode, ForceCollect, Parser, Restrictions,
24+
SemiColonMode, Trailing, UsePreAttrPos,
2525
};
2626
use crate::errors::{self, MalformedLoopLabel};
2727
use crate::exp;
@@ -154,7 +154,7 @@ impl<'a> Parser<'a> {
154154
attrs.clone(), // FIXME: unwanted clone of attrs
155155
false,
156156
true,
157-
FnParseMode { req_name: |_| true, req_body: true },
157+
FnParseMode { req_name: |_| true, context: FnContext::Free, req_body: true },
158158
force_collect,
159159
)? {
160160
self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item)))

compiler/rustc_parse/src/parser/ty.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::errors::{
2020
NestedCVariadicType, ReturnTypesUseThinArrow,
2121
};
2222
use crate::parser::item::FrontMatterParsingMode;
23+
use crate::parser::{FnContext, FnParseMode};
2324
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
2425

2526
/// Signals whether parsing a type should allow `+`.
@@ -770,7 +771,12 @@ impl<'a> Parser<'a> {
770771
if self.may_recover() && self.token == TokenKind::Lt {
771772
self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
772773
}
773-
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
774+
let mode = crate::parser::item::FnParseMode {
775+
req_name: |_| false,
776+
context: FnContext::Free,
777+
req_body: false,
778+
};
779+
let decl = self.parse_fn_decl(&mode, AllowPlus::No, recover_return_sign)?;
774780

775781
let decl_span = span_start.to(self.prev_token.span);
776782
Ok(TyKind::FnPtr(P(FnPtrTy { ext, safety, generic_params: params, decl, decl_span })))
@@ -1309,7 +1315,8 @@ impl<'a> Parser<'a> {
13091315
self.bump();
13101316
let args_lo = self.token.span;
13111317
let snapshot = self.create_snapshot_for_diagnostic();
1312-
match self.parse_fn_decl(|_| false, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
1318+
let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
1319+
match self.parse_fn_decl(&mode, AllowPlus::No, RecoverReturnSign::OnlyFatArrow) {
13131320
Ok(decl) => {
13141321
self.dcx().emit_err(ExpectedFnPathFoundFnKeyword { fn_token_span });
13151322
Some(ast::Path {
@@ -1393,8 +1400,9 @@ impl<'a> Parser<'a> {
13931400

13941401
// Parse `(T, U) -> R`.
13951402
let inputs_lo = self.token.span;
1403+
let mode = FnParseMode { req_name: |_| false, context: FnContext::Free, req_body: false };
13961404
let inputs: ThinVec<_> =
1397-
self.parse_fn_params(|_| false)?.into_iter().map(|input| input.ty).collect();
1405+
self.parse_fn_params(&mode)?.into_iter().map(|input| input.ty).collect();
13981406
let inputs_span = inputs_lo.to(self.prev_token.span);
13991407
let output = self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
14001408
let args = ast::ParenthesizedArgs {

0 commit comments

Comments
 (0)