diff --git a/core/lib/Drupal/Core/Theme/Registry.php b/core/lib/Drupal/Core/Theme/Registry.php
index 6fb3733..0167a74 100644
--- a/core/lib/Drupal/Core/Theme/Registry.php
+++ b/core/lib/Drupal/Core/Theme/Registry.php
@@ -472,12 +472,14 @@ protected function processExtension(array &$cache, $name, $type, $theme, $path)
         // A template file is the default implementation for a theme hook, but
         // if the theme hook specifies a function callback instead, check to
         // ensure the function actually exists.
-        if (isset($info['function']) && !function_exists($info['function'])) {
-          throw new \BadFunctionCallException(sprintf(
-            'Theme hook "%s" refers to a theme function callback that does not exist: "%s"',
-            $hook,
-            $info['function']
-          ));
+        if (isset($info['function'])) {
+          if (!function_exists($info['function'])) {
+            throw new \BadFunctionCallException(sprintf(
+              'Theme hook "%s" refers to a theme function callback that does not exist: "%s"',
+              $hook,
+              $info['function']
+            ));
+          }
         }
         // Provide a default naming convention for 'template' based on the
         // hook used. If the template does not exist, the theme engine used
diff --git a/core/modules/system/src/Tests/Theme/RegistryTest.php b/core/modules/system/src/Tests/Theme/RegistryTest.php
index 1fc3715..92d52b4 100644
--- a/core/modules/system/src/Tests/Theme/RegistryTest.php
+++ b/core/modules/system/src/Tests/Theme/RegistryTest.php
@@ -100,6 +100,11 @@ public function testMultipleSubThemes() {
       'test_basetheme_preprocess_theme_test_template_test',
     ], $preprocess_functions);
 
+    $preprocess_functions = $registry_base_theme->get()['theme_test_function_suggestions']['preprocess functions'];
+    $this->assertIdentical([
+       'template_preprocess_theme_test_function_suggestions',
+       'test_basetheme_preprocess_theme_test_function_suggestions',
+    ], $preprocess_functions, "Theme functions don't have template_preprocess but do have template_preprocess_HOOK");
   }
 
   /**
diff --git a/core/modules/system/tests/modules/theme_test/theme_test.module b/core/modules/system/tests/modules/theme_test/theme_test.module
index 8b820c3..8a8841e 100644
--- a/core/modules/system/tests/modules/theme_test/theme_test.module
+++ b/core/modules/system/tests/modules/theme_test/theme_test.module
@@ -82,6 +82,12 @@ function theme_test_page_bottom(array &$page_bottom) {
 }
 
 /**
+ * Implements template_preprocess_HOOK() for theme_test_function_suggestions theme functions.
+ */
+function template_preprocess_theme_test_function_suggestions(&$variables) {
+}
+
+/**
  * Theme function for testing _theme('theme_test_foo').
  */
 function theme_theme_test_foo($variables) {
diff --git a/core/modules/system/tests/themes/test_basetheme/test_basetheme.theme b/core/modules/system/tests/themes/test_basetheme/test_basetheme.theme
index 9864286..1467e49 100644
--- a/core/modules/system/tests/themes/test_basetheme/test_basetheme.theme
+++ b/core/modules/system/tests/themes/test_basetheme/test_basetheme.theme
@@ -28,3 +28,9 @@ function test_basetheme_views_post_render(ViewExecutable $view, &$output, CacheP
  */
 function test_basetheme_preprocess_theme_test_template_test(&$variables) {
 }
+
+/**
+ * Implements hook_preprocess_HOOK() for theme_test_function_suggestions theme functions.
+ */
+function test_basetheme_preprocess_theme_test_function_suggestions(&$variables) {
+}
