Skip to content

Commit 66e4288

Browse files
authored
Rollup merge of rust-lang#65362 - Centril:extract_fun, r=petrochenkov
syntax: consolidate function parsing in item.rs Extracted from rust-lang#65324. r? @estebank
2 parents c2ae4de + 4a0c487 commit 66e4288

File tree

3 files changed

+491
-487
lines changed

3 files changed

+491
-487
lines changed

Diff for: src/libsyntax/parse/parser.rs

+4-281
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,19 @@ mod path;
99
pub use path::PathStyle;
1010
mod stmt;
1111
mod generics;
12+
use super::diagnostics::Error;
1213

1314
use crate::ast::{
14-
self, DUMMY_NODE_ID, AttrStyle, Attribute, BindingMode, CrateSugar, Ident,
15-
IsAsync, MacDelimiter, Mutability, Param, StrStyle, SelfKind, TyKind, Visibility,
16-
VisibilityKind, Unsafety,
15+
self, DUMMY_NODE_ID, AttrStyle, Attribute, CrateSugar, Ident,
16+
IsAsync, MacDelimiter, Mutability, StrStyle, Visibility, VisibilityKind, Unsafety,
1717
};
1818
use crate::parse::{ParseSess, PResult, Directory, DirectoryOwnership, SeqSep, literal, token};
19-
use crate::parse::diagnostics::{Error, dummy_arg};
2019
use crate::parse::lexer::UnmatchedBrace;
2120
use crate::parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
2221
use crate::parse::token::{Token, TokenKind, DelimToken};
2322
use crate::print::pprust;
2423
use crate::ptr::P;
25-
use crate::source_map::{self, respan};
24+
use crate::source_map::respan;
2625
use crate::symbol::{kw, sym, Symbol};
2726
use crate::tokenstream::{self, DelimSpan, TokenTree, TokenStream, TreeAndJoint};
2827
use crate::ThinVec;
@@ -56,17 +55,6 @@ crate enum BlockMode {
5655
Ignore,
5756
}
5857

59-
/// The parsing configuration used to parse a parameter list (see `parse_fn_params`).
60-
struct ParamCfg {
61-
/// Is `self` is allowed as the first parameter?
62-
is_self_allowed: bool,
63-
/// Is `...` allowed as the tail of the parameter list?
64-
allow_c_variadic: bool,
65-
/// `is_name_required` decides if, per-parameter,
66-
/// the parameter must have a pattern or just a type.
67-
is_name_required: fn(&token::Token) -> bool,
68-
}
69-
7058
/// Like `maybe_whole_expr`, but for things other than expressions.
7159
#[macro_export]
7260
macro_rules! maybe_whole {
@@ -1105,271 +1093,6 @@ impl<'a> Parser<'a> {
11051093
res
11061094
}
11071095

1108-
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
1109-
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
1110-
let sp = self.token.span;
1111-
let is_trait_item = cfg.is_self_allowed;
1112-
let mut c_variadic = false;
1113-
// Parse the arguments, starting out with `self` being possibly allowed...
1114-
let (params, _) = self.parse_paren_comma_seq(|p| {
1115-
let param = p.parse_param_general(&cfg, is_trait_item);
1116-
// ...now that we've parsed the first argument, `self` is no longer allowed.
1117-
cfg.is_self_allowed = false;
1118-
1119-
match param {
1120-
Ok(param) => Ok(
1121-
if let TyKind::CVarArgs = param.ty.kind {
1122-
c_variadic = true;
1123-
if p.token != token::CloseDelim(token::Paren) {
1124-
p.span_err(
1125-
p.token.span,
1126-
"`...` must be the last argument of a C-variadic function",
1127-
);
1128-
// FIXME(eddyb) this should probably still push `CVarArgs`.
1129-
// Maybe AST validation/HIR lowering should emit the above error?
1130-
None
1131-
} else {
1132-
Some(param)
1133-
}
1134-
} else {
1135-
Some(param)
1136-
}
1137-
),
1138-
Err(mut e) => {
1139-
e.emit();
1140-
let lo = p.prev_span;
1141-
// Skip every token until next possible arg or end.
1142-
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
1143-
// Create a placeholder argument for proper arg count (issue #34264).
1144-
let span = lo.to(p.prev_span);
1145-
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
1146-
}
1147-
}
1148-
})?;
1149-
1150-
let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
1151-
1152-
// Replace duplicated recovered params with `_` pattern to avoid unecessary errors.
1153-
self.deduplicate_recovered_params_names(&mut params);
1154-
1155-
if c_variadic && params.len() <= 1 {
1156-
self.span_err(
1157-
sp,
1158-
"C-variadic function must be declared with at least one named argument",
1159-
);
1160-
}
1161-
1162-
Ok(params)
1163-
}
1164-
1165-
/// Skips unexpected attributes and doc comments in this position and emits an appropriate
1166-
/// error.
1167-
/// This version of parse param doesn't necessarily require identifier names.
1168-
fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResult<'a, Param> {
1169-
let lo = self.token.span;
1170-
let attrs = self.parse_outer_attributes()?;
1171-
1172-
// Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
1173-
if let Some(mut param) = self.parse_self_param()? {
1174-
param.attrs = attrs.into();
1175-
return if cfg.is_self_allowed {
1176-
Ok(param)
1177-
} else {
1178-
self.recover_bad_self_param(param, is_trait_item)
1179-
};
1180-
}
1181-
1182-
let is_name_required = match self.token.kind {
1183-
token::DotDotDot => false,
1184-
_ => (cfg.is_name_required)(&self.token),
1185-
};
1186-
let (pat, ty) = if is_name_required || self.is_named_param() {
1187-
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
1188-
1189-
let pat = self.parse_fn_param_pat()?;
1190-
if let Err(mut err) = self.expect(&token::Colon) {
1191-
return if let Some(ident) = self.parameter_without_type(
1192-
&mut err,
1193-
pat,
1194-
is_name_required,
1195-
cfg.is_self_allowed,
1196-
is_trait_item,
1197-
) {
1198-
err.emit();
1199-
Ok(dummy_arg(ident))
1200-
} else {
1201-
Err(err)
1202-
};
1203-
}
1204-
1205-
self.eat_incorrect_doc_comment_for_param_type();
1206-
(pat, self.parse_ty_common(true, true, cfg.allow_c_variadic)?)
1207-
} else {
1208-
debug!("parse_param_general ident_to_pat");
1209-
let parser_snapshot_before_ty = self.clone();
1210-
self.eat_incorrect_doc_comment_for_param_type();
1211-
let mut ty = self.parse_ty_common(true, true, cfg.allow_c_variadic);
1212-
if ty.is_ok() && self.token != token::Comma &&
1213-
self.token != token::CloseDelim(token::Paren) {
1214-
// This wasn't actually a type, but a pattern looking like a type,
1215-
// so we are going to rollback and re-parse for recovery.
1216-
ty = self.unexpected();
1217-
}
1218-
match ty {
1219-
Ok(ty) => {
1220-
let ident = Ident::new(kw::Invalid, self.prev_span);
1221-
let bm = BindingMode::ByValue(Mutability::Immutable);
1222-
let pat = self.mk_pat_ident(ty.span, bm, ident);
1223-
(pat, ty)
1224-
}
1225-
// If this is a C-variadic argument and we hit an error, return the error.
1226-
Err(err) if self.token == token::DotDotDot => return Err(err),
1227-
// Recover from attempting to parse the argument as a type without pattern.
1228-
Err(mut err) => {
1229-
err.cancel();
1230-
mem::replace(self, parser_snapshot_before_ty);
1231-
self.recover_arg_parse()?
1232-
}
1233-
}
1234-
};
1235-
1236-
let span = lo.to(self.token.span);
1237-
1238-
Ok(Param {
1239-
attrs: attrs.into(),
1240-
id: ast::DUMMY_NODE_ID,
1241-
is_placeholder: false,
1242-
pat,
1243-
span,
1244-
ty,
1245-
})
1246-
}
1247-
1248-
/// Returns the parsed optional self parameter and whether a self shortcut was used.
1249-
///
1250-
/// See `parse_self_param_with_attrs` to collect attributes.
1251-
fn parse_self_param(&mut self) -> PResult<'a, Option<Param>> {
1252-
// Extract an identifier *after* having confirmed that the token is one.
1253-
let expect_self_ident = |this: &mut Self| {
1254-
match this.token.kind {
1255-
// Preserve hygienic context.
1256-
token::Ident(name, _) => {
1257-
let span = this.token.span;
1258-
this.bump();
1259-
Ident::new(name, span)
1260-
}
1261-
_ => unreachable!(),
1262-
}
1263-
};
1264-
// Is `self` `n` tokens ahead?
1265-
let is_isolated_self = |this: &Self, n| {
1266-
this.is_keyword_ahead(n, &[kw::SelfLower])
1267-
&& this.look_ahead(n + 1, |t| t != &token::ModSep)
1268-
};
1269-
// Is `mut self` `n` tokens ahead?
1270-
let is_isolated_mut_self = |this: &Self, n| {
1271-
this.is_keyword_ahead(n, &[kw::Mut])
1272-
&& is_isolated_self(this, n + 1)
1273-
};
1274-
// Parse `self` or `self: TYPE`. We already know the current token is `self`.
1275-
let parse_self_possibly_typed = |this: &mut Self, m| {
1276-
let eself_ident = expect_self_ident(this);
1277-
let eself_hi = this.prev_span;
1278-
let eself = if this.eat(&token::Colon) {
1279-
SelfKind::Explicit(this.parse_ty()?, m)
1280-
} else {
1281-
SelfKind::Value(m)
1282-
};
1283-
Ok((eself, eself_ident, eself_hi))
1284-
};
1285-
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
1286-
let recover_self_ptr = |this: &mut Self| {
1287-
let msg = "cannot pass `self` by raw pointer";
1288-
let span = this.token.span;
1289-
this.struct_span_err(span, msg)
1290-
.span_label(span, msg)
1291-
.emit();
1292-
1293-
Ok((SelfKind::Value(Mutability::Immutable), expect_self_ident(this), this.prev_span))
1294-
};
1295-
1296-
// Parse optional `self` parameter of a method.
1297-
// Only a limited set of initial token sequences is considered `self` parameters; anything
1298-
// else is parsed as a normal function parameter list, so some lookahead is required.
1299-
let eself_lo = self.token.span;
1300-
let (eself, eself_ident, eself_hi) = match self.token.kind {
1301-
token::BinOp(token::And) => {
1302-
let eself = if is_isolated_self(self, 1) {
1303-
// `&self`
1304-
self.bump();
1305-
SelfKind::Region(None, Mutability::Immutable)
1306-
} else if is_isolated_mut_self(self, 1) {
1307-
// `&mut self`
1308-
self.bump();
1309-
self.bump();
1310-
SelfKind::Region(None, Mutability::Mutable)
1311-
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_self(self, 2) {
1312-
// `&'lt self`
1313-
self.bump();
1314-
let lt = self.expect_lifetime();
1315-
SelfKind::Region(Some(lt), Mutability::Immutable)
1316-
} else if self.look_ahead(1, |t| t.is_lifetime()) && is_isolated_mut_self(self, 2) {
1317-
// `&'lt mut self`
1318-
self.bump();
1319-
let lt = self.expect_lifetime();
1320-
self.bump();
1321-
SelfKind::Region(Some(lt), Mutability::Mutable)
1322-
} else {
1323-
// `&not_self`
1324-
return Ok(None);
1325-
};
1326-
(eself, expect_self_ident(self), self.prev_span)
1327-
}
1328-
// `*self`
1329-
token::BinOp(token::Star) if is_isolated_self(self, 1) => {
1330-
self.bump();
1331-
recover_self_ptr(self)?
1332-
}
1333-
// `*mut self` and `*const self`
1334-
token::BinOp(token::Star) if
1335-
self.look_ahead(1, |t| t.is_mutability())
1336-
&& is_isolated_self(self, 2) =>
1337-
{
1338-
self.bump();
1339-
self.bump();
1340-
recover_self_ptr(self)?
1341-
}
1342-
// `self` and `self: TYPE`
1343-
token::Ident(..) if is_isolated_self(self, 0) => {
1344-
parse_self_possibly_typed(self, Mutability::Immutable)?
1345-
}
1346-
// `mut self` and `mut self: TYPE`
1347-
token::Ident(..) if is_isolated_mut_self(self, 0) => {
1348-
self.bump();
1349-
parse_self_possibly_typed(self, Mutability::Mutable)?
1350-
}
1351-
_ => return Ok(None),
1352-
};
1353-
1354-
let eself = source_map::respan(eself_lo.to(eself_hi), eself);
1355-
Ok(Some(Param::from_self(ThinVec::default(), eself, eself_ident)))
1356-
}
1357-
1358-
fn is_named_param(&self) -> bool {
1359-
let offset = match self.token.kind {
1360-
token::Interpolated(ref nt) => match **nt {
1361-
token::NtPat(..) => return self.look_ahead(1, |t| t == &token::Colon),
1362-
_ => 0,
1363-
}
1364-
token::BinOp(token::And) | token::AndAnd => 1,
1365-
_ if self.token.is_keyword(kw::Mut) => 1,
1366-
_ => 0,
1367-
};
1368-
1369-
self.look_ahead(offset, |t| t.is_ident()) &&
1370-
self.look_ahead(offset + 1, |t| t == &token::Colon)
1371-
}
1372-
13731096
fn is_crate_vis(&self) -> bool {
13741097
self.token.is_keyword(kw::Crate) && self.look_ahead(1, |t| t != &token::ModSep)
13751098
}

0 commit comments

Comments
 (0)