Use parse_param_general when parsing (T, U)->R in parse_path_segment

Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>

Co-authored-by: Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
This commit is contained in:
xizheyin
2025-05-06 15:45:04 +08:00
parent 896cf8029c
commit b922da3586
10 changed files with 158 additions and 75 deletions

View File

@@ -1591,6 +1591,30 @@ pub(crate) struct ExpectedFnPathFoundFnKeyword {
pub fn_token_span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_path_found_named_params)]
pub(crate) struct FnPathFoundNamedParams {
#[primary_span]
#[suggestion(applicability = "machine-applicable", code = "")]
pub named_param_span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_path_found_c_variadic_params)]
pub(crate) struct PathFoundCVariadicParams {
#[primary_span]
#[suggestion(applicability = "machine-applicable", code = "")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_path_found_attribute_in_params)]
pub(crate) struct PathFoundAttributeInParams {
#[primary_span]
#[suggestion(applicability = "machine-applicable", code = "")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_path_double_colon)]
pub(crate) struct PathSingleColon {

View File

@@ -2894,7 +2894,7 @@ impl<'a> Parser<'a> {
let (mut params, _) = self.parse_paren_comma_seq(|p| {
p.recover_vcs_conflict_marker();
let snapshot = p.create_snapshot_for_diagnostic();
let param = p.parse_param_general(req_name, first_param).or_else(|e| {
let param = p.parse_param_general(req_name, first_param, true).or_else(|e| {
let guar = e.emit();
// When parsing a param failed, we should check to make the span of the param
// not contain '(' before it.
@@ -2922,7 +2922,13 @@ impl<'a> Parser<'a> {
/// Parses a single function parameter.
///
/// - `self` is syntactically allowed when `first_param` holds.
fn parse_param_general(&mut self, req_name: ReqName, first_param: bool) -> PResult<'a, Param> {
/// - `recover_arg_parse` is used to recover from a failed argument parse.
pub(super) fn parse_param_general(
&mut self,
req_name: ReqName,
first_param: bool,
recover_arg_parse: bool,
) -> PResult<'a, Param> {
let lo = self.token.span;
let attrs = self.parse_outer_attributes()?;
self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
@@ -2990,12 +2996,13 @@ impl<'a> Parser<'a> {
// If this is a C-variadic argument and we hit an error, return the error.
Err(err) if this.token == token::DotDotDot => return Err(err),
Err(err) if this.unmatched_angle_bracket_count > 0 => return Err(err),
// Recover from attempting to parse the argument as a type without pattern.
Err(err) => {
Err(err) if recover_arg_parse => {
// Recover from attempting to parse the argument as a type without pattern.
err.cancel();
this.restore_snapshot(parser_snapshot_before_ty);
this.recover_arg_parse()?
}
Err(err) => return Err(err),
}
};

View File

@@ -15,7 +15,11 @@ use tracing::debug;
use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
use super::{Parser, Restrictions, TokenType};
use crate::errors::{self, PathSingleColon, PathTripleColon};
use crate::ast::{PatKind, TyKind};
use crate::errors::{
self, FnPathFoundNamedParams, PathFoundAttributeInParams, PathFoundCVariadicParams,
PathSingleColon, PathTripleColon,
};
use crate::exp;
use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
@@ -396,7 +400,28 @@ impl<'a> Parser<'a> {
snapshot = Some(self.create_snapshot_for_diagnostic());
}
let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) {
let dcx = self.dcx();
let parse_params_result = self.parse_paren_comma_seq(|p| {
let param = p.parse_param_general(|_| false, false, false);
param.map(move |param| {
if !matches!(param.pat.kind, PatKind::Missing) {
dcx.emit_err(FnPathFoundNamedParams {
named_param_span: param.pat.span,
});
}
if matches!(param.ty.kind, TyKind::CVarArgs) {
dcx.emit_err(PathFoundCVariadicParams { span: param.pat.span });
}
if !param.attrs.is_empty() {
dcx.emit_err(PathFoundAttributeInParams {
span: param.attrs[0].span,
});
}
param.ty
})
});
let (inputs, _) = match parse_params_result {
Ok(output) => output,
Err(mut error) if prev_token_before_parsing == token::PathSep => {
error.span_label(