about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-01-30 00:18:54 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-02-05 01:27:09 +0100
commitb2c6eeb713d4cf9b35b7dda6ff2b0274e7f24684 (patch)
treedb169a7cc1f065c0b2975a1178d3afdef5a172b4 /src/libsyntax
parentc0b7b41cff2b40d430befefc8688fb8ad847bcd4 (diff)
downloadrust-b2c6eeb713d4cf9b35b7dda6ff2b0274e7f24684.tar.gz
rust-b2c6eeb713d4cf9b35b7dda6ff2b0274e7f24684.zip
parser: merge `fn` grammars wrt. bodies & headers
also refactor `FnKind` and `visit_assoc_item` visitors
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs15
-rw-r--r--src/libsyntax/mut_visit.rs7
-rw-r--r--src/libsyntax/visit.rs136
3 files changed, 80 insertions, 78 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 5a8c9f76ea9..b22406124e0 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -2533,6 +2533,17 @@ pub struct FnHeader {
     pub ext: Extern,
 }
 
+impl FnHeader {
+    /// Does this function header have any qualifiers or is it empty?
+    pub fn has_qualifiers(&self) -> bool {
+        let Self { unsafety, asyncness, constness, ext } = self;
+        matches!(unsafety, Unsafety::Unsafe)
+            || asyncness.node.is_async()
+            || matches!(constness.node, Constness::Const)
+            || !matches!(ext, Extern::None)
+    }
+}
+
 impl Default for FnHeader {
     fn default() -> FnHeader {
         FnHeader {
@@ -2565,7 +2576,7 @@ pub enum ItemKind {
     /// A function declaration (`fn`).
     ///
     /// E.g., `fn foo(bar: usize) -> usize { .. }`.
-    Fn(FnSig, Generics, P<Block>),
+    Fn(FnSig, Generics, Option<P<Block>>),
     /// A module declaration (`mod`).
     ///
     /// E.g., `mod foo;` or `mod foo { .. }`.
@@ -2667,7 +2678,7 @@ pub type ForeignItem = Item<ForeignItemKind>;
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum ForeignItemKind {
     /// A foreign function.
-    Fn(P<FnDecl>, Generics),
+    Fn(FnSig, Generics, Option<P<Block>>),
     /// A foreign static item (`static ext: u8`).
     Static(P<Ty>, Mutability),
     /// A foreign type.
diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs
index 3bcdf8fe286..8517f223f92 100644
--- a/src/libsyntax/mut_visit.rs
+++ b/src/libsyntax/mut_visit.rs
@@ -901,7 +901,7 @@ pub fn noop_visit_item_kind<T: MutVisitor>(kind: &mut ItemKind, vis: &mut T) {
         ItemKind::Fn(sig, generics, body) => {
             visit_fn_sig(sig, vis);
             vis.visit_generics(generics);
-            vis.visit_block(body);
+            visit_opt(body, |body| vis.visit_block(body));
         }
         ItemKind::Mod(m) => vis.visit_mod(m),
         ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm),
@@ -1044,9 +1044,10 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
     visitor.visit_ident(ident);
     visit_attrs(attrs, visitor);
     match kind {
-        ForeignItemKind::Fn(fdec, generics) => {
-            visitor.visit_fn_decl(fdec);
+        ForeignItemKind::Fn(sig, generics, body) => {
+            visit_fn_sig(sig, visitor);
             visitor.visit_generics(generics);
+            visit_opt(body, |body| visitor.visit_block(body));
         }
         ForeignItemKind::Static(t, _m) => visitor.visit_ty(t),
         ForeignItemKind::Ty => {}
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 946a0d29cd3..73e731397c3 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -19,24 +19,47 @@ use crate::tokenstream::{TokenStream, TokenTree};
 
 use rustc_span::Span;
 
+#[derive(Copy, Clone, PartialEq)]
+pub enum AssocCtxt {
+    Trait,
+    Impl,
+}
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum FnCtxt {
+    Free,
+    Foreign,
+    Assoc(AssocCtxt),
+}
+
 #[derive(Copy, Clone)]
 pub enum FnKind<'a> {
-    /// E.g., `fn foo()` or `extern "Abi" fn foo()`.
-    ItemFn(Ident, &'a FnHeader, &'a Visibility, &'a Block),
-
-    /// E.g., `fn foo(&self)`.
-    Method(Ident, &'a FnSig, &'a Visibility, &'a Block),
+    /// E.g., `fn foo()`, `fn foo(&self)`, or `extern "Abi" fn foo()`.
+    Fn(FnCtxt, Ident, &'a FnSig, &'a Visibility, Option<&'a Block>),
 
     /// E.g., `|x, y| body`.
-    Closure(&'a Expr),
+    Closure(&'a FnDecl, &'a Expr),
 }
 
 impl<'a> FnKind<'a> {
     pub fn header(&self) -> Option<&'a FnHeader> {
         match *self {
-            FnKind::ItemFn(_, header, _, _) => Some(header),
-            FnKind::Method(_, sig, _, _) => Some(&sig.header),
-            FnKind::Closure(_) => None,
+            FnKind::Fn(_, _, sig, _, _) => Some(&sig.header),
+            FnKind::Closure(_, _) => None,
+        }
+    }
+
+    pub fn decl(&self) -> &'a FnDecl {
+        match self {
+            FnKind::Fn(_, _, sig, _, _) => &sig.decl,
+            FnKind::Closure(decl, _) => decl,
+        }
+    }
+
+    pub fn ctxt(&self) -> Option<FnCtxt> {
+        match self {
+            FnKind::Fn(ctxt, ..) => Some(*ctxt),
+            FnKind::Closure(..) => None,
         }
     }
 }
@@ -106,17 +129,11 @@ pub trait Visitor<'ast>: Sized {
     fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
         walk_where_predicate(self, p)
     }
-    fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, s: Span, _: NodeId) {
-        walk_fn(self, fk, fd, s)
-    }
-    fn visit_trait_item(&mut self, i: &'ast AssocItem) {
-        walk_trait_item(self, i)
+    fn visit_fn(&mut self, fk: FnKind<'ast>, s: Span, _: NodeId) {
+        walk_fn(self, fk, s)
     }
-    fn visit_impl_item(&mut self, i: &'ast AssocItem) {
-        walk_impl_item(self, i)
-    }
-    fn visit_assoc_item(&mut self, i: &'ast AssocItem) {
-        walk_assoc_item(self, i)
+    fn visit_assoc_item(&mut self, i: &'ast AssocItem, ctxt: AssocCtxt) {
+        walk_assoc_item(self, i, ctxt)
     }
     fn visit_trait_ref(&mut self, t: &'ast TraitRef) {
         walk_trait_ref(self, t)
@@ -287,13 +304,8 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
         }
         ItemKind::Fn(ref sig, ref generics, ref body) => {
             visitor.visit_generics(generics);
-            visitor.visit_fn_header(&sig.header);
-            visitor.visit_fn(
-                FnKind::ItemFn(item.ident, &sig.header, &item.vis, body),
-                &sig.decl,
-                item.span,
-                item.id,
-            )
+            let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref());
+            visitor.visit_fn(kind, item.span, item.id)
         }
         ItemKind::Mod(ref module) => visitor.visit_mod(module, item.span, &item.attrs, item.id),
         ItemKind::ForeignMod(ref foreign_module) => {
@@ -321,17 +333,17 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_trait_ref, of_trait);
             visitor.visit_ty(self_ty);
-            walk_list!(visitor, visit_impl_item, items);
+            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Impl);
         }
         ItemKind::Struct(ref struct_definition, ref generics)
         | ItemKind::Union(ref struct_definition, ref generics) => {
             visitor.visit_generics(generics);
             visitor.visit_variant_data(struct_definition);
         }
-        ItemKind::Trait(.., ref generics, ref bounds, ref methods) => {
+        ItemKind::Trait(.., ref generics, ref bounds, ref items) => {
             visitor.visit_generics(generics);
             walk_list!(visitor, visit_param_bound, bounds);
-            walk_list!(visitor, visit_trait_item, methods);
+            walk_list!(visitor, visit_assoc_item, items, AssocCtxt::Trait);
         }
         ItemKind::TraitAlias(ref generics, ref bounds) => {
             visitor.visit_generics(generics);
@@ -512,21 +524,22 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) {
     }
 }
 
-pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, foreign_item: &'a ForeignItem) {
-    visitor.visit_vis(&foreign_item.vis);
-    visitor.visit_ident(foreign_item.ident);
+pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) {
+    visitor.visit_vis(&item.vis);
+    visitor.visit_ident(item.ident);
 
-    match foreign_item.kind {
-        ForeignItemKind::Fn(ref function_declaration, ref generics) => {
-            walk_fn_decl(visitor, function_declaration);
-            visitor.visit_generics(generics)
+    match item.kind {
+        ForeignItemKind::Fn(ref sig, ref generics, ref body) => {
+            visitor.visit_generics(generics);
+            let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref());
+            visitor.visit_fn(kind, item.span, item.id);
         }
         ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ),
         ForeignItemKind::Ty => (),
         ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac),
     }
 
-    walk_list!(visitor, visit_attribute, &foreign_item.attrs);
+    walk_list!(visitor, visit_attribute, &item.attrs);
 }
 
 pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) {
@@ -594,37 +607,21 @@ pub fn walk_fn_decl<'a, V: Visitor<'a>>(visitor: &mut V, function_declaration: &
     visitor.visit_fn_ret_ty(&function_declaration.output);
 }
 
-pub fn walk_fn<'a, V>(visitor: &mut V, kind: FnKind<'a>, declaration: &'a FnDecl, _span: Span)
-where
-    V: Visitor<'a>,
-{
+pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Span) {
     match kind {
-        FnKind::ItemFn(_, header, _, body) => {
-            visitor.visit_fn_header(header);
-            walk_fn_decl(visitor, declaration);
-            visitor.visit_block(body);
-        }
-        FnKind::Method(_, sig, _, body) => {
+        FnKind::Fn(_, _, sig, _, body) => {
             visitor.visit_fn_header(&sig.header);
-            walk_fn_decl(visitor, declaration);
-            visitor.visit_block(body);
+            walk_fn_decl(visitor, &sig.decl);
+            walk_list!(visitor, visit_block, body);
         }
-        FnKind::Closure(body) => {
-            walk_fn_decl(visitor, declaration);
+        FnKind::Closure(decl, body) => {
+            walk_fn_decl(visitor, decl);
             visitor.visit_expr(body);
         }
     }
 }
 
-pub fn walk_impl_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
-    visitor.visit_assoc_item(item);
-}
-
-pub fn walk_trait_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
-    visitor.visit_assoc_item(item);
-}
-
-pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem) {
+pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) {
     visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.ident);
     walk_list!(visitor, visit_attribute, &item.attrs);
@@ -634,17 +631,9 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem)
             visitor.visit_ty(ty);
             walk_list!(visitor, visit_expr, expr);
         }
-        AssocItemKind::Fn(ref sig, None) => {
-            visitor.visit_fn_header(&sig.header);
-            walk_fn_decl(visitor, &sig.decl);
-        }
-        AssocItemKind::Fn(ref sig, Some(ref body)) => {
-            visitor.visit_fn(
-                FnKind::Method(item.ident, sig, &item.vis, body),
-                &sig.decl,
-                item.span,
-                item.id,
-            );
+        AssocItemKind::Fn(ref sig, ref body) => {
+            let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref());
+            visitor.visit_fn(kind, item.span, item.id);
         }
         AssocItemKind::TyAlias(ref bounds, ref ty) => {
             walk_list!(visitor, visit_param_bound, bounds);
@@ -765,8 +754,9 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
             visitor.visit_expr(subexpression);
             walk_list!(visitor, visit_arm, arms);
         }
-        ExprKind::Closure(_, _, _, ref function_declaration, ref body, _decl_span) => visitor
-            .visit_fn(FnKind::Closure(body), function_declaration, expression.span, expression.id),
+        ExprKind::Closure(_, _, _, ref decl, ref body, _decl_span) => {
+            visitor.visit_fn(FnKind::Closure(decl, body), expression.span, expression.id)
+        }
         ExprKind::Block(ref block, ref opt_label) => {
             walk_list!(visitor, visit_label, opt_label);
             visitor.visit_block(block);