Skip to content

Commit f290467

Browse files
committed
syntax: cleanup method parsing.
1 parent 8431f26 commit f290467

File tree

2 files changed

+66
-74
lines changed

2 files changed

+66
-74
lines changed

src/libsyntax/parse/diagnostics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1180,7 +1180,7 @@ impl<'a> Parser<'a> {
11801180
}
11811181
}
11821182

1183-
crate fn expected_semi_or_open_brace(&mut self) -> PResult<'a, ast::TraitItem> {
1183+
crate fn expected_semi_or_open_brace<T>(&mut self) -> PResult<'a, T> {
11841184
let token_str = self.this_token_descr();
11851185
let mut err = self.fatal(&format!("expected `;` or `{{`, found {}", token_str));
11861186
err.span_label(self.token.span, "expected `;` or `{`");

src/libsyntax/parse/parser/item.rs

Lines changed: 65 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::ast::{
77
Item, ItemKind, ImplItem, TraitItem, TraitItemKind,
88
UseTree, UseTreeKind, PathSegment,
99
IsAuto, Constness, IsAsync, Unsafety, Defaultness,
10-
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader,
10+
Visibility, VisibilityKind, Mutability, FnDecl, FnHeader, MethodSig, Block,
1111
ForeignItem, ForeignItemKind,
1212
Ty, TyKind, Generics, GenericBounds, TraitRef,
1313
EnumDef, VariantData, StructField, AnonConst,
@@ -848,29 +848,38 @@ impl<'a> Parser<'a> {
848848
}
849849

850850
/// Parses a method or a macro invocation in a trait impl.
851-
fn parse_impl_method(&mut self, vis: &Visibility, at_end: &mut bool)
852-
-> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
851+
fn parse_impl_method(
852+
&mut self,
853+
vis: &Visibility,
854+
at_end: &mut bool
855+
) -> PResult<'a, (Ident, Vec<Attribute>, Generics, ast::ImplItemKind)> {
853856
// FIXME: code copied from `parse_macro_use_or_failure` -- use abstraction!
854857
if let Some(mac) = self.parse_assoc_macro_invoc("impl", Some(vis), at_end)? {
855858
// method macro
856-
Ok((Ident::invalid(), vec![], Generics::default(),
857-
ast::ImplItemKind::Macro(mac)))
859+
Ok((Ident::invalid(), vec![], Generics::default(), ast::ImplItemKind::Macro(mac)))
858860
} else {
859-
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
860-
let ident = self.parse_ident()?;
861-
let mut generics = self.parse_generics()?;
862-
let decl = self.parse_fn_decl_with_self(|_| true)?;
863-
generics.where_clause = self.parse_where_clause()?;
861+
let (ident, sig, generics) = self.parse_method_sig(|_| true)?;
864862
*at_end = true;
865863
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
866-
let header = ast::FnHeader { abi, unsafety, constness, asyncness };
867-
Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(
868-
ast::MethodSig { header, decl },
869-
body
870-
)))
864+
Ok((ident, inner_attrs, generics, ast::ImplItemKind::Method(sig, body)))
871865
}
872866
}
873867

868+
/// Parse the "signature", including the identifier, parameters, and generics
869+
/// of a method. The body is not parsed as that differs between `trait`s and `impl`s.
870+
fn parse_method_sig(
871+
&mut self,
872+
is_name_required: impl Copy + Fn(&token::Token) -> bool,
873+
) -> PResult<'a, (Ident, MethodSig, Generics)> {
874+
let header = self.parse_fn_front_matter()?;
875+
let ident = self.parse_ident()?;
876+
let mut generics = self.parse_generics()?;
877+
let decl = self.parse_fn_decl_with_self(is_name_required)?;
878+
let sig = MethodSig { header, decl };
879+
generics.where_clause = self.parse_where_clause()?;
880+
Ok((ident, sig, generics))
881+
}
882+
874883
/// Parses all the "front matter" for a `fn` declaration, up to
875884
/// and including the `fn` keyword:
876885
///
@@ -879,14 +888,7 @@ impl<'a> Parser<'a> {
879888
/// - `const unsafe fn`
880889
/// - `extern fn`
881890
/// - etc.
882-
fn parse_fn_front_matter(&mut self)
883-
-> PResult<'a, (
884-
Spanned<Constness>,
885-
Unsafety,
886-
Spanned<IsAsync>,
887-
Abi
888-
)>
889-
{
891+
fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
890892
let is_const_fn = self.eat_keyword(kw::Const);
891893
let const_span = self.prev_span;
892894
let asyncness = self.parse_asyncness();
@@ -911,7 +913,7 @@ impl<'a> Parser<'a> {
911913
// account for this.
912914
if !self.expect_one_of(&[], &[])? { unreachable!() }
913915
}
914-
Ok((constness, unsafety, asyncness, abi))
916+
Ok(FnHeader { constness, unsafety, asyncness, abi })
915917
}
916918

917919
/// Parses `trait Foo { ... }` or `trait Foo = Bar;`.
@@ -1025,59 +1027,12 @@ impl<'a> Parser<'a> {
10251027
// trait item macro.
10261028
(Ident::invalid(), ast::TraitItemKind::Macro(mac), Generics::default())
10271029
} else {
1028-
let (constness, unsafety, asyncness, abi) = self.parse_fn_front_matter()?;
1029-
1030-
let ident = self.parse_ident()?;
1031-
let mut generics = self.parse_generics()?;
1032-
10331030
// This is somewhat dubious; We don't want to allow
10341031
// argument names to be left off if there is a definition...
10351032
//
10361033
// We don't allow argument names to be left off in edition 2018.
1037-
let decl = self.parse_fn_decl_with_self(|t| t.span.rust_2018())?;
1038-
generics.where_clause = self.parse_where_clause()?;
1039-
1040-
let sig = ast::MethodSig {
1041-
header: FnHeader {
1042-
unsafety,
1043-
constness,
1044-
abi,
1045-
asyncness,
1046-
},
1047-
decl,
1048-
};
1049-
1050-
let body = match self.token.kind {
1051-
token::Semi => {
1052-
self.bump();
1053-
*at_end = true;
1054-
debug!("parse_trait_methods(): parsing required method");
1055-
None
1056-
}
1057-
token::OpenDelim(token::Brace) => {
1058-
debug!("parse_trait_methods(): parsing provided method");
1059-
*at_end = true;
1060-
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
1061-
attrs.extend(inner_attrs.iter().cloned());
1062-
Some(body)
1063-
}
1064-
token::Interpolated(ref nt) => {
1065-
match **nt {
1066-
token::NtBlock(..) => {
1067-
*at_end = true;
1068-
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
1069-
attrs.extend(inner_attrs.iter().cloned());
1070-
Some(body)
1071-
}
1072-
_ => {
1073-
return self.expected_semi_or_open_brace();
1074-
}
1075-
}
1076-
}
1077-
_ => {
1078-
return self.expected_semi_or_open_brace();
1079-
}
1080-
};
1034+
let (ident, sig, generics) = self.parse_method_sig(|t| t.span.rust_2018())?;
1035+
let body = self.parse_trait_method_body(at_end, &mut attrs)?;
10811036
(ident, ast::TraitItemKind::Method(sig, body), generics)
10821037
};
10831038

@@ -1092,6 +1047,43 @@ impl<'a> Parser<'a> {
10921047
})
10931048
}
10941049

1050+
/// Parse the "body" of a method in a trait item definition.
1051+
/// This can either be `;` when there's no body,
1052+
/// or e.g. a block when the method is a provided one.
1053+
fn parse_trait_method_body(
1054+
&mut self,
1055+
at_end: &mut bool,
1056+
attrs: &mut Vec<Attribute>,
1057+
) -> PResult<'a, Option<P<Block>>> {
1058+
Ok(match self.token.kind {
1059+
token::Semi => {
1060+
debug!("parse_trait_method_body(): parsing required method");
1061+
self.bump();
1062+
*at_end = true;
1063+
None
1064+
}
1065+
token::OpenDelim(token::Brace) => {
1066+
debug!("parse_trait_method_body(): parsing provided method");
1067+
*at_end = true;
1068+
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
1069+
attrs.extend(inner_attrs.iter().cloned());
1070+
Some(body)
1071+
}
1072+
token::Interpolated(ref nt) => {
1073+
match **nt {
1074+
token::NtBlock(..) => {
1075+
*at_end = true;
1076+
let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
1077+
attrs.extend(inner_attrs.iter().cloned());
1078+
Some(body)
1079+
}
1080+
_ => return self.expected_semi_or_open_brace(),
1081+
}
1082+
}
1083+
_ => return self.expected_semi_or_open_brace(),
1084+
})
1085+
}
1086+
10951087
/// Parses the following grammar:
10961088
///
10971089
/// TraitItemAssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty]

0 commit comments

Comments
 (0)