Просмотр исходного кода

Form a struct value directly in tree extraction. (#3563)

Don't first form a `std::tuple` and then convert it to a struct. Speeds
up compilation of extract.cpp by 15-20%.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: josh11b <josh11b@users.noreply.github.com>
Richard Smith 2 лет назад
Родитель
Сommit
840cb1bed7
2 измененных файлов с 30 добавлено и 73 удалено
  1. 30 59
      toolchain/parse/extract.cpp
  2. 0 14
      toolchain/parse/typed_nodes_test.cpp

+ 30 - 59
toolchain/parse/extract.cpp

@@ -245,49 +245,36 @@ struct Extractable<std::optional<T>> {
   }
 };
 
-// Extract a `tuple<T...>` from a list of child nodes by extracting each `T` in
-// reverse order.
-template <typename... T>
-struct Extractable<std::tuple<T...>> {
-  template <std::size_t... Index>
-  static auto ExtractImpl(const Tree* tree, Tree::SiblingIterator& it,
-                          Tree::SiblingIterator end, ErrorBuilder* trace,
-                          std::index_sequence<Index...>)
-      -> std::optional<std::tuple<T...>> {
-    std::tuple<std::optional<T>...> fields;
-    if (trace) {
-      *trace << sizeof...(T) << "-tuple: begin\n";
-    }
-
-    // Use a fold over the `=` operator to parse fields from right to left.
-    [[maybe_unused]] int unused;
-    bool ok = true;
-    static_cast<void>(
-        ((ok && (ok = (std::get<Index>(fields) =
-                           Extractable<T>::Extract(tree, it, end, trace))
-                          .has_value()),
-          unused) = ... = 0));
-
-    if (!ok) {
-      if (trace) {
-        *trace << sizeof...(T) << "-tuple: error\n";
-      }
-      return std::nullopt;
-    }
-
+template <typename T, typename... U, std::size_t... Index>
+static auto ExtractTupleLikeType(const Tree* tree, Tree::SiblingIterator& it,
+                                 Tree::SiblingIterator end, ErrorBuilder* trace,
+                                 std::index_sequence<Index...> /*indices*/,
+                                 std::tuple<U...>* /*type*/)
+    -> std::optional<T> {
+  std::tuple<std::optional<U>...> fields;
+  if (trace) {
+    *trace << "Aggregate " << typeid(T).name() << ": begin\n";
+  }
+  // Use a fold over the `=` operator to parse fields from right to left.
+  [[maybe_unused]] int unused;
+  bool ok = true;
+  static_cast<void>(
+      ((ok && (ok = (std::get<Index>(fields) =
+                         Extractable<U>::Extract(tree, it, end, trace))
+                        .has_value()),
+        unused) = ... = 0));
+  if (!ok) {
     if (trace) {
-      *trace << sizeof...(T) << "-tuple: success\n";
+      *trace << "Aggregate " << typeid(T).name() << ": error\n";
     }
-    return std::tuple<T...>{std::move(std::get<Index>(fields).value())...};
+    return std::nullopt;
   }
 
-  static auto Extract(const Tree* tree, Tree::SiblingIterator& it,
-                      Tree::SiblingIterator end, ErrorBuilder* trace)
-      -> std::optional<std::tuple<T...>> {
-    return ExtractImpl(tree, it, end, trace,
-                       std::make_index_sequence<sizeof...(T)>());
+  if (trace) {
+    *trace << "Aggregate " << typeid(T).name() << ": success\n";
   }
-};
+  return T{std::move(std::get<Index>(fields).value())...};
+}
 
 // Extract the fields of a simple aggregate type.
 template <typename T>
@@ -296,28 +283,12 @@ struct Extractable {
   static auto ExtractImpl(const Tree* tree, Tree::SiblingIterator& it,
                           Tree::SiblingIterator end, ErrorBuilder* trace)
       -> std::optional<T> {
-    if (trace) {
-      *trace << "Aggregate " << typeid(T).name() << ": begin\n";
-    }
-    // Extract the corresponding tuple type.
+    // Compute the corresponding tuple type.
     using TupleType = decltype(StructReflection::AsTuple(std::declval<T>()));
-    auto tuple = Extractable<TupleType>::Extract(tree, it, end, trace);
-    if (!tuple.has_value()) {
-      if (trace) {
-        *trace << "Aggregate " << typeid(T).name() << ": error\n";
-      }
-      return std::nullopt;
-    }
-
-    if (trace) {
-      *trace << "Aggregate " << typeid(T).name() << ": success\n";
-    }
-    // Convert the tuple to the struct type.
-    return std::apply(
-        [](auto&&... value) {
-          return T{std::forward<decltype(value)>(value)...};
-        },
-        *tuple);
+    return ExtractTupleLikeType<T>(
+        tree, it, end, trace,
+        std::make_index_sequence<std::tuple_size_v<TupleType>>(),
+        (TupleType*)nullptr);
   }
 
   static auto Extract(const Tree* tree, Tree::SiblingIterator& it,

+ 0 - 14
toolchain/parse/typed_nodes_test.cpp

@@ -151,11 +151,9 @@ TEST_F(TypedNodeTest, VerifyExtractTraceLibrary) {
   // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`.
   EXPECT_THAT(err.message(), testing::MatchesRegex(
                                  R"Trace(Aggregate [^:]*: begin
-3-tuple: begin
 NodeIdOneOf PackageApi or PackageImpl: PackageImpl consumed
 NodeIdOneOf LibraryName or DefaultLibrary: DefaultLibrary consumed
 NodeIdForKind: LibraryIntroducer consumed
-3-tuple: success
 Aggregate [^:]*: success
 )Trace"));
 }
@@ -174,12 +172,9 @@ TEST_F(TypedNodeTest, VerifyExtractTraceVarNoInit) {
   // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`.
   EXPECT_THAT(err.message(), testing::MatchesRegex(
                                  R"Trace(Aggregate [^:]*: begin
-5-tuple: begin
 Optional [^:]*: begin
 Aggregate [^:]*: begin
-2-tuple: begin
 NodeIdInCategory Expr error: kind BindingPattern doesn't match
-2-tuple: error
 Aggregate [^:]*: error
 Optional [^:]*: missing
 NodeIdInCategory Pattern: kind BindingPattern consumed
@@ -190,7 +185,6 @@ Vector: begin
 NodeIdInCategory Modifier error: kind VariableIntroducer doesn't match
 Vector: end
 NodeIdForKind: VariableIntroducer consumed
-5-tuple: success
 Aggregate [^:]*: success
 )Trace"));
 }
@@ -209,13 +203,10 @@ TEST_F(TypedNodeTest, VerifyExtractTraceExpression) {
   // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`.
   EXPECT_THAT(err1.message(), testing::MatchesRegex(
                                   R"Trace(Aggregate [^:]*: begin
-5-tuple: begin
 Optional [^:]*leDecl11InitializerE: begin
 Aggregate [^:]*: begin
-2-tuple: begin
 NodeIdInCategory Expr: kind MemberAccessExpr consumed
 NodeIdForKind: VariableInitializer consumed
-2-tuple: success
 Aggregate [^:]*: success
 Optional [^:]*: found
 NodeIdInCategory Pattern: kind BindingPattern consumed
@@ -226,7 +217,6 @@ Vector: begin
 NodeIdInCategory Modifier error: kind VariableIntroducer doesn't match
 Vector: end
 NodeIdForKind: VariableIntroducer consumed
-5-tuple: success
 Aggregate [^:]*: success
 )Trace"));
 
@@ -239,10 +229,8 @@ Aggregate [^:]*: success
   // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`.
   EXPECT_THAT(err2.message(), testing::MatchesRegex(
                                   R"Trace(Aggregate [^:]*: begin
-2-tuple: begin
 NodeIdInCategory MemberName: kind IdentifierName consumed
 NodeIdInCategory Expr: kind PointerMemberAccessExpr consumed
-2-tuple: success
 Aggregate [^:]*: success
 )Trace"));
 }
@@ -261,7 +249,6 @@ TEST_F(TypedNodeTest, VerifyExtractTraceClassDecl) {
   // Use Regex matching to avoid hard-coding the result of `typeinfo(T).name()`.
   EXPECT_THAT(err.message(), testing::MatchesRegex(
                                  R"Trace(Aggregate [^:]*: begin
-5-tuple: begin
 Optional [^:]*: begin
 NodeIdForKind: TuplePattern consumed
 Optional [^:]*: found
@@ -275,7 +262,6 @@ NodeIdInCategory Modifier: kind PrivateModifier consumed
 NodeIdInCategory Modifier error: kind ClassIntroducer doesn't match
 Vector: end
 NodeIdForKind: ClassIntroducer consumed
-5-tuple: success
 Aggregate [^:]*: success
 )Trace"));
 }