diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 9d37754d73b3115ba2b0bb434b4d2c5c7a53de3e..f2bce97ff3368c9640e1914a3d9f1df64b0daed3 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -344,13 +344,14 @@ function theme_get_setting($setting_name, $theme = NULL) {
  * @throws \Exception
  *   Thrown when an object is passed in which cannot be printed.
  *
- * @see \Drupal\Core\Template\TwigExtension::escapeFilter()
+ * @deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no
+ *   replacement. Theme engines must handle escaping by themselves.
  *
- * @todo Discuss deprecating this in https://www.drupal.org/node/2575081.
- * @todo Refactor this to keep it in sync with Twig filtering in
- *   https://www.drupal.org/node/2575065
+ * @see https://www.drupal.org/node/3336253
  */
 function theme_render_and_autoescape($arg) {
+  @trigger_error('theme_render_and_autoescape() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no replacement. Theme engines must handle escaping by themselves. See https://www.drupal.org/node/3336253', E_USER_DEPRECATED);
+
   // If it's a renderable, then it'll be up to the generated render array it
   // returns to contain the necessary cacheability & attachment metadata. If
   // it doesn't implement CacheableDependencyInterface or AttachmentsInterface
diff --git a/core/lib/Drupal/Core/Render/theme.api.php b/core/lib/Drupal/Core/Render/theme.api.php
index 5c3081555bb21e972f94fcefb1a77849c0b7be3a..19058e346207ed19d0bb3bce5a458fcac0026c2a 100644
--- a/core/lib/Drupal/Core/Render/theme.api.php
+++ b/core/lib/Drupal/Core/Render/theme.api.php
@@ -760,8 +760,7 @@ function hook_extension() {
  * It is the theme engine's responsibility to escape variables. The only
  * exception is if a variable implements
  * \Drupal\Component\Render\MarkupInterface. Drupal is inherently unsafe if
- * other variables are not escaped. The helper function
- * theme_render_and_autoescape() may be used for this.
+ * other variables are not escaped.
  *
  * @param string $template_file
  *   The path (relative to the Drupal root directory) to the template to be
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index e38c0a0fcbbd23ef6d233167fa5d630919ccd039..eb748c8dfe77fe3b400664b87c0aca1da27f2771 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -387,9 +387,6 @@ public function escapePlaceholder(Environment $env, $string) {
    *
    * Replacement function for Twig's escape filter.
    *
-   * Note: This function should be kept in sync with
-   * theme_render_and_autoescape().
-   *
    * @param \Twig\Environment $env
    *   A Twig Environment instance.
    * @param mixed $arg
@@ -408,9 +405,6 @@ public function escapePlaceholder(Environment $env, $string) {
    * @throws \Exception
    *   When $arg is passed as an object which does not implement __toString(),
    *   RenderableInterface or toString().
-   *
-   * @todo Refactor this to keep it in sync with theme_render_and_autoescape()
-   *   in https://www.drupal.org/node/2575065
    */
   public function escapeFilter(Environment $env, $arg, $strategy = 'html', $charset = NULL, $autoescape = FALSE) {
     // Check for a numeric zero int or float.
diff --git a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine b/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
index 44a50da8ade7d4cd77e41a2eb23e0f93c660a06c..bcc3f7ef83f79431abf55c9af9aa5ff4b3058593 100644
--- a/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
+++ b/core/modules/system/tests/themes/engines/nyan_cat/nyan_cat.engine
@@ -5,6 +5,7 @@
  * Handles integration of Nyan cat templates because we love kittens.
  */
 
+use Drupal\Component\Utility\Html;
 use Drupal\Core\Extension\Extension;
 
 /**
@@ -36,7 +37,7 @@ function nyan_cat_render_template($template_file, $variables) {
   $output = str_replace('div', 'nyancat', file_get_contents(\Drupal::root() . '/' . $template_file));
   foreach ($variables as $key => $variable) {
     if (strpos($output, '9' . $key) !== FALSE) {
-      $output = str_replace('9' . $key, theme_render_and_autoescape($variable), $output);
+      $output = str_replace('9' . $key, Html::escape($variable), $output);
     }
   }
   return $output;
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php b/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
index 722d559981053de733afcedd9cda82b13e77d477..5c47f174a78d63241ca7f58f181b4cb0b70ec818 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/ThemeRenderAndAutoescapeTest.php
@@ -19,6 +19,7 @@
  * Tests the theme_render_and_autoescape() function.
  *
  * @group Theme
+ * @group legacy
  */
 class ThemeRenderAndAutoescapeTest extends KernelTestBase {
 
@@ -27,6 +28,14 @@ class ThemeRenderAndAutoescapeTest extends KernelTestBase {
    */
   protected static $modules = ['system'];
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->expectDeprecation('theme_render_and_autoescape() is deprecated in drupal:10.1.0 and is removed from drupal:11.0.0. There is no replacement. Theme engines must handle escaping by themselves. See https://www.drupal.org/node/3336253');
+  }
+
   /**
    * @dataProvider providerTestThemeRenderAndAutoescape
    */