diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 5296b08..fa4caa8 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1122,7 +1122,7 @@ function theme($hook, $variables = array()) {
 
   // restore path_to_theme()
   $theme_path = $temp;
-  return $output;
+  return (string) $output;
 }
 
 /**
diff --git a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
index 8bbb3d0..9f3c477 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Theme/ThemeTest.php
@@ -58,6 +58,24 @@ function testAttributeMerging() {
   }
 
   /**
+   * Test that theme() returns expected data types.
+   */
+  function testThemeDataTypes() {
+    // theme_test_false is an implemented theme hook so theme() should return a
+    // string, even though the theme function itself can return anything.
+    $foos = array('null' => NULL, 'false' => FALSE, 'integer' => 1, 'string' => 'foo');
+    foreach ($foos as $type => $example) {
+      $output = theme('theme_test_foo', array('foo' => $example));
+      $this->assertTrue(is_string($output), 'theme() returns a string for data type ' . $type);
+    }
+
+    // suggestionnotimplemented is not an implemented theme hook so theme()
+    // should return FALSE instead of a string.
+    $output = theme(array('suggestionnotimplemented'));
+    $this->assertIdentical($output, FALSE, 'theme() returns FALSE when a hook suggestion is not implemented');
+  }
+
+  /**
    * Test function theme_get_suggestions() for SA-CORE-2009-003.
    */
   function testThemeSuggestions() {
