diff --git a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php
index fe1ae25..4d6ba8d 100644
--- a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php
+++ b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php
@@ -38,6 +38,8 @@ public function __construct(Registry $theme_registry) {
    *
    * @param string $name
    *   The name of the template to load.
+   * @param bool $throw
+   *   Whether to throw an exception when an error occurs.
    *
    * @return string
    *   The path to the template.
@@ -45,7 +47,7 @@ public function __construct(Registry $theme_registry) {
    * @throws \Twig_Error_Loader
    *   Thrown if a template matching $name cannot be found.
    */
-  protected function findTemplate($name) {
+  protected function findTemplate($name, $throw = TRUE) {
     // Allow for loading based on the Drupal theme registry.
     $hook = str_replace('.html.twig', '', strtr($name, '-', '_'));
     $theme_registry = $this->themeRegistry->getRuntime();
@@ -63,7 +65,9 @@ protected function findTemplate($name) {
       }
     }
 
-    throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name));
+    if ($throw) {
+      throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name));
+    }
   }
 
 }
diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php
index 8d3feaa..560d7c7 100644
--- a/core/lib/Drupal/Core/Template/TwigEnvironment.php
+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -28,6 +28,8 @@ class TwigEnvironment extends \Twig_Environment {
    */
   protected $templateClasses;
 
+  protected $templateClassPrefix = '__TwigTemplate_';
+
   /**
    * Constructs a TwigEnvironment object and stores cache and storage
    * internally.
@@ -44,10 +46,6 @@ class TwigEnvironment extends \Twig_Environment {
    *   The options for the Twig environment.
    */
   public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, \Twig_LoaderInterface $loader = NULL, $options = array()) {
-    // Ensure that twig.engine is loaded, given that it is needed to render a
-    // template because functions like TwigExtension::escapeFilter() are called.
-    require_once $root . '/core/themes/engines/twig/twig.engine';
-
     $this->templateClasses = array();
 
     $options += array(
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 52291c3..b250483 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -166,7 +166,7 @@ public function getFilters() {
       new \Twig_SimpleFilter('safe_join', [$this, 'safeJoin'], ['needs_environment' => true, 'is_safe' => ['html']]),
 
       // Array filters.
-      new \Twig_SimpleFilter('without', 'twig_without'),
+      new \Twig_SimpleFilter('without', [$this, 'withoutFilter']),
 
       // CSS class and ID filters.
       new \Twig_SimpleFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'),
@@ -551,4 +551,37 @@ public function safeJoin(\Twig_Environment $env, $value, $glue = '') {
     }, $value));
   }
 
+  /**
+   * Removes child elements from a copy of the original array.
+   *
+   * Creates a copy of the renderable array and removes child elements by key
+   * specified through filter's arguments. The copy can be printed without these
+   * elements. The original renderable array is still available and can be used
+   * to print child elements in their entirety in the twig template.
+   *
+   * @param array|object $element
+   *   The parent renderable array to exclude the child items.
+   * @param string[] $args, ...
+   *   The string keys of $element to prevent printing.
+   *
+   * @return array
+   *   The filtered renderable array.
+   */
+  public function withoutFilter($element) {
+    if ($element instanceof \ArrayAccess) {
+      $filtered_element = clone $element;
+    }
+    else {
+      $filtered_element = $element;
+    }
+    $args = func_get_args();
+    unset($args[0]);
+    foreach ($args as $arg) {
+      if (isset($filtered_element[$arg])) {
+        unset($filtered_element[$arg]);
+      }
+    }
+    return $filtered_element;
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
index 757b94b..67a471b 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
@@ -25,7 +25,7 @@ class TwigNodeTrans extends \Twig_Node {
   /**
    * {@inheritdoc}
    */
-  public function __construct(\Twig_NodeInterface $body, \Twig_NodeInterface $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) {
+  public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) {
     parent::__construct(array(
       'count' => $count,
       'body' => $body,
@@ -91,7 +91,7 @@ public function compile(\Twig_Compiler $compiler) {
   /**
    * Extracts the text and tokens for the "trans" tag.
    *
-   * @param \Twig_NodeInterface $body
+   * @param \Twig_Node $body
    *   The node to compile.
    *
    * @return array
@@ -101,7 +101,7 @@ public function compile(\Twig_Compiler $compiler) {
    *   - array $tokens
    *       The extracted tokens as new \Twig_Node_Expression_Name instances.
    */
-  protected function compileString(\Twig_NodeInterface $body) {
+  protected function compileString(\Twig_Node $body) {
     if ($body instanceof \Twig_Node_Expression_Name || $body instanceof \Twig_Node_Expression_Constant || $body instanceof \Twig_Node_Expression_TempName) {
       return array($body, array());
     }
diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
index ac1e676..860cc56 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
@@ -16,19 +16,19 @@
  *
  * @see twig_render
  */
-class TwigNodeVisitor implements \Twig_NodeVisitorInterface {
+class TwigNodeVisitor extends \Twig_BaseNodeVisitor {
 
   /**
    * {@inheritdoc}
    */
-  public function enterNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
+  protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) {
     return $node;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function leaveNode(\Twig_NodeInterface $node, \Twig_Environment $env) {
+  protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) {
     // We use this to inject a call to render_var -> TwigExtension->renderVar()
     // before anything is printed.
     if ($node instanceof \Twig_Node_Print) {
diff --git a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php
index c67f463..009cc9c 100644
--- a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php
+++ b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php
@@ -82,14 +82,14 @@ public function getTag() {
   /**
    * Ensure that any nodes that are parsed are only of allowed types.
    *
-   * @param \Twig_NodeInterface $body
+   * @param \Twig_Node $body
    *   The expression to check.
    * @param integer $lineno
    *   The source line.
    *
    * @throws \Twig_Error_Syntax
    */
-  protected function checkTransString(\Twig_NodeInterface $body, $lineno) {
+  protected function checkTransString(\Twig_Node $body, $lineno) {
     foreach ($body as $node) {
       if (
         $node instanceof \Twig_Node_Text
diff --git a/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php b/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php
index 0bc52d0..f818637 100644
--- a/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php
+++ b/core/modules/system/src/Tests/Theme/TwigEnvironmentTest.php
@@ -120,13 +120,18 @@ public function testCacheFilename() {
     // Note: Later we refetch the twig service in order to bypass its internal
     // static cache.
     $environment = \Drupal::service('twig');
+    $template_path = 'core/modules/system/templates/container.html.twig';
 
-    $original_filename = $environment->getCacheFilename('core/modules/system/templates/container.html.twig');
+    $cache = $environment->getCache();
+    $class = $environment->getTemplateClass($template_path);
+    $original_filename = $cache->generateKey($template_path, $class);
     \Drupal::getContainer()->set('twig', NULL);
 
     \Drupal::service('module_installer')->install(['twig_extension_test']);
     $environment = \Drupal::service('twig');
-    $new_extension_filename = $environment->getCacheFilename('core/modules/system/templates/container.html.twig');
+    $cache = $environment->getCache();
+    $class = $environment->getTemplateClass($template_path);
+    $new_extension_filename = $cache->generateKey($template_path, $class);
     \Drupal::getContainer()->set('twig', NULL);
 
     $this->assertNotEqual($new_extension_filename, $original_filename);
diff --git a/core/modules/system/src/Tests/Theme/TwigSettingsTest.php b/core/modules/system/src/Tests/Theme/TwigSettingsTest.php
index f581fa62..74a517b 100644
--- a/core/modules/system/src/Tests/Theme/TwigSettingsTest.php
+++ b/core/modules/system/src/Tests/Theme/TwigSettingsTest.php
@@ -101,7 +101,11 @@ function testTwigCacheOverride() {
     // theme_test.template_test.html.twig.
     $info = $templates->get('theme_test_template_test');
     $template_filename = $info['path'] . '/' . $info['template'] . $extension;
-    $cache_filename = $this->container->get('twig')->getCacheFilename($template_filename);
+
+    $environment = $this->container->get('twig');
+    $cache = $environment->getCache();
+    $class = $environment->getTemplateClass($template_filename);
+    $cache_filename = $cache->generateKey($template_filename, $class);
 
     // Navigate to the page and make sure the template gets cached.
     $this->drupalGet('theme-test/template-test');
diff --git a/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php b/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php
index 3c2b851..c4c6025 100644
--- a/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php
+++ b/core/modules/system/tests/modules/twig_extension_test/src/TwigExtension/TestExtension.php
@@ -12,7 +12,7 @@
 /**
  * A test Twig extension that adds a custom function and a custom filter.
  */
-class TestExtension extends TwigExtension {
+class TestExtension extends \Twig_Extension {
 
   /**
    * Generates a list of all Twig functions that this extension defines.
@@ -27,9 +27,9 @@ class TestExtension extends TwigExtension {
    *   The value is a standard PHP callback that defines what the function does.
    */
   public function getFunctions() {
-    return array(
-      'testfunc' => new \Twig_Function_Function(array('Drupal\twig_extension_test\TwigExtension\TestExtension', 'testFunction')),
-    );
+    return [
+      new \Twig_SimpleFunction('testfunc', [$this, 'testFunction']),
+    ];
   }
 
   /**
@@ -45,9 +45,9 @@ public function getFunctions() {
    *   The value is a standard PHP callback that defines what the filter does.
    */
   public function getFilters() {
-    return array(
-      'testfilter' => new \Twig_Filter_Function(array('Drupal\twig_extension_test\TwigExtension\TestExtension', 'testFilter')),
-    );
+    return [
+      new \Twig_SimpleFilter('testfilter', [$this, 'testFilter']),
+    ];
   }
 
   /**
diff --git a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml
index 491d1e8..8784c0f 100644
--- a/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml
+++ b/core/modules/system/tests/modules/twig_extension_test/twig_extension_test.services.yml
@@ -1,6 +1,5 @@
 services:
   twig_extension_test.twig.test_extension:
-    arguments: ['@renderer']
     class: Drupal\twig_extension_test\TwigExtension\TestExtension
     tags:
       - { name: twig.extension }
diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
index 69941a9..3f7a5f1 100644
--- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Template\AttributeArray;
 use Drupal\Core\Template\AttributeString;
+use Drupal\Core\Template\Loader\StringLoader;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Component\Render\MarkupInterface;
 
@@ -268,7 +269,7 @@ public function testChainAddRemoveClasses() {
    * @covers ::addClass
    */
   public function testTwigAddRemoveClasses($template, $expected, $seed_attributes = array()) {
-    $loader = new \Twig_Loader_String();
+    $loader = new StringLoader();
     $twig = new \Twig_Environment($loader);
     $data = array('attributes' => new Attribute($seed_attributes));
     $result = $twig->render($template, $data);
diff --git a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php
index 6b9525e..ee95dc4 100644
--- a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php
@@ -5,7 +5,7 @@
  * Contains \Drupal\Tests\Core\Template\TwigExtensionTest.
  */
 
-namespace Drupal\Tests\Core\Template;
+namespace Drupal\Tests\Core\Template {
 
 use Drupal\Core\Render\RenderableInterface;
 use Drupal\Core\Render\RendererInterface;
@@ -13,6 +13,7 @@
 use Drupal\Core\Template\Loader\StringLoader;
 use Drupal\Core\Template\TwigEnvironment;
 use Drupal\Core\Template\TwigExtension;
+use Drupal\Core\Template\Loader\StringLoader;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -31,7 +32,8 @@ class TwigExtensionTest extends UnitTestCase {
    */
   public function testEscaping($template, $expected) {
     $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface');
-    $twig = new \Twig_Environment(NULL, array(
+    $loader = new \Twig_Loader_Filesystem();
+    $twig = new \Twig_Environment($loader, array(
       'debug' => TRUE,
       'cache' => FALSE,
       'autoescape' => 'html',
@@ -97,7 +99,7 @@ public function testActiveTheme() {
       ->willReturn($active_theme);
     $extension->setThemeManager($theme_manager);
 
-    $loader = new \Twig_Loader_String();
+    $loader = new StringLoader();
     $twig = new \Twig_Environment($loader);
     $twig->addExtension($extension);
     $result = $twig->render('{{ active_theme() }}');
@@ -159,7 +161,8 @@ public function testActiveThemePath() {
    */
   public function testSafeStringEscaping() {
     $renderer = $this->getMock('\Drupal\Core\Render\RendererInterface');
-    $twig = new \Twig_Environment(NULL, array(
+    $loader = new \Twig_Loader_Filesystem();
+    $twig = new \Twig_Environment($loader, array(
       'debug' => TRUE,
       'cache' => FALSE,
       'autoescape' => 'html',
@@ -241,3 +244,16 @@ public function __toString() {
   }
 
 }
+
+}
+
+namespace {
+  if (!function_exists('t')) {
+    function t($string, array $args = []) {
+      return strtr($string, $args);
+    }
+  }
+  if (!function_exists('file_create_url')) {
+    function file_create_url() {}
+  }
+}
diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine
index 44ee5ac..bb83d5d 100644
--- a/core/themes/engines/twig/twig.engine
+++ b/core/themes/engines/twig/twig.engine
@@ -118,36 +118,3 @@ function twig_render_template($template_file, array $variables) {
   // This output has already been rendered and is therefore considered safe.
   return Markup::create(implode('', $output));
 }
-
-/**
- * Removes child elements from a copy of the original array.
- *
- * Creates a copy of the renderable array and removes child elements by key
- * specified through filter's arguments. The copy can be printed without these
- * elements. The original renderable array is still available and can be used
- * to print child elements in their entirety in the twig template.
- *
- * @param array|object $element
- *   The parent renderable array to exclude the child items.
- * @param string[] $args, ...
- *   The string keys of $element to prevent printing.
- *
- * @return array
- *   The filtered renderable array.
- */
-function twig_without($element) {
-  if ($element instanceof ArrayAccess) {
-    $filtered_element = clone $element;
-  }
-  else {
-    $filtered_element = $element;
-  }
-  $args = func_get_args();
-  unset($args[0]);
-  foreach ($args as $arg) {
-    if (isset($filtered_element[$arg])) {
-      unset($filtered_element[$arg]);
-    }
-  }
-  return $filtered_element;
-}
