diff --git a/composer.lock b/composer.lock
index 9b2b43dfe3195c84a7377be279ffe2a3f3677e3d..59e4b29c99f2a804b5d5119ef30e747f732bb2ae 100644
--- a/composer.lock
+++ b/composer.lock
@@ -653,7 +653,7 @@
             "dist": {
                 "type": "path",
                 "url": "core",
-                "reference": "9faae700fd9adfe0a1c5ffd73dcc334b3be5ce5a"
+                "reference": "ae05b62ba90c6bb364ba715d7005d99e188b8b85"
             },
             "require": {
                 "asm89/stack-cors": "^1.1",
@@ -695,7 +695,7 @@
                 "symfony/translation": "^4.4",
                 "symfony/validator": "^4.4",
                 "symfony/yaml": "^4.4",
-                "twig/twig": "^1.38.2",
+                "twig/twig": "^2.12.0",
                 "typo3/phar-stream-wrapper": "^3.1.3",
                 "zendframework/zend-diactoros": "^1.8",
                 "zendframework/zend-feed": "^2.12"
@@ -3472,21 +3472,22 @@
         },
         {
             "name": "twig/twig",
-            "version": "v1.42.3",
+            "version": "v2.12.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/twigphp/Twig.git",
-                "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e"
+                "reference": "ddd4134af9bfc6dba4eff7c8447444ecc45b9ee5"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/twigphp/Twig/zipball/201baee843e0ffe8b0b956f336dd42b2a92fae4e",
-                "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e",
+                "url": "https://api.github.com/repos/twigphp/Twig/zipball/ddd4134af9bfc6dba4eff7c8447444ecc45b9ee5",
+                "reference": "ddd4134af9bfc6dba4eff7c8447444ecc45b9ee5",
                 "shasum": ""
             },
             "require": {
-                "php": ">=5.5.0",
-                "symfony/polyfill-ctype": "^1.8"
+                "php": "^7.0",
+                "symfony/polyfill-ctype": "^1.8",
+                "symfony/polyfill-mbstring": "^1.3"
             },
             "require-dev": {
                 "psr/container": "^1.0",
@@ -3496,7 +3497,7 @@
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "1.42-dev"
+                    "dev-master": "2.12-dev"
                 }
             },
             "autoload": {
@@ -3534,7 +3535,7 @@
             "keywords": [
                 "templating"
             ],
-            "time": "2019-08-24T12:51:03+00:00"
+            "time": "2019-10-17T07:34:53+00:00"
         },
         {
             "name": "typo3/phar-stream-wrapper",
diff --git a/composer/Metapackage/CoreRecommended/composer.json b/composer/Metapackage/CoreRecommended/composer.json
index c42c8708a846d78a8c4b59b93eaba4bf94fcc032..fabe0c14b6e40e45def86e80684ec2c472ba0610 100644
--- a/composer/Metapackage/CoreRecommended/composer.json
+++ b/composer/Metapackage/CoreRecommended/composer.json
@@ -59,7 +59,7 @@
         "symfony/translation-contracts": "v1.1.7",
         "symfony/validator": "4.4.x-dev",
         "symfony/yaml": "4.4.x-dev",
-        "twig/twig": "v1.42.3",
+        "twig/twig": "v2.12.1",
         "typo3/phar-stream-wrapper": "v3.1.3",
         "zendframework/zend-diactoros": "1.8.7",
         "zendframework/zend-escaper": "2.6.1",
diff --git a/core/composer.json b/core/composer.json
index 392bbe073a9de00fc78609f058367c5845dd49b9..2573c591d23b34bb0f93a7f126e4540fe421320a 100644
--- a/core/composer.json
+++ b/core/composer.json
@@ -32,7 +32,7 @@
         "symfony/polyfill-iconv": "^1.0",
         "symfony/yaml": "^4.4",
         "typo3/phar-stream-wrapper": "^3.1.3",
-        "twig/twig": "^1.38.2",
+        "twig/twig": "^2.12.0",
         "doctrine/common": "^2.7",
         "doctrine/annotations": "^1.4",
         "guzzlehttp/guzzle": "^6.3",
diff --git a/core/core.services.yml b/core/core.services.yml
index 9d6ad2711a12597e054d81e2139ceaa894aa0bf9..5cdcc3efe5a5bbff5010b74a98ddf961dbce052c 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -1643,11 +1643,11 @@ services:
   # @todo Figure out what to do about debugging functions.
   # @see https://www.drupal.org/node/1804998
   twig.extension.debug:
-    class: Twig_Extension_Debug
+    class: Twig\Extension\DebugExtension
     tags:
       - { name: twig.extension }
   twig.loader:
-    class: Twig_Loader_Chain
+    class: Twig\Loader\ChainLoader
     public: false
     tags:
       - { name: service_collector, tag: twig.loader, call: addLoader, required: TRUE }
diff --git a/core/lib/Drupal/Core/Render/Markup.php b/core/lib/Drupal/Core/Render/Markup.php
index 0947f8fc675eae35715eed1704c3430f59ee1395..8278389df9134c6bf32938aca9428dcdbaacb6e8 100644
--- a/core/lib/Drupal/Core/Render/Markup.php
+++ b/core/lib/Drupal/Core/Render/Markup.php
@@ -17,7 +17,7 @@
  *   rendering.
  *
  * @see \Drupal\Core\Template\TwigExtension::escapeFilter
- * @see \Twig_Markup
+ * @see \Twig\Markup
  */
 final class Markup implements MarkupInterface, \Countable {
   use MarkupTrait;
diff --git a/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php b/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php
index b84e790b62f93d9d8c48846345ac43ba704ff385..4edb6e2d8d740c82130057b74fd7823dbce5d808 100644
--- a/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php
+++ b/core/lib/Drupal/Core/Template/Loader/FilesystemLoader.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Extension\ThemeHandlerInterface;
+use Twig\Loader\FilesystemLoader as TwigFilesystemLoader;
 
 /**
  * Loads templates from the filesystem.
@@ -12,7 +13,7 @@
  * filesystem loader so that templates can be referenced by namespace, like
  * @block/block.html.twig or @mytheme/page.html.twig.
  */
-class FilesystemLoader extends \Twig_Loader_Filesystem {
+class FilesystemLoader extends TwigFilesystemLoader {
 
   /**
    * Constructs a new FilesystemLoader object.
diff --git a/core/lib/Drupal/Core/Template/Loader/StringLoader.php b/core/lib/Drupal/Core/Template/Loader/StringLoader.php
index 909a09a8f86e19857456aabf1e5575611079e186..3991a72680278df9f4ddfc03d35929c39b350a1f 100644
--- a/core/lib/Drupal/Core/Template/Loader/StringLoader.php
+++ b/core/lib/Drupal/Core/Template/Loader/StringLoader.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\Core\Template\Loader;
 
-use Twig\Loader\ExistsLoaderInterface;
+use Twig\Loader\LoaderInterface;
 use Twig\Loader\SourceContextLoaderInterface;
 use Twig\Source;
 
@@ -18,13 +18,13 @@
  * This class override ensures that the string loader behaves as expected in
  * the loader chain. If Twig's string loader is used as is, any string (even a
  * reference to a file-based Twig template) is treated as a valid template and
- * is rendered instead of a \Twig_Error_Loader exception being thrown.
+ * is rendered instead of a \Twig\Error\LoaderError exception being thrown.
  *
  * @see \Drupal\Core\Template\TwigEnvironment::renderInline()
  * @see \Drupal\Core\Render\Element\InlineTemplate
  * @see twig_render_template()
  */
-class StringLoader implements \Twig_LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface {
+class StringLoader implements LoaderInterface, SourceContextLoaderInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php
index 862092b6062a0d085b99ea19d4ecc6fd71139acf..b59b83d8ffffd5ad8f4d3a0c86d4ef1c4840e845 100644
--- a/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php
+++ b/core/lib/Drupal/Core/Template/Loader/ThemeRegistryLoader.php
@@ -3,13 +3,15 @@
 namespace Drupal\Core\Template\Loader;
 
 use Drupal\Core\Theme\Registry;
+use Twig\Error\LoaderError;
+use Twig\Loader\FilesystemLoader;
 
 /**
  * Loads templates based on information from the Drupal theme registry.
  *
  * Allows for template inheritance based on the currently active template.
  */
-class ThemeRegistryLoader extends \Twig_Loader_Filesystem {
+class ThemeRegistryLoader extends FilesystemLoader {
 
   /**
    * The theme registry used to determine which template to use.
@@ -39,7 +41,7 @@ public function __construct(Registry $theme_registry) {
    * @return string|false
    *   The path to the template, or false if the template is not found.
    *
-   * @throws \Twig_Error_Loader
+   * @throws \Twig\Error\LoaderError
    *   Thrown if a template matching $name cannot be found.
    */
   protected function findTemplate($name, $throw = TRUE) {
@@ -61,7 +63,7 @@ protected function findTemplate($name, $throw = TRUE) {
     }
 
     if ($throw) {
-      throw new \Twig_Error_Loader(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name));
+      throw new LoaderError(sprintf('Unable to find template "%s" in the Drupal theme registry.', $name));
     }
 
     return FALSE;
diff --git a/core/lib/Drupal/Core/Template/TwigEnvironment.php b/core/lib/Drupal/Core/Template/TwigEnvironment.php
index 426234459bdd81a780b18a5fe430b3a73f0d3c05..b59f8a73f78f53fe3abf4b2b25522433906fd0a0 100644
--- a/core/lib/Drupal/Core/Template/TwigEnvironment.php
+++ b/core/lib/Drupal/Core/Template/TwigEnvironment.php
@@ -6,16 +6,17 @@
 use Drupal\Core\PhpStorage\PhpStorageFactory;
 use Drupal\Core\Render\Markup;
 use Drupal\Core\State\StateInterface;
+use Twig\Environment;
+use Twig\Extension\SandboxExtension;
+use Twig\Loader\LoaderInterface;
 
 /**
  * A class that defines a Twig environment for Drupal.
  *
  * Instances of this class are used to store the configuration and extensions,
  * and are used to load templates from the file system or other locations.
- *
- * @see core\vendor\twig\twig\lib\Twig\Environment.php
  */
-class TwigEnvironment extends \Twig_Environment {
+class TwigEnvironment extends Environment {
 
   /**
    * Key name of the Twig cache prefix metadata key-value pair in State.
@@ -55,12 +56,12 @@ class TwigEnvironment extends \Twig_Environment {
    *   The Twig extension hash.
    * @param \Drupal\Core\State\StateInterface $state
    *   The state service.
-   * @param \Twig_LoaderInterface $loader
+   * @param \Twig\Loader\LoaderInterface $loader
    *   The Twig loader or loader chain.
    * @param array $options
    *   The options for the Twig environment.
    */
-  public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, \Twig_LoaderInterface $loader = NULL, array $options = []) {
+  public function __construct($root, CacheBackendInterface $cache, $twig_extension_hash, StateInterface $state, LoaderInterface $loader = NULL, array $options = []) {
     $this->state = $state;
 
     // Ensure that twig.engine is loaded, given that it is needed to render a
@@ -97,7 +98,7 @@ public function __construct($root, CacheBackendInterface $cache, $twig_extension
     $this->setLoader($loader);
     parent::__construct($this->getLoader(), $options);
     $policy = new TwigSandboxPolicy();
-    $sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
+    $sandbox = new SandboxExtension($policy, TRUE);
     $this->addExtension($sandbox);
   }
 
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index db6e080b5f94e2a0feed77ab69619a32fdd5d8b7..2188cffa44458302704b3e078f818d2cb42cab82 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -14,6 +14,14 @@
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\Theme\ThemeManagerInterface;
 use Drupal\Core\Url;
+use Twig\Environment;
+use Twig\Extension\AbstractExtension;
+use Twig\Markup as TwigMarkup;
+use Twig\Node\Expression\ArrayExpression;
+use Twig\Node\Expression\ConstantExpression;
+use Twig\Node\Node;
+use Twig\TwigFilter;
+use Twig\TwigFunction;
 
 /**
  * A class providing Drupal Twig extensions.
@@ -23,7 +31,7 @@
  *
  * @see \Drupal\Core\CoreServiceProvider
  */
-class TwigExtension extends \Twig_Extension {
+class TwigExtension extends AbstractExtension {
 
   /**
    * The URL generator.
@@ -137,19 +145,19 @@ public function setDateFormatter(DateFormatterInterface $date_formatter) {
   public function getFunctions() {
     return [
       // This function will receive a renderable array, if an array is detected.
-      new \Twig_SimpleFunction('render_var', [$this, 'renderVar']),
+      new TwigFunction('render_var', [$this, 'renderVar']),
       // The url and path function are defined in close parallel to those found
       // in \Symfony\Bridge\Twig\Extension\RoutingExtension
-      new \Twig_SimpleFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]),
-      new \Twig_SimpleFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]),
-      new \Twig_SimpleFunction('link', [$this, 'getLink']),
-      new \Twig_SimpleFunction('file_url', function ($uri) {
+      new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]),
+      new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]),
+      new TwigFunction('link', [$this, 'getLink']),
+      new TwigFunction('file_url', function ($uri) {
         return file_url_transform_relative(file_create_url($uri));
       }),
-      new \Twig_SimpleFunction('attach_library', [$this, 'attachLibrary']),
-      new \Twig_SimpleFunction('active_theme_path', [$this, 'getActiveThemePath']),
-      new \Twig_SimpleFunction('active_theme', [$this, 'getActiveTheme']),
-      new \Twig_SimpleFunction('create_attribute', [$this, 'createAttribute']),
+      new TwigFunction('attach_library', [$this, 'attachLibrary']),
+      new TwigFunction('active_theme_path', [$this, 'getActiveThemePath']),
+      new TwigFunction('active_theme', [$this, 'getActiveTheme']),
+      new TwigFunction('create_attribute', [$this, 'createAttribute']),
     ];
   }
 
@@ -159,32 +167,32 @@ public function getFunctions() {
   public function getFilters() {
     return [
       // Translation filters.
-      new \Twig_SimpleFilter('t', 't', ['is_safe' => ['html']]),
-      new \Twig_SimpleFilter('trans', 't', ['is_safe' => ['html']]),
+      new TwigFilter('t', 't', ['is_safe' => ['html']]),
+      new TwigFilter('trans', 't', ['is_safe' => ['html']]),
       // The "raw" filter is not detectable when parsing "trans" tags. To detect
       // which prefix must be used for translation (@, !, %), we must clone the
       // "raw" filter and give it identifiable names. These filters should only
       // be used in "trans" tags.
       // @see TwigNodeTrans::compileString()
-      new \Twig_SimpleFilter('placeholder', [$this, 'escapePlaceholder'], ['is_safe' => ['html'], 'needs_environment' => TRUE]),
+      new TwigFilter('placeholder', [$this, 'escapePlaceholder'], ['is_safe' => ['html'], 'needs_environment' => TRUE]),
 
       // Replace twig's escape filter with our own.
-      new \Twig_SimpleFilter('drupal_escape', [$this, 'escapeFilter'], ['needs_environment' => TRUE, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
+      new TwigFilter('drupal_escape', [$this, 'escapeFilter'], ['needs_environment' => TRUE, 'is_safe_callback' => 'twig_escape_filter_is_safe']),
 
       // Implements safe joining.
       // @todo Make that the default for |join? Upstream issue:
       //   https://github.com/fabpot/Twig/issues/1420
-      new \Twig_SimpleFilter('safe_join', [$this, 'safeJoin'], ['needs_environment' => TRUE, 'is_safe' => ['html']]),
+      new TwigFilter('safe_join', [$this, 'safeJoin'], ['needs_environment' => TRUE, 'is_safe' => ['html']]),
 
       // Array filters.
-      new \Twig_SimpleFilter('without', [$this, 'withoutFilter']),
+      new TwigFilter('without', [$this, 'withoutFilter']),
 
       // CSS class and ID filters.
-      new \Twig_SimpleFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'),
-      new \Twig_SimpleFilter('clean_id', '\Drupal\Component\Utility\Html::getId'),
+      new TwigFilter('clean_class', '\Drupal\Component\Utility\Html::getClass'),
+      new TwigFilter('clean_id', '\Drupal\Component\Utility\Html::getId'),
       // This filter will render a renderable array to use the string results.
-      new \Twig_SimpleFilter('render', [$this, 'renderVar']),
-      new \Twig_SimpleFilter('format_date', [$this->dateFormatter, 'format']),
+      new TwigFilter('render', [$this, 'renderVar']),
+      new TwigFilter('format_date', [$this->dateFormatter, 'format']),
     ];
   }
 
@@ -299,7 +307,7 @@ public function getLink($text, $url, $attributes = []) {
     }
     // The text has been processed by twig already, convert it to a safe object
     // for the render system.
-    if ($text instanceof \Twig_Markup) {
+    if ($text instanceof TwigMarkup) {
       $text = Markup::create($text);
     }
     $build = [
@@ -351,18 +359,18 @@ public function getActiveThemePath() {
    * If param1 and param2 reference placeholders in the route, it would not
    * need to be escaped, but we don't know that in advance.
    *
-   * @param \Twig_Node $args_node
+   * @param \Twig\Node\Node $args_node
    *   The arguments of the path/url functions.
    *
    * @return array
    *   An array with the contexts the URL is safe
    */
-  public function isUrlGenerationSafe(\Twig_Node $args_node) {
+  public function isUrlGenerationSafe(Node $args_node) {
     // Support named arguments.
     $parameter_node = $args_node->hasNode('parameters') ? $args_node->getNode('parameters') : ($args_node->hasNode(1) ? $args_node->getNode(1) : NULL);
 
-    if (!isset($parameter_node) || $parameter_node instanceof \Twig_Node_Expression_Array && count($parameter_node) <= 2 &&
-        (!$parameter_node->hasNode(1) || $parameter_node->getNode(1) instanceof \Twig_Node_Expression_Constant)) {
+    if (!isset($parameter_node) || $parameter_node instanceof ArrayExpression && count($parameter_node) <= 2 &&
+        (!$parameter_node->hasNode(1) || $parameter_node->getNode(1) instanceof ConstantExpression)) {
       return ['html'];
     }
 
@@ -392,15 +400,15 @@ public function attachLibrary($library) {
   /**
    * Provides a placeholder wrapper around ::escapeFilter.
    *
-   * @param \Twig_Environment $env
-   *   A Twig_Environment instance.
+   * @param \Twig\Environment $env
+   *   A Twig Environment instance.
    * @param mixed $string
    *   The value to be escaped.
    *
    * @return string|null
    *   The escaped, rendered output, or NULL if there is no valid output.
    */
-  public function escapePlaceholder(\Twig_Environment $env, $string) {
+  public function escapePlaceholder(Environment $env, $string) {
     $return = $this->escapeFilter($env, $string);
 
     return $return ? '<em class="placeholder">' . $return . '</em>' : NULL;
@@ -414,8 +422,8 @@ public function escapePlaceholder(\Twig_Environment $env, $string) {
    * Note: This function should be kept in sync with
    * theme_render_and_autoescape().
    *
-   * @param \Twig_Environment $env
-   *   A Twig_Environment instance.
+   * @param \Twig\Environment $env
+   *   A Twig Environment instance.
    * @param mixed $arg
    *   The value to be escaped.
    * @param string $strategy
@@ -436,7 +444,7 @@ public function escapePlaceholder(\Twig_Environment $env, $string) {
    * @todo Refactor this to keep it in sync with theme_render_and_autoescape()
    *   in https://www.drupal.org/node/2575065
    */
-  public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $charset = NULL, $autoescape = FALSE) {
+  public function escapeFilter(Environment $env, $arg, $strategy = 'html', $charset = NULL, $autoescape = FALSE) {
     // Check for a numeric zero int or float.
     if ($arg === 0 || $arg === 0.0) {
       return 0;
@@ -449,8 +457,8 @@ public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $
 
     $this->bubbleArgMetadata($arg);
 
-    // Keep Twig_Markup objects intact to support autoescaping.
-    if ($autoescape && ($arg instanceof \Twig_Markup || $arg instanceof MarkupInterface)) {
+    // Keep \Twig\Markup objects intact to support autoescaping.
+    if ($autoescape && ($arg instanceof TwigMarkup || $arg instanceof MarkupInterface)) {
       return $arg;
     }
 
@@ -538,7 +546,7 @@ protected function bubbleArgMetadata($arg) {
    * If an object is passed which does not implement __toString(),
    * RenderableInterface or toString() then an exception is thrown;
    * Other objects are casted to string. However in the case that the
-   * object is an instance of a Twig_Markup object it is returned directly
+   * object is an instance of a \Twig\Markup object it is returned directly
    * to support auto escaping.
    *
    * If an array is passed it is rendered via render() and scalar values are
@@ -552,7 +560,7 @@ protected function bubbleArgMetadata($arg) {
    *   RenderableInterface or toString().
    *
    * @return mixed
-   *   The rendered output or an Twig_Markup object.
+   *   The rendered output or an \Twig\Markup object.
    *
    * @see render
    * @see TwigNodeVisitor
@@ -604,8 +612,8 @@ public function renderVar($arg) {
   /**
    * Joins several strings together safely.
    *
-   * @param \Twig_Environment $env
-   *   A Twig_Environment instance.
+   * @param \Twig\Environment $env
+   *   A Twig Environment instance.
    * @param mixed[]|\Traversable|null $value
    *   The pieces to join.
    * @param string $glue
@@ -616,7 +624,7 @@ public function renderVar($arg) {
    * @return string
    *   The strings joined together.
    */
-  public function safeJoin(\Twig_Environment $env, $value, $glue = '') {
+  public function safeJoin(Environment $env, $value, $glue = '') {
     if ($value instanceof \Traversable) {
       $value = iterator_to_array($value, FALSE);
     }
diff --git a/core/lib/Drupal/Core/Template/TwigNodeTrans.php b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
index b6d6d077d45fc1506e7fc0e6b92fc787e3332035..e581fa9c2bbcaf76ea8aa76d41936c82cd499d7a 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeTrans.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeTrans.php
@@ -2,7 +2,18 @@
 
 namespace Drupal\Core\Template;
 
+use Twig\Compiler;
+use Twig\Error\SyntaxError;
 use Twig\Node\CheckToStringNode;
+use Twig\Node\Expression\AbstractExpression;
+use Twig\Node\Expression\ConstantExpression;
+use Twig\Node\Expression\FilterExpression;
+use Twig\Node\Expression\FunctionExpression;
+use Twig\Node\Expression\GetAttrExpression;
+use Twig\Node\Expression\NameExpression;
+use Twig\Node\Expression\TempNameExpression;
+use Twig\Node\Node;
+use Twig\Node\PrintNode;
 
 /**
  * A class that defines the Twig 'trans' tag for Drupal.
@@ -14,12 +25,12 @@
  * @see https://twig-extensions.readthedocs.io/en/latest/i18n.html
  * @see https://github.com/fabpot/Twig-extensions
  */
-class TwigNodeTrans extends \Twig_Node {
+class TwigNodeTrans extends Node {
 
   /**
    * {@inheritdoc}
    */
-  public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_Node_Expression $count = NULL, \Twig_Node_Expression $options = NULL, $lineno, $tag = NULL) {
+  public function __construct(Node $body, Node $plural = NULL, AbstractExpression $count = NULL, AbstractExpression $options = NULL, $lineno, $tag = NULL) {
     $nodes['body'] = $body;
     if ($count !== NULL) {
       $nodes['count'] = $count;
@@ -36,7 +47,7 @@ public function __construct(\Twig_Node $body, \Twig_Node $plural = NULL, \Twig_N
   /**
    * {@inheritdoc}
    */
-  public function compile(\Twig_Compiler $compiler) {
+  public function compile(Compiler $compiler) {
     $compiler->addDebugInfo($this);
 
     list($singular, $tokens) = $this->compileString($this->getNode('body'));
@@ -88,7 +99,7 @@ public function compile(\Twig_Compiler $compiler) {
   /**
    * Extracts the text and tokens for the "trans" tag.
    *
-   * @param \Twig_Node $body
+   * @param \Twig\Node\Node $body
    *   The node to compile.
    *
    * @return array
@@ -96,10 +107,11 @@ public function compile(\Twig_Compiler $compiler) {
    *   - string $text
    *       The extracted text.
    *   - array $tokens
-   *       The extracted tokens as new \Twig_Node_Expression_Name instances.
+   *       The extracted tokens as new \Twig\Node\Expression\TempNameExpression
+   *       instances.
    */
-  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) {
+  protected function compileString(Node $body) {
+    if ($body instanceof NameExpression || $body instanceof ConstantExpression || $body instanceof TempNameExpression) {
       return [$body, []];
     }
 
@@ -108,13 +120,9 @@ protected function compileString(\Twig_Node $body) {
       $text = '';
 
       foreach ($body as $node) {
-        if (get_class($node) === 'Twig_Node' && $node->getNode(0) instanceof \Twig_Node_SetTemp) {
-          $node = $node->getNode(1);
-        }
-
-        if ($node instanceof \Twig_Node_Print) {
+        if ($node instanceof PrintNode) {
           $n = $node->getNode('expr');
-          while ($n instanceof \Twig_Node_Expression_Filter) {
+          while ($n instanceof FilterExpression) {
             $n = $n->getNode('node');
           }
 
@@ -124,7 +132,7 @@ protected function compileString(\Twig_Node $body) {
           $args = $n;
 
           // Support TwigExtension->renderVar() function in chain.
-          if ($args instanceof \Twig_Node_Expression_Function) {
+          if ($args instanceof FunctionExpression) {
             $args = $n->getNode('arguments')->getNode(0);
           }
 
@@ -134,7 +142,7 @@ protected function compileString(\Twig_Node $body) {
           // safe for templates.
           // @see TwigExtension::getFilters()
           $argPrefix = '@';
-          while ($args instanceof \Twig_Node_Expression_Filter) {
+          while ($args instanceof FilterExpression) {
             switch ($args->getNode('filter')->getAttribute('value')) {
               case 'placeholder':
                 $argPrefix = '%';
@@ -145,7 +153,7 @@ protected function compileString(\Twig_Node $body) {
           if ($args instanceof CheckToStringNode) {
             $args = $args->getNode('expr');
           }
-          if ($args instanceof \Twig_Node_Expression_GetAttr) {
+          if ($args instanceof GetAttrExpression) {
             $argName = [];
             // Reuse the incoming expression.
             $expr = $args;
@@ -153,7 +161,7 @@ protected function compileString(\Twig_Node $body) {
             $argName[] = $args->getNode('attribute')->getAttribute('value');
             while ($args->hasNode('node')) {
               $args = $args->getNode('node');
-              if ($args instanceof \Twig_Node_Expression_Name) {
+              if ($args instanceof NameExpression) {
                 $argName[] = $args->getAttribute('name');
               }
               else {
@@ -168,7 +176,7 @@ protected function compileString(\Twig_Node $body) {
             if (!is_null($args)) {
               $argName = $args->getAttribute('name');
             }
-            $expr = new \Twig_Node_Expression_Name($argName, $n->getTemplateLine());
+            $expr = new NameExpression($argName, $n->getTemplateLine());
           }
           $placeholder = sprintf('%s%s', $argPrefix, $argName);
           $text .= $placeholder;
@@ -181,14 +189,14 @@ protected function compileString(\Twig_Node $body) {
       }
     }
     elseif (!$body->hasAttribute('data')) {
-      throw new \Twig_Error_Syntax('{% trans %} tag cannot be empty');
+      throw new SyntaxError('{% trans %} tag cannot be empty');
     }
     else {
       $text = $body->getAttribute('data');
     }
 
     return [
-      new \Twig_Node([new \Twig_Node_Expression_Constant(trim($text), $body->getTemplateLine())]),
+      new Node([new ConstantExpression(trim($text), $body->getTemplateLine())]),
       $tokens,
     ];
   }
diff --git a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
index 5286242281a5c94b047163a4e1f96f163acd04bc..0429b6a31d4df79158af3acae9120f0275137fcf 100644
--- a/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
+++ b/core/lib/Drupal/Core/Template/TwigNodeVisitor.php
@@ -2,8 +2,15 @@
 
 namespace Drupal\Core\Template;
 
+use Twig\Environment;
+use Twig\Node\Expression\FilterExpression;
+use Twig\Node\Expression\FunctionExpression;
+use Twig\Node\Node;
+use Twig\Node\PrintNode;
+use Twig\NodeVisitor\AbstractNodeVisitor;
+
 /**
- * Provides a Twig_NodeVisitor to change the generated parse-tree.
+ * Provides a TwigNodeVisitor to change the generated parse-tree.
  *
  * This is used to ensure that everything printed is wrapped via the
  * TwigExtension->renderVar() function in order to just write {{ content }}
@@ -11,22 +18,22 @@
  *
  * @see twig_render
  */
-class TwigNodeVisitor extends \Twig_BaseNodeVisitor {
+class TwigNodeVisitor extends AbstractNodeVisitor {
 
   /**
    * {@inheritdoc}
    */
-  protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) {
+  protected function doEnterNode(Node $node, Environment $env) {
     return $node;
   }
 
   /**
    * {@inheritdoc}
    */
-  protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) {
+  protected function doLeaveNode(Node $node, Environment $env) {
     // We use this to inject a call to render_var -> TwigExtension->renderVar()
     // before anything is printed.
-    if ($node instanceof \Twig_Node_Print) {
+    if ($node instanceof PrintNode) {
       if (!empty($this->skipRenderVarFunction)) {
         // No need to add the callback, we have escape active already.
         unset($this->skipRenderVarFunction);
@@ -35,12 +42,12 @@ protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) {
       $class = get_class($node);
       $line = $node->getTemplateLine();
       return new $class(
-        new \Twig_Node_Expression_Function('render_var', new \Twig_Node([$node->getNode('expr')]), $line),
+        new FunctionExpression('render_var', new Node([$node->getNode('expr')]), $line),
         $line
       );
     }
     // Change the 'escape' filter to our own 'drupal_escape' filter.
-    elseif ($node instanceof \Twig_Node_Expression_Filter) {
+    elseif ($node instanceof FilterExpression) {
       $name = $node->getNode('filter')->getAttribute('value');
       if ('escape' == $name || 'e' == $name) {
         // Use our own escape filter that is MarkupInterface aware.
diff --git a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php
index 995ce9780306fd2e9c91f48597d9356640be49f1..fcffa1cd1358cdade311d348d4493053f20b67bb 100644
--- a/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php
+++ b/core/lib/Drupal/Core/Template/TwigPhpStorageCache.php
@@ -5,6 +5,7 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\PhpStorage\PhpStorageFactory;
+use Twig\Cache\CacheInterface;
 
 /**
  * Provides an alternate cache storage for Twig using PhpStorage.
@@ -16,7 +17,7 @@
  *
  * @see \Drupal\Core\DependencyInjection\Compiler\TwigExtensionPass
  */
-class TwigPhpStorageCache implements \Twig_CacheInterface {
+class TwigPhpStorageCache implements CacheInterface {
 
   /**
    * The maximum length for each part of the cache key suffix.
diff --git a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
index 4adc9d60d30aeaa9046acf9220cb560e6d9d076e..ab8dc33feb9817c3986cad9c9a2e4490eed72a82 100644
--- a/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
+++ b/core/lib/Drupal/Core/Template/TwigSandboxPolicy.php
@@ -3,6 +3,8 @@
 namespace Drupal\Core\Template;
 
 use Drupal\Core\Site\Settings;
+use Twig\Sandbox\SecurityError;
+use Twig\Sandbox\SecurityPolicyInterface;
 
 /**
  * Default sandbox policy for Twig templates.
@@ -13,7 +15,7 @@
  * objects can do by whitelisting certain classes, method names, and method
  * names with an allowed prefix. All object properties may be accessed.
  */
-class TwigSandboxPolicy implements \Twig_Sandbox_SecurityPolicyInterface {
+class TwigSandboxPolicy implements SecurityPolicyInterface {
 
   /**
    * An array of whitelisted methods in the form of methodName => TRUE.
@@ -102,7 +104,7 @@ public function checkMethodAllowed($obj, $method) {
       }
     }
 
-    throw new \Twig_Sandbox_SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj)));
+    throw new SecurityError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, get_class($obj)));
   }
 
 }
diff --git a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php
index 07580e90d782631d0d834297cfb11f3c199c04e5..93e4fdcfe3f213b682386e542fd983a4d6d52c22 100644
--- a/core/lib/Drupal/Core/Template/TwigTransTokenParser.php
+++ b/core/lib/Drupal/Core/Template/TwigTransTokenParser.php
@@ -2,6 +2,16 @@
 
 namespace Drupal\Core\Template;
 
+use Twig\Error\SyntaxError;
+use Twig\Node\Expression\FilterExpression;
+use Twig\Node\Expression\GetAttrExpression;
+use Twig\Node\Expression\NameExpression;
+use Twig\Node\Node;
+use Twig\Node\PrintNode;
+use Twig\Node\TextNode;
+use Twig\Token;
+use Twig\TokenParser\AbstractTokenParser;
+
 /**
  * A class that defines the Twig 'trans' token parser for Drupal.
  *
@@ -9,16 +19,15 @@
  * code into an Abstract Syntax Tree (AST).  The AST will later be compiled
  * into PHP code usable for runtime execution of the template.
  *
- * @see \Twig_TokenParser
  * @see https://twig-extensions.readthedocs.io/en/latest/i18n.html
  * @see https://github.com/fabpot/Twig-extensions
  */
-class TwigTransTokenParser extends \Twig_TokenParser {
+class TwigTransTokenParser extends AbstractTokenParser {
 
   /**
    * {@inheritdoc}
    */
-  public function parse(\Twig_Token $token) {
+  public function parse(Token $token) {
     $lineno = $token->getLine();
     $stream = $this->parser->getStream();
     $body = NULL;
@@ -26,24 +35,24 @@ public function parse(\Twig_Token $token) {
     $count = NULL;
     $plural = NULL;
 
-    if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::STRING_TYPE)) {
+    if (!$stream->test(Token::BLOCK_END_TYPE) && $stream->test(Token::STRING_TYPE)) {
       $body = $this->parser->getExpressionParser()->parseExpression();
     }
-    if (!$stream->test(\Twig_Token::BLOCK_END_TYPE) && $stream->test(\Twig_Token::NAME_TYPE, 'with')) {
+    if (!$stream->test(Token::BLOCK_END_TYPE) && $stream->test(Token::NAME_TYPE, 'with')) {
       $stream->next();
       $options = $this->parser->getExpressionParser()->parseExpression();
     }
     if (!$body) {
-      $stream->expect(\Twig_Token::BLOCK_END_TYPE);
+      $stream->expect(Token::BLOCK_END_TYPE);
       $body = $this->parser->subparse([$this, 'decideForFork']);
       if ('plural' === $stream->next()->getValue()) {
         $count = $this->parser->getExpressionParser()->parseExpression();
-        $stream->expect(\Twig_Token::BLOCK_END_TYPE);
+        $stream->expect(Token::BLOCK_END_TYPE);
         $plural = $this->parser->subparse([$this, 'decideForEnd'], TRUE);
       }
     }
 
-    $stream->expect(\Twig_Token::BLOCK_END_TYPE);
+    $stream->expect(Token::BLOCK_END_TYPE);
 
     $this->checkTransString($body, $lineno);
 
@@ -76,27 +85,27 @@ public function getTag() {
   /**
    * Ensure that any nodes that are parsed are only of allowed types.
    *
-   * @param \Twig_Node $body
+   * @param \Twig\Node\Node $body
    *   The expression to check.
    * @param int $lineno
    *   The source line.
    *
-   * @throws \Twig_Error_Syntax
+   * @throws \Twig\Error\SyntaxError
    */
-  protected function checkTransString(\Twig_Node $body, $lineno) {
+  protected function checkTransString(Node $body, $lineno) {
     foreach ($body as $node) {
       if (
-        $node instanceof \Twig_Node_Text
+        $node instanceof TextNode
         ||
-        ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_Name)
+        ($node instanceof PrintNode && $node->getNode('expr') instanceof NameExpression)
         ||
-        ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_GetAttr)
+        ($node instanceof PrintNode && $node->getNode('expr') instanceof GetAttrExpression)
         ||
-        ($node instanceof \Twig_Node_Print && $node->getNode('expr') instanceof \Twig_Node_Expression_Filter)
+        ($node instanceof PrintNode && $node->getNode('expr') instanceof FilterExpression)
       ) {
         continue;
       }
-      throw new \Twig_Error_Syntax(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno);
+      throw new SyntaxError(sprintf('The text to be translated with "trans" can only contain references to simple variables'), $lineno);
     }
   }
 
diff --git a/core/modules/block_content/templates/block-content-add-list.html.twig b/core/modules/block_content/templates/block-content-add-list.html.twig
index 08104617c68b0a34a4316890838f30a35ba8d8d7..f04d5e58bab377125c4c48bcadb33806cc457577 100644
--- a/core/modules/block_content/templates/block-content-add-list.html.twig
+++ b/core/modules/block_content/templates/block-content-add-list.html.twig
@@ -14,11 +14,11 @@
  * @ingroup themeable
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <dl>
     {% for type in types %}
       <dt>{{ type.link }}</dt>
       <dd>{{ type.description }}</dd>
     {% endfor %}
   </dl>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/modules/book/templates/book-export-html.html.twig b/core/modules/book/templates/book-export-html.html.twig
index 5fb2e971a53a545c95df7b417f5d0f74ea8004d4..025762ca12fb919793fa379c14f6c77ab904b8bb 100644
--- a/core/modules/book/templates/book-export-html.html.twig
+++ b/core/modules/book/templates/book-export-html.html.twig
@@ -36,12 +36,12 @@
       to be exported as printer-friendly HTML.
     #}
 
-  {% for i in 1..depth-1 if depth > 1 %}
+  {% if depth > 1 %}{% for i in 1..depth-1 %}
     <div>
-  {% endfor %}
+  {% endfor %}{% endif %}
   {{ contents }}
-  {% for i in 1..depth-1 if depth > 1 %}
+      {% if depth > 1 %}{% for i in 1..depth-1 %}
     </div>
-  {% endfor %}
+  {% endfor %}{% endif %}
   </body>
 </html>
diff --git a/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig b/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig
index bc8e836493bbad31b37bbd8e09569bfc02e8c5c9..3636bf06c543d4170831e44b6e79054d8304c992 100644
--- a/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig
+++ b/core/modules/ckeditor/templates/ckeditor-settings-toolbar.html.twig
@@ -13,7 +13,7 @@
  * @ingroup themeable
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <fieldset role="form" aria-labelledby="ckeditor-button-configuration ckeditor-button-description">
     <legend id="ckeditor-button-configuration">{{ 'Toolbar configuration'|t }}</legend>
     <div class="fieldset-wrapper">
@@ -72,4 +72,4 @@
       </div>
     </div>
   </fieldset>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/modules/forum/templates/forum-list.html.twig b/core/modules/forum/templates/forum-list.html.twig
index c2e55675c7f9863a9a4c9c53a897d624d3cdebda..6bf4220b827a364d62aeddd3e8419776ce7b0703 100644
--- a/core/modules/forum/templates/forum-list.html.twig
+++ b/core/modules/forum/templates/forum-list.html.twig
@@ -50,7 +50,7 @@
           depth this forum resides at. This will allow us to use CSS
           left-margin for indenting.
         #}
-        {% for i in 1..forum.depth if forum.depth > 0 %}<div class="indent">{% endfor %}
+        {% if forum.depth > 0 %}{% for i in 1..forum.depth %}<div class="indent">{% endfor %}{% endif %}
           <div title="{{ forum.icon_title }}">
             <span class="visually-hidden">{{ forum.icon_title }}</span>
           </div>
@@ -58,7 +58,7 @@
           {% if forum.description.value %}
             <div>{{ forum.description.value }}</div>
           {% endif %}
-        {% for i in 1..forum.depth if forum.depth > 0 %}</div>{% endfor %}
+        {% if forum.depth > 0 %}{% for i in 1..forum.depth %}</div>{% endfor %}{% endif %}
       </td>
       {% if forum.is_container == false %}
         <td>
diff --git a/core/modules/help_topics/src/HelpTopicTwigLoader.php b/core/modules/help_topics/src/HelpTopicTwigLoader.php
index b785736f1968a665c8de518c01fbdf69b1f05c82..27260983d073798fde3bdc0aa4daf6d1e9f305ab 100644
--- a/core/modules/help_topics/src/HelpTopicTwigLoader.php
+++ b/core/modules/help_topics/src/HelpTopicTwigLoader.php
@@ -7,6 +7,7 @@
 use Drupal\Core\Extension\ThemeHandlerInterface;
 use Drupal\Core\Serialization\Yaml;
 use Twig\Error\LoaderError;
+use Twig\Loader\FilesystemLoader;
 use Twig\Source;
 
 /**
@@ -24,7 +25,7 @@
  *   experimental modules and development releases of contributed modules.
  *   See https://www.drupal.org/core/experimental for more information.
  */
-class HelpTopicTwigLoader extends \Twig_Loader_Filesystem {
+class HelpTopicTwigLoader extends FilesystemLoader {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php b/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php
index 201b73b70fd35e76c87f6787088df8ea15ebc31d..1682e0cbe0a8571247a8500d0db0fbac58f68979 100644
--- a/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php
+++ b/core/modules/help_topics/tests/src/Unit/HelpTopicTwigTest.php
@@ -104,7 +104,7 @@ protected function getTwigMock() {
 }
 
 /**
- * Defines a fake template class to mock \Twig_TemplateWrapper.
+ * Defines a fake template class to mock \Twig\TemplateWrapper.
  *
  * We cannot use getMockBuilder() for this, because the Twig TemplateWrapper
  * class is declared "final" and cannot be mocked.
@@ -129,7 +129,7 @@ public function __construct($body) {
   }
 
   /**
-   * Mocks the \Twig_TemplateWrapper render() method.
+   * Mocks the \Twig\TemplateWrapper render() method.
    *
    * @param array $context
    *   (optional) Render context.
diff --git a/core/modules/link/templates/link-formatter-link-separate.html.twig b/core/modules/link/templates/link-formatter-link-separate.html.twig
index 469cd9aef827a9c56d6354ea0fee0535c8932de8..932aae8ba91b95b133efdd51a0e1b5eff2dcddd0 100644
--- a/core/modules/link/templates/link-formatter-link-separate.html.twig
+++ b/core/modules/link/templates/link-formatter-link-separate.html.twig
@@ -14,7 +14,7 @@
  * @ingroup themeable
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   {{ title }}
   {{ link }}
-{% endspaceless %}
+{% endapply %}
diff --git a/core/modules/system/templates/dropbutton-wrapper.html.twig b/core/modules/system/templates/dropbutton-wrapper.html.twig
index 5f1aadf97ffa37850a997b5d6948c3b23a6c17cd..62d2ef200d444d0067f07f81ae333d14d94fac39 100644
--- a/core/modules/system/templates/dropbutton-wrapper.html.twig
+++ b/core/modules/system/templates/dropbutton-wrapper.html.twig
@@ -12,11 +12,11 @@
  */
 #}
 {% if children %}
-  {% spaceless %}
+  {% apply spaceless %}
     <div class="dropbutton-wrapper">
       <div class="dropbutton-widget">
         {{ children }}
       </div>
     </div>
-  {% endspaceless %}
+  {% endapply %}
 {% endif %}
diff --git a/core/modules/system/templates/indentation.html.twig b/core/modules/system/templates/indentation.html.twig
index c7067fbe0843dfcaa5c9516836e6d5614e1dab09..3cb4fa4f3cf818340354c74a43ee7c6a39ea61c8 100644
--- a/core/modules/system/templates/indentation.html.twig
+++ b/core/modules/system/templates/indentation.html.twig
@@ -11,4 +11,4 @@
  * @ingroup themeable
  */
 #}
-{% for i in 1..size if size > 0 %}<div class="js-indentation indentation">&nbsp;</div>{% endfor %}
+{% if size > 0 %}{% for i in 1..size %}<div class="js-indentation indentation">&nbsp;</div>{% endfor %}{% endif %}
diff --git a/core/modules/system/templates/select.html.twig b/core/modules/system/templates/select.html.twig
index 0b5c3d22c58dfeeacd0d1c150878ab9a02dc23e6..a86ed97f98e5a65313eb208f74e37821f60da1f7 100644
--- a/core/modules/system/templates/select.html.twig
+++ b/core/modules/system/templates/select.html.twig
@@ -12,7 +12,7 @@
  * @ingroup themeable
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <select{{ attributes }}>
     {% for option in options %}
       {% if option.type == 'optgroup' %}
@@ -26,4 +26,4 @@
       {% endif %}
     {% endfor %}
   </select>
-{% endspaceless %}
+{% endapply %}
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 2f51e721a6ff22220aef771adec7249fbe3f69f4..753c90f2f4b5cf6761c2b17ba16b1d7547cb24d5 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
@@ -2,13 +2,14 @@
 
 namespace Drupal\twig_extension_test\TwigExtension;
 
+use Twig\Extension\AbstractExtension;
 use Twig\TwigFilter;
 use Twig\TwigFunction;
 
 /**
  * A test Twig extension that adds a custom function and a custom filter.
  */
-class TestExtension extends \Twig_Extension {
+class TestExtension extends AbstractExtension {
 
   /**
    * Generates a list of all Twig functions that this extension defines.
diff --git a/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php b/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php
index e9a05b0ad2f2fa3bea8130adf9f0792f643f0e02..250950539f9209280261727ff4cc6d82ad222338 100644
--- a/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php
+++ b/core/modules/system/tests/modules/twig_loader_test/src/Loader/TestLoader.php
@@ -2,12 +2,15 @@
 
 namespace Drupal\twig_loader_test\Loader;
 
+use Twig\Loader\ExistsLoaderInterface;
+use Twig\Loader\LoaderInterface;
+use Twig\Loader\SourceContextLoaderInterface;
 use Twig\Source;
 
 /**
  * A test Twig loader.
  */
-class TestLoader implements \Twig_LoaderInterface, \Twig_ExistsLoaderInterface, \Twig_SourceContextLoaderInterface {
+class TestLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php b/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php
index c664c5dd73409a964059fe59140cc38cc814a8b0..75596f7ade96f8bc9edeeabeddbdc6a82fd8e010 100644
--- a/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php
+++ b/core/modules/system/tests/src/Functional/Theme/TwigTransTest.php
@@ -4,6 +4,7 @@
 
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Tests\BrowserTestBase;
+use Twig\Error\SyntaxError;
 
 /**
  * Tests Twig "trans" tags.
@@ -107,7 +108,7 @@ public function testEmptyTwigTransTags() {
 
       $this->fail('{% trans %}{% endtrans %} did not throw an exception.');
     }
-    catch (\Twig_Error_Syntax $e) {
+    catch (SyntaxError $e) {
       $this->assertTrue(strstr($e->getMessage(), '{% trans %} tag cannot be empty'), '{% trans %}{% endtrans %} threw the expected exception.');
     }
     catch (\Exception $e) {
diff --git a/core/modules/toolbar/templates/toolbar.html.twig b/core/modules/toolbar/templates/toolbar.html.twig
index cb82774b8603014b08a8884053082b9558a9acc7..64e29eabfa578208f0f4782d22f4bc99cb560cc3 100644
--- a/core/modules/toolbar/templates/toolbar.html.twig
+++ b/core/modules/toolbar/templates/toolbar.html.twig
@@ -29,7 +29,7 @@
       {% set tray = trays[key] %}
       <div{{ tab.attributes.addClass('toolbar-tab') }}>
         {{ tab.link }}
-        {% spaceless %}
+        {% apply spaceless %}
           <div{{ tray.attributes }}>
             {% if tray.label %}
               <nav class="toolbar-lining clearfix" role="navigation" aria-label="{{ tray.label }}">
@@ -40,7 +40,7 @@
             {{ tray.links }}
             </nav>
           </div>
-        {% endspaceless %}
+        {% endapply %}
       </div>
     {% endfor %}
   </nav>
diff --git a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
index 8030f8860a4ef1c32c6dce4ef06ed5618d5ef341..14539d7565b135fe6e21e8acb87d54040dea69d9 100644
--- a/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
+++ b/core/modules/views/src/Plugin/views/field/FieldPluginBase.php
@@ -13,6 +13,7 @@
 use Drupal\views\Render\ViewsRenderPipelineMarkup;
 use Drupal\views\ResultRow;
 use Drupal\views\ViewExecutable;
+use Twig\Environment;
 
 /**
  * @defgroup views_field_handlers Views field handler plugins
@@ -726,7 +727,7 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
         '#default_value' => $this->options['alter']['text'],
         // The tag list will be escaped.
         '#description' => $this->t('The text to display for this field. You may enter data from this view as per the "Replacement patterns" below. You may include <a href="@twig_docs">Twig</a> or the following allowed HTML tags: <code>@tags</code>', [
-          '@twig_docs' => 'https://twig.symfony.com/doc/' . \Twig_Environment::MAJOR_VERSION . '.x',
+          '@twig_docs' => 'https://twig.symfony.com/doc/' . Environment::MAJOR_VERSION . '.x',
           '@tags' => '<' . implode('> <', Xss::getAdminTagList()) . '>',
         ]),
         '#states' => [
diff --git a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php
index bbc1253a3f25e761a0f7094faffb65038cf77ecc..65f80c4054ad35494a406f57ce3fbfad1a5ebc9c 100644
--- a/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php
+++ b/core/tests/Drupal/KernelTests/Core/Theme/TwigEnvironmentTest.php
@@ -9,6 +9,8 @@
 use Drupal\Core\Template\TwigPhpStorageCache;
 use Drupal\KernelTests\KernelTestBase;
 use Symfony\Component\DependencyInjection\Definition;
+use Twig\Environment;
+use Twig\Error\LoaderError;
 
 /**
  * Tests the twig environment.
@@ -106,7 +108,7 @@ public function testTemplateNotFoundException() {
       $environment->loadTemplate('this-template-does-not-exist.html.twig')->render([]);
       $this->fail('Did not throw an exception as expected.');
     }
-    catch (\Twig_Error_Loader $e) {
+    catch (LoaderError $e) {
       $this->assertTrue(strpos($e->getMessage(), 'Template "this-template-does-not-exist.html.twig" is not defined') === 0);
     }
   }
@@ -184,7 +186,7 @@ public function testCacheFilename() {
   public function register(ContainerBuilder $container) {
     parent::register($container);
 
-    $container->setDefinition('twig_loader__file_system', new Definition('Twig_Loader_Filesystem', [[sys_get_temp_dir()]]))
+    $container->setDefinition('twig_loader__file_system', new Definition('Twig\Loader\FilesystemLoader', [[sys_get_temp_dir()]]))
       ->addTag('twig.loader');
   }
 
@@ -216,7 +218,7 @@ public function testTemplateInvalidation() {
     // Manually change $templateClassPrefix to force a different template
     // classname, as the other class is still loaded. This wouldn't be a problem
     // on a real site where you reload the page.
-    $reflection = new \ReflectionClass(\Twig_Environment::class);
+    $reflection = new \ReflectionClass(Environment::class);
     $property_reflection = $reflection->getProperty('templateClassPrefix');
     $property_reflection->setAccessible(TRUE);
     $property_reflection->setValue($environment, 'otherPrefix');
diff --git a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
index 911b6e150d0a6b9366b763569740cacaf278cc7a..5dd35aeb55ee5ce1cf578ff1407c53422c1e327e 100644
--- a/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/AttributeTest.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Template\Loader\StringLoader;
 use Drupal\Tests\UnitTestCase;
 use Drupal\Component\Render\MarkupInterface;
+use Twig\Environment;
 
 /**
  * @coversDefaultClass \Drupal\Core\Template\Attribute
@@ -265,7 +266,7 @@ public function testChainAddRemoveClasses() {
    */
   public function testTwigAddRemoveClasses($template, $expected, $seed_attributes = []) {
     $loader = new StringLoader();
-    $twig = new \Twig_Environment($loader);
+    $twig = new Environment($loader);
     $data = ['attributes' => new Attribute($seed_attributes)];
     $result = $twig->createTemplate($template)->render($data);
     $this->assertEquals($expected, $result);
diff --git a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php
index 87d5397b31ef5d734774fa2510e18937d48bd132..a463601cf4894b78261a114cb373d4822cbe17aa 100644
--- a/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/TwigExtensionTest.php
@@ -10,6 +10,11 @@
 use Drupal\Core\Template\TwigExtension;
 use Drupal\Core\Url;
 use Drupal\Tests\UnitTestCase;
+use Twig\Environment;
+use Twig\Loader\ArrayLoader;
+use Twig\Loader\FilesystemLoader;
+use Twig\Node\Expression\FilterExpression;
+use Twig\Source;
 
 /**
  * Tests the twig extension.
@@ -75,8 +80,8 @@ public function setUp() {
    * @dataProvider providerTestEscaping
    */
   public function testEscaping($template, $expected) {
-    $loader = new \Twig_Loader_Filesystem();
-    $twig = new \Twig_Environment($loader, [
+    $loader = new FilesystemLoader();
+    $twig = new Environment($loader, [
       'debug' => TRUE,
       'cache' => FALSE,
       'autoescape' => 'html',
@@ -85,11 +90,11 @@ public function testEscaping($template, $expected) {
     $twig->addExtension($this->systemUnderTest);
 
     $name = '__string_template_test__';
-    $nodes = $twig->parse($twig->tokenize(new \Twig_Source($template, $name)));
+    $nodes = $twig->parse($twig->tokenize(new Source($template, $name)));
 
     $this->assertSame($expected, $nodes->getNode('body')
       ->getNode(0)
-      ->getNode('expr') instanceof \Twig_Node_Expression_Filter);
+      ->getNode('expr') instanceof FilterExpression);
   }
 
   /**
@@ -138,7 +143,7 @@ public function testActiveTheme() {
       ->willReturn($active_theme);
 
     $loader = new StringLoader();
-    $twig = new \Twig_Environment($loader);
+    $twig = new Environment($loader);
     $twig->addExtension($this->systemUnderTest);
     $result = $twig->render('{{ active_theme() }}');
     $this->assertEquals('test_theme', $result);
@@ -155,7 +160,7 @@ public function testFormatDate() {
       }));
 
     $loader = new StringLoader();
-    $twig = new \Twig_Environment($loader);
+    $twig = new Environment($loader);
     $twig->addExtension($this->systemUnderTest);
     $timestamp = strtotime('1978-11-19');
     $result = $twig->render('{{ time|format_date("html_date") }}', ['time' => $timestamp]);
@@ -178,7 +183,7 @@ public function testActiveThemePath() {
       ->willReturn($active_theme);
 
     $loader = new StringLoader();
-    $twig = new \Twig_Environment($loader);
+    $twig = new Environment($loader);
     $twig->addExtension($this->systemUnderTest);
     $result = $twig->render('{{ active_theme_path() }}');
     $this->assertEquals('foo/bar', $result);
@@ -190,8 +195,8 @@ public function testActiveThemePath() {
    * @covers ::escapeFilter
    */
   public function testSafeStringEscaping() {
-    $loader = new \Twig_Loader_Filesystem();
-    $twig = new \Twig_Environment($loader, [
+    $loader = new FilesystemLoader();
+    $twig = new Environment($loader, [
       'debug' => TRUE,
       'cache' => FALSE,
       'autoescape' => 'html',
@@ -275,8 +280,8 @@ public function providerTestRenderVar() {
    * @covers ::bubbleArgMetadata
    */
   public function testEscapeWithGeneratedLink() {
-    $loader = new \Twig_Loader_Filesystem();
-    $twig = new \Twig_Environment($loader, [
+    $loader = new FilesystemLoader();
+    $twig = new Environment($loader, [
         'debug' => TRUE,
         'cache' => FALSE,
         'autoescape' => 'html',
@@ -335,8 +340,8 @@ public function testRenderVarWithGeneratedLink() {
    */
   public function testCreateAttribute() {
     $name = '__string_template_test_1__';
-    $loader = new \Twig_Loader_Array([$name => "{% for iteration in iterations %}<div{{ create_attribute(iteration) }}></div>{% endfor %}"]);
-    $twig = new \Twig_Environment($loader);
+    $loader = new ArrayLoader([$name => "{% for iteration in iterations %}<div{{ create_attribute(iteration) }}></div>{% endfor %}"]);
+    $twig = new Environment($loader);
     $twig->addExtension($this->systemUnderTest);
 
     $iterations = [
@@ -350,7 +355,7 @@ public function testCreateAttribute() {
 
     // Test default creation of empty attribute object and using its method.
     $name = '__string_template_test_2__';
-    $loader = new \Twig_Loader_Array([$name => "<div{{ create_attribute().addClass('meow') }}></div>"]);
+    $loader = new ArrayLoader([$name => "<div{{ create_attribute().addClass('meow') }}></div>"]);
     $twig->setLoader($loader);
     $result = $twig->render($name);
     $expected = '<div class="meow"></div>';
diff --git a/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php b/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
index 019acbe1dcad7398cc69839e29ebb24e2572c865..e1bbd3d330bbc719c92d3032d0f43ebfdb0e67d8 100644
--- a/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
+++ b/core/tests/Drupal/Tests/Core/Template/TwigSandboxTest.php
@@ -11,6 +11,9 @@
 use Drupal\Core\Template\TwigSandboxPolicy;
 use Drupal\Core\Template\Loader\StringLoader;
 use Drupal\Tests\UnitTestCase;
+use Twig\Environment;
+use Twig\Extension\SandboxExtension;
+use Twig\Sandbox\SecurityError;
 
 /**
  * Tests the twig sandbox policy.
@@ -24,7 +27,7 @@ class TwigSandboxTest extends UnitTestCase {
   /**
    * The Twig environment loaded with the sandbox extension.
    *
-   * @var \Twig_Environment
+   * @var \Twig\Environment
    */
   protected $twig;
 
@@ -35,9 +38,9 @@ protected function setUp() {
     parent::setUp();
 
     $loader = new StringLoader();
-    $this->twig = new \Twig_Environment($loader);
+    $this->twig = new Environment($loader);
     $policy = new TwigSandboxPolicy();
-    $sandbox = new \Twig_Extension_Sandbox($policy, TRUE);
+    $sandbox = new SandboxExtension($policy, TRUE);
     $this->twig->addExtension($sandbox);
   }
 
@@ -48,7 +51,7 @@ protected function setUp() {
    */
   public function testEntityDangerousMethods($template) {
     $entity = $this->createMock('Drupal\Core\Entity\EntityInterface');
-    $this->expectException(\Twig_Sandbox_SecurityError::class);
+    $this->expectException(SecurityError::class);
     $this->twig->render($template, ['entity' => $entity]);
   }
 
diff --git a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
index 46493f2979fd3db877d98c8f82b553afcf202b0f..7d66a6ae622bd9ccd1205dd47a725efd3974a380 100644
--- a/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
+++ b/core/tests/Drupal/Tests/Listeners/DeprecationListenerTrait.php
@@ -193,6 +193,9 @@ public static function getSkippedDeprecations() {
       'The "core/matchmedia" asset library is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. See https://www.drupal.org/node/3086653',
       'The "core/matchmedia.addListener" asset library is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. See https://www.drupal.org/node/3086653',
       'The "core/classList" asset library is deprecated in drupal:8.8.0 and is removed from drupal:9.0.0. Use the the native browser implementation instead. See https://www.drupal.org/node/3089511',
+      // The following deprecation is listed for Twig 2 compatibility when unit
+      // testing using \Symfony\Component\ErrorHandler\DebugClassLoader.
+      'The "Twig\Environment::getTemplateClass()" method is considered internal. It may change without further notice. You should not extend it from "Drupal\Core\Template\TwigEnvironment".',
     ];
   }
 
diff --git a/core/themes/claro/templates/admin/indentation.html.twig b/core/themes/claro/templates/admin/indentation.html.twig
index 7618abab8a3e574b2b59356aa3719e8a4450e7c5..9b22d3b51d7c0952299015cd4048d4a585f3d7a4 100644
--- a/core/themes/claro/templates/admin/indentation.html.twig
+++ b/core/themes/claro/templates/admin/indentation.html.twig
@@ -9,7 +9,7 @@
  * - size: Optional. The number of indentations to create.
  */
 #}
-{% for i in 1..size if size > 0 %}<div class="js-indentation indentation">
+{% if size > 0 %}{% for i in 1..size %}<div class="js-indentation indentation">
   <svg
     xmlns="http://www.w3.org/2000/svg"
     class="tree"
@@ -33,4 +33,4 @@
       d="M12.5,12 v99"
       stroke="#888"/>
   </svg>
-</div>{% endfor %}
+</div>{% endfor %}{% endif %}
diff --git a/core/themes/claro/templates/form/input.html.twig b/core/themes/claro/templates/form/input.html.twig
index f8a6cab610f9e4f066105e93a8cc08dd526322ea..12697039f4e45f5340d95fb11a9728eb406785a0 100644
--- a/core/themes/claro/templates/form/input.html.twig
+++ b/core/themes/claro/templates/form/input.html.twig
@@ -11,7 +11,7 @@
  * @see claro_preprocess_input()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
 {% if autocomplete_message %}
   <div class="claro-autocomplete">
     <input{{ attributes }}/>
@@ -21,4 +21,4 @@
 {% else %}
   <input{{ attributes }}/>{{ children }}
 {% endif %}
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/claro/templates/pager.html.twig b/core/themes/claro/templates/pager.html.twig
index e59cdb36007302ad39d7695738882ca59688ede6..e91a3ff031a1d81d72671471cc2fe211d4c1efaf 100644
--- a/core/themes/claro/templates/pager.html.twig
+++ b/core/themes/claro/templates/pager.html.twig
@@ -40,7 +40,7 @@
     <ul class="pager__items js-pager__items">
       {# Print first item if we are not on the first page. #}
       {% if items.first %}
-        {% spaceless %}
+        {% apply spaceless %}
         <li class="pager__item pager__item--action pager__item--first">
           <a href="{{ items.first.href }}" class="pager__link pager__link--action-link" title="{{ 'Go to first page'|t }}"{{ items.first.attributes|without('href', 'title') }}>
             <span class="visually-hidden">{{ 'First page'|t }}</span>
@@ -49,12 +49,12 @@
             </span>
           </a>
         </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endif %}
 
       {# Print previous item if we are not on the first page. #}
       {% if items.previous %}
-        {% spaceless %}
+        {% apply spaceless %}
         <li class="pager__item pager__item--action pager__item--previous">
           <a href="{{ items.previous.href }}" class="pager__link pager__link--action-link" title="{{ 'Go to previous page'|t }}" rel="prev"{{ items.previous.attributes|without('href', 'title', 'rel') }}>
             <span class="visually-hidden">{{ 'Previous page'|t }}</span>
@@ -63,7 +63,7 @@
             </span>
           </a>
         </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endif %}
 
       {# Add an ellipsis if there are further previous pages. #}
@@ -73,7 +73,7 @@
 
       {# Now generate the actual pager piece. #}
       {% for key, item in items.pages %}
-        {% spaceless %}
+        {% apply spaceless %}
         <li class="pager__item{{ current == key ? ' pager__item--active' : '' }} pager__item--number">
           {% if current == key %}
             {% set title = 'Current page'|t %}
@@ -87,7 +87,7 @@
             {{ key }}
           </a>
         </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endfor %}
 
       {# Add an ellipsis if there are further next pages. #}
@@ -97,7 +97,7 @@
 
       {# Print next item if we are not on the last page. #}
       {% if items.next %}
-        {% spaceless %}
+        {% apply spaceless %}
         <li class="pager__item pager__item--action pager__item--next">
           <a href="{{ items.next.href }}" class="pager__link pager__link--action-link" title="{{ 'Go to next page'|t }}" rel="next"{{ items.next.attributes|without('href', 'title', 'rel') }}>
             <span class="visually-hidden">{{ 'Next page'|t }}</span>
@@ -106,12 +106,12 @@
             </span>
           </a>
         </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endif %}
 
       {# Print last item if we are not on the last page. #}
       {% if items.last %}
-        {% spaceless %}
+        {% apply spaceless %}
         <li class="pager__item pager__item--action pager__item--last">
           <a href="{{ items.last.href }}" class="pager__link pager__link--action-link" title="{{ 'Go to last page'|t }}"{{ items.last.attributes|without('href', 'title') }}>
             <span class="visually-hidden">{{ 'Last page'|t }}</span>
@@ -120,7 +120,7 @@
             </span>
           </a>
         </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endif %}
     </ul>
   </nav>
diff --git a/core/themes/claro/templates/views/views-mini-pager.html.twig b/core/themes/claro/templates/views/views-mini-pager.html.twig
index 7f429be4c52eb8bf3d977b144ff2f1ab5de71cb4..c84eb710c9cb1214206d568385ad07c70a4a47ac 100644
--- a/core/themes/claro/templates/views/views-mini-pager.html.twig
+++ b/core/themes/claro/templates/views/views-mini-pager.html.twig
@@ -22,13 +22,13 @@
     <h4{{ title_attributes.addClass('visually-hidden').setAttribute('id', heading_id) }}>{{ 'Pagination'|t }}</h4>
     <ul{{ content_attributes.addClass('pager__items', 'js-pager__items') }}>
       {% if items.previous %}
-        {% spaceless %}
+        {% apply spaceless %}
           <li class="pager__item pager__item--mini pager__item--action pager__item--previous">
             <a{{ items.previous.attributes.addClass(pager_action_classes).setAttribute('title', 'Go to previous page'|t).setAttribute('href', items.previous.href) }}>
               <span class="visually-hidden">{{ 'Previous page'|t }}</span>
             </a>
           </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endif %}
 
       {% if items.current %}
@@ -41,13 +41,13 @@
       {% endif %}
 
       {% if items.next %}
-        {% spaceless %}
+        {% apply spaceless %}
           <li class="pager__item pager__item--mini pager__item--action pager__item--next">
             <a{{ items.next.attributes.addClass(pager_action_classes).setAttribute('title', 'Go to next page'|t).setAttribute('href', items.next.href) }}>
               <span class="visually-hidden">{{ 'Next page'|t }}</span>
             </a>
           </li>
-        {% endspaceless %}
+        {% endapply %}
       {% endif %}
     </ul>
   </nav>
diff --git a/core/themes/classy/templates/dataset/forum-list.html.twig b/core/themes/classy/templates/dataset/forum-list.html.twig
index ce610bb49b9f860ff4f7bfb4f3dc56ae5d23b543..d8523f1598276ca42a5d759fd45852f871158774 100644
--- a/core/themes/classy/templates/dataset/forum-list.html.twig
+++ b/core/themes/classy/templates/dataset/forum-list.html.twig
@@ -52,7 +52,7 @@
           depth this forum resides at. This will allow us to use CSS
           left-margin for indenting.
         #}
-        {% for i in 1..forum.depth if forum.depth > 0 %}<div class="indented">{% endfor %}
+        {% if forum.depth > 0 %}{% for i in 1..forum.depth %}<div class="indented">{% endfor %}{% endif %}
           <div class="forum__icon forum-status-{{ forum.icon_class }}" title="{{ forum.icon_title }}">
             <span class="visually-hidden">{{ forum.icon_title }}</span>
           </div>
@@ -60,7 +60,7 @@
           {% if forum.description.value %}
             <div class="forum__description">{{ forum.description.value }}</div>
           {% endif %}
-        {% for i in 1..forum.depth if forum.depth > 0 %}</div>{% endfor %}
+          {% if forum.depth > 0 %}{% for i in 1..forum.depth %}</div>{% endfor %}{% endif %}
       </td>
       {% if forum.is_container == false %}
         <td class="forum__topics">
diff --git a/core/themes/classy/templates/field/link-formatter-link-separate.html.twig b/core/themes/classy/templates/field/link-formatter-link-separate.html.twig
index cb94264c66a9b930d2218ac1727024aced915d8d..52c8d29a77fc11c037ee2811e4f2eb30f67368aa 100644
--- a/core/themes/classy/templates/field/link-formatter-link-separate.html.twig
+++ b/core/themes/classy/templates/field/link-formatter-link-separate.html.twig
@@ -12,11 +12,11 @@
  * @see template_preprocess_link_formatter_link_separate()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <div class="link-item">
     {% if title %}
       <div class="link-title">{{ title }}</div>
     {% endif %}
     <div class="link-url">{{ link }}</div>
   </div>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/classy/templates/form/dropbutton-wrapper.html.twig b/core/themes/classy/templates/form/dropbutton-wrapper.html.twig
index ca68716db265b4085a34f10cf32edb81c44543a0..a2bdc21d67492b7e772e5a43549a937c6dae40da 100644
--- a/core/themes/classy/templates/form/dropbutton-wrapper.html.twig
+++ b/core/themes/classy/templates/form/dropbutton-wrapper.html.twig
@@ -10,11 +10,11 @@
  */
 #}
 {% if children %}
-  {% spaceless %}
+  {% apply spaceless %}
     <div class="dropbutton-wrapper">
       <div class="dropbutton-widget">
         {{ children }}
       </div>
     </div>
-  {% endspaceless %}
+  {% endapply %}
 {% endif %}
diff --git a/core/themes/classy/templates/form/select.html.twig b/core/themes/classy/templates/form/select.html.twig
index 8af42616f74a825190651a95557231b56dce3794..9c8a97c058977793d4fed3ed5f2ef32b5abe2190 100644
--- a/core/themes/classy/templates/form/select.html.twig
+++ b/core/themes/classy/templates/form/select.html.twig
@@ -10,7 +10,7 @@
  * @see template_preprocess_select()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <select{{ attributes }}>
     {% for option in options %}
       {% if option.type == 'optgroup' %}
@@ -24,4 +24,4 @@
       {% endif %}
     {% endfor %}
   </select>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/classy/templates/layout/book-export-html.html.twig b/core/themes/classy/templates/layout/book-export-html.html.twig
index ea33648d3854a9e356146bd0c4dedaa92b875ee9..b7525f7efa88263beed101cbe8e0dcd4377ab5a8 100644
--- a/core/themes/classy/templates/layout/book-export-html.html.twig
+++ b/core/themes/classy/templates/layout/book-export-html.html.twig
@@ -34,12 +34,12 @@
       to be exported as printer-friendly HTML.
     #}
 
-  {% for i in 1..depth-1 if depth > 1 %}
+  {% if depth > 1 %}{% for i in 1..depth-1 %}
     <div class="section-{{ i }}">
-  {% endfor %}
+  {% endfor %}{% endif %}
   {{ contents }}
-  {% for i in 1..depth-1 if depth > 1 %}
+  {% if depth > 1 %}{% for i in 1..depth-1 %}
     </div>
-  {% endfor %}
+  {% endfor %}{% endif %}
   </body>
 </html>
diff --git a/core/themes/classy/templates/navigation/toolbar.html.twig b/core/themes/classy/templates/navigation/toolbar.html.twig
index 20f12d48b2d4b131393123740fe6e7850a0623f0..5ef3ffad3a3283c4ed4f21b8551271f600cbfe06 100644
--- a/core/themes/classy/templates/navigation/toolbar.html.twig
+++ b/core/themes/classy/templates/navigation/toolbar.html.twig
@@ -27,7 +27,7 @@
       {% set tray = trays[key] %}
       <div{{ tab.attributes.addClass('toolbar-tab') }}>
         {{ tab.link }}
-        {% spaceless %}
+        {% apply spaceless %}
           <div{{ tray.attributes }}>
             {% if tray.label %}
               <nav class="toolbar-lining clearfix" role="navigation" aria-label="{{ tray.label }}">
@@ -38,7 +38,7 @@
             {{ tray.links }}
             </nav>
           </div>
-        {% endspaceless %}
+        {% endapply %}
       </div>
     {% endfor %}
   </nav>
diff --git a/core/themes/engines/twig/twig.engine b/core/themes/engines/twig/twig.engine
index a3d2a5e26dc8e998f31c9b549ffa74e2aafad614..589b5263b4d1e9a52d495a381cc17dde8307cd93 100644
--- a/core/themes/engines/twig/twig.engine
+++ b/core/themes/engines/twig/twig.engine
@@ -8,6 +8,7 @@
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Render\Markup;
 use Drupal\Core\Extension\Extension;
+use Twig\Error\RuntimeError;
 
 /**
  * Implements hook_theme().
@@ -52,7 +53,7 @@ function twig_init(Extension $theme) {
  *   The output generated by the template, plus any debug information.
  */
 function twig_render_template($template_file, array $variables) {
-  /** @var \Twig_Environment $twig_service */
+  /** @var \Twig\Environment $twig_service */
   $twig_service = \Drupal::service('twig');
   $output = [
     'debug_prefix' => '',
@@ -63,10 +64,10 @@ function twig_render_template($template_file, array $variables) {
   try {
     $output['rendered_markup'] = $twig_service->loadTemplate($template_file)->render($variables);
   }
-  catch (\Twig_Error_Runtime $e) {
+  catch (RuntimeError $e) {
     // In case there is a previous exception, re-throw the previous exception,
     // so that the original exception is shown, rather than
-    // \Twig_Template::displayWithErrorHandling()'s exception.
+    // \Twig\Template::displayWithErrorHandling()'s exception.
     $previous_exception = $e->getPrevious();
     if ($previous_exception) {
       throw $previous_exception;
diff --git a/core/themes/stable/templates/admin/block-content-add-list.html.twig b/core/themes/stable/templates/admin/block-content-add-list.html.twig
index ae99d1f834fb286bb3fe6fdbf2047ecad1ab2ded..23717f2fac90202e0adac4ebc30c8a419c6d4313 100644
--- a/core/themes/stable/templates/admin/block-content-add-list.html.twig
+++ b/core/themes/stable/templates/admin/block-content-add-list.html.twig
@@ -12,11 +12,11 @@
  * @see template_preprocess_block_content_add_list()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <dl>
     {% for type in types %}
       <dt>{{ type.link }}</dt>
       <dd>{{ type.description }}</dd>
     {% endfor %}
   </dl>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig b/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig
index 392c494301f45d7c9221dee85eaeed3a520b43b6..c5e87e0fb96cef81de90d4d2bbaa79f410c76bab 100644
--- a/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig
+++ b/core/themes/stable/templates/admin/ckeditor-settings-toolbar.html.twig
@@ -11,7 +11,7 @@
  * @see template_preprocess_ckeditor_settings_toolbar()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <fieldset role="form" aria-labelledby="ckeditor-button-configuration ckeditor-button-description">
     <legend id="ckeditor-button-configuration">{{ 'Toolbar configuration'|t }}</legend>
     <div class="fieldset-wrapper">
@@ -70,4 +70,4 @@
       </div>
     </div>
   </fieldset>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/stable/templates/admin/indentation.html.twig b/core/themes/stable/templates/admin/indentation.html.twig
index c8244b51129236d4cfc4839e80604f9e01cbdae0..591933de0714d3eb3a54cdc41573d5049df604d4 100644
--- a/core/themes/stable/templates/admin/indentation.html.twig
+++ b/core/themes/stable/templates/admin/indentation.html.twig
@@ -9,4 +9,4 @@
  * - size: Optional. The number of indentations to create.
  */
 #}
-{% for i in 1..size if size > 0 %}<div class="js-indentation indentation">&nbsp;</div>{% endfor %}
+{% if size > 0 %}{% for i in 1..size %}<div class="js-indentation indentation">&nbsp;</div>{% endfor %}{% endif %}
diff --git a/core/themes/stable/templates/dataset/forum-list.html.twig b/core/themes/stable/templates/dataset/forum-list.html.twig
index 3de920ae1d0f182b72c3137aba36d6b7e4998a4f..892c59156a0b5949a8d5c3e968a87e446dc99a91 100644
--- a/core/themes/stable/templates/dataset/forum-list.html.twig
+++ b/core/themes/stable/templates/dataset/forum-list.html.twig
@@ -48,7 +48,7 @@
           depth this forum resides at. This will allow us to use CSS
           left-margin for indenting.
         #}
-        {% for i in 1..forum.depth if forum.depth > 0 %}<div class="indent">{% endfor %}
+        {% if forum.depth > 0 %}{% for i in 1..forum.depth %}<div class="indent">{% endfor %}{% endif %}
           <div title="{{ forum.icon_title }}">
             <span class="visually-hidden">{{ forum.icon_title }}</span>
           </div>
@@ -56,7 +56,7 @@
           {% if forum.description.value %}
             <div>{{ forum.description.value }}</div>
           {% endif %}
-        {% for i in 1..forum.depth if forum.depth > 0 %}</div>{% endfor %}
+        {% if forum.depth > 0 %}{% for i in 1..forum.depth %}</div>{% endfor %}{% endif %}
       </td>
       {% if forum.is_container == false %}
         <td>
diff --git a/core/themes/stable/templates/field/link-formatter-link-separate.html.twig b/core/themes/stable/templates/field/link-formatter-link-separate.html.twig
index 0aa1b4a11cbb52af80e68203129ac53af1649709..b75457b412c6469edbb3d40a18a5ed930e4f3fb6 100644
--- a/core/themes/stable/templates/field/link-formatter-link-separate.html.twig
+++ b/core/themes/stable/templates/field/link-formatter-link-separate.html.twig
@@ -12,7 +12,7 @@
  * @see template_preprocess_link_formatter_link_separate()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   {{ title }}
   {{ link }}
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/stable/templates/form/dropbutton-wrapper.html.twig b/core/themes/stable/templates/form/dropbutton-wrapper.html.twig
index ca68716db265b4085a34f10cf32edb81c44543a0..a2bdc21d67492b7e772e5a43549a937c6dae40da 100644
--- a/core/themes/stable/templates/form/dropbutton-wrapper.html.twig
+++ b/core/themes/stable/templates/form/dropbutton-wrapper.html.twig
@@ -10,11 +10,11 @@
  */
 #}
 {% if children %}
-  {% spaceless %}
+  {% apply spaceless %}
     <div class="dropbutton-wrapper">
       <div class="dropbutton-widget">
         {{ children }}
       </div>
     </div>
-  {% endspaceless %}
+  {% endapply %}
 {% endif %}
diff --git a/core/themes/stable/templates/form/select.html.twig b/core/themes/stable/templates/form/select.html.twig
index 3150bdcb36e3af4fcaa85e5ac53b9f97796d9b7f..28c355b3cd629151454b15f57d5cb704a0d3ee16 100644
--- a/core/themes/stable/templates/form/select.html.twig
+++ b/core/themes/stable/templates/form/select.html.twig
@@ -10,7 +10,7 @@
  * @see template_preprocess_select()
  */
 #}
-{% spaceless %}
+{% apply spaceless %}
   <select{{ attributes }}>
     {% for option in options %}
       {% if option.type == 'optgroup' %}
@@ -24,4 +24,4 @@
       {% endif %}
     {% endfor %}
   </select>
-{% endspaceless %}
+{% endapply %}
diff --git a/core/themes/stable/templates/layout/book-export-html.html.twig b/core/themes/stable/templates/layout/book-export-html.html.twig
index 17ac1bc2487b6dac6cd22dfb366ce675e14b87c2..86bb37ed225ef26154b554f46ec76ea2e45dfe32 100644
--- a/core/themes/stable/templates/layout/book-export-html.html.twig
+++ b/core/themes/stable/templates/layout/book-export-html.html.twig
@@ -34,12 +34,12 @@
       to be exported as printer-friendly HTML.
     #}
 
-  {% for i in 1..depth-1 if depth > 1 %}
+  {% if depth > 1 %}{% for i in 1..depth-1 %}
     <div>
-  {% endfor %}
+  {% endfor %}{% endif %}
   {{ contents }}
-  {% for i in 1..depth-1 if depth > 1 %}
+  {% if depth > 1 %}{% for i in 1..depth-1 %}
     </div>
-  {% endfor %}
+  {% endfor %}{% endif %}
   </body>
 </html>
diff --git a/core/themes/stable/templates/navigation/toolbar.html.twig b/core/themes/stable/templates/navigation/toolbar.html.twig
index 497bc781e5f8aefdd5a1f58505d081d9d44384ac..efbe00c2db416a734aa9925be5349bfe62f27902 100644
--- a/core/themes/stable/templates/navigation/toolbar.html.twig
+++ b/core/themes/stable/templates/navigation/toolbar.html.twig
@@ -27,7 +27,7 @@
       {% set tray = trays[key] %}
       <div{{ tab.attributes.addClass('toolbar-tab') }}>
         {{ tab.link }}
-        {% spaceless %}
+        {% apply spaceless %}
           <div{{ tray.attributes }}>
             {% if tray.label %}
               <nav class="toolbar-lining clearfix" role="navigation" aria-label="{{ tray.label }}">
@@ -38,7 +38,7 @@
             {{ tray.links }}
             </nav>
           </div>
-        {% endspaceless %}
+        {% endapply %}
       </div>
     {% endfor %}
   </nav>