diff --git a/core/includes/batch.inc b/core/includes/batch.inc
index cc70557..889e920 100644
--- a/core/includes/batch.inc
+++ b/core/includes/batch.inc
@@ -257,7 +257,7 @@ function _batch_process() {
         'finished' => &$finished,
         'message'  => &$task_message,
       );
-      call_user_func_array($callback, array_merge($args, array(&$batch_context)));
+      $callback(...array_merge($args, array(&$batch_context)));
 
       if ($finished >= 1) {
         // Make sure this step is not counted twice when computing $current.
@@ -392,7 +392,7 @@ function _batch_next_set() {
       // We use our stored copies of $form and $form_state to account for
       // possible alterations by previous form submit handlers.
       $complete_form = &$batch['form_state']->getCompleteForm();
-      call_user_func_array($callback, array(&$complete_form, &$batch['form_state']));
+      $callback(...array(&$complete_form, &$batch['form_state']));
     }
     return TRUE;
   }
@@ -418,7 +418,7 @@ function _batch_finished() {
       if (is_callable($batch_set['finished'])) {
         $queue = _batch_queue($batch_set);
         $operations = $queue->getAllItems();
-        $batch_set_result = call_user_func_array($batch_set['finished'], array($batch_set['success'], $batch_set['results'], $operations, \Drupal::service('date.formatter')->formatInterval($batch_set['elapsed'] / 1000)));
+        $batch_set_result = $batch_set['finished'](...array($batch_set['success'], $batch_set['results'], $operations, \Drupal::service('date.formatter')->formatInterval($batch_set['elapsed'] / 1000)));
         // If a batch 'finished' callback requested a redirect after the batch
         // is complete, save that for later use. If more than one batch set
         // returned a redirect, the last one is used.
diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 03572a6..909b45b 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1004,7 +1004,7 @@ function _drupal_shutdown_function() {
 
   try {
     while (list($key, $callback) = each($callbacks)) {
-      call_user_func_array($callback['callback'], $callback['arguments']);
+      $callback['callback'](...$callback['arguments']);
     }
   }
   // PHP 7 introduces Throwable, which covers both Error and
diff --git a/core/includes/common.inc b/core/includes/common.inc
index 006c58f..74874e8 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -628,7 +628,7 @@ function drupal_process_attached(array $elements) {
       // Limit the amount allowed entries.
       switch ($callback) {
         case 'html_head':
-          call_user_func_array('_drupal_add_html_head', $args);
+          _drupal_add_html_head(...$args);
           break;
         case 'feed':
           $args = [[
@@ -637,10 +637,10 @@ function drupal_process_attached(array $elements) {
             'title' => $args[1],
             'type' => 'application/rss+xml',
           ]];
-          call_user_func_array('_drupal_add_html_head_link', $args);
+          _drupal_add_html_head_link(...$args);
           break;
         case 'html_head_link':
-          call_user_func_array('_drupal_add_html_head_link', $args);
+          _drupal_add_html_head_link(...$args);
           break;
         case 'http_header':
           // @todo Remove validation in https://www.drupal.org/node/2477223
diff --git a/core/lib/Drupal/Component/Datetime/DateTimePlus.php b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
index c3edf99..646e8ae 100644
--- a/core/lib/Drupal/Component/Datetime/DateTimePlus.php
+++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php
@@ -296,7 +296,7 @@ public function __call($method, $args) {
     if (!method_exists($this->dateTimeObject, $method)) {
       throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method));
     }
-    return call_user_func_array(array($this->dateTimeObject, $method), $args);
+    return $this->dateTimeObject->$method(...$args);
   }
 
   /**
@@ -308,7 +308,7 @@ public static function __callStatic($method, $args) {
     if (!method_exists('\DateTime', $method)) {
       throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_called_class(), $method));
     }
-    return call_user_func_array(array('\DateTime', $method), $args);
+    return \DateTime::$method(...$args);
   }
 
   /**
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
index 04e360f..5599002 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/DerivativeDiscoveryDecorator.php
@@ -243,6 +243,6 @@ protected function mergeDerivativeDefinition($base_plugin_definition, $derivativ
    * Passes through all unknown calls onto the decorated object.
    */
   public function __call($method, $args) {
-    return call_user_func_array(array($this->decorated, $method), $args);
+    return $this->decorated->$method(...$args);
   }
 }
diff --git a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php
index ab31eac..7df07d8 100644
--- a/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php
+++ b/core/lib/Drupal/Component/Plugin/Discovery/StaticDiscoveryDecorator.php
@@ -66,6 +66,6 @@ public function getDefinitions() {
    * Passes through all unknown calls onto the decorated object
    */
   public function __call($method, $args) {
-    return call_user_func_array(array($this->decorated, $method), $args);
+    return $this->decorated->$method(...$args);
   }
 }
diff --git a/core/lib/Drupal/Core/Access/AccessManager.php b/core/lib/Drupal/Core/Access/AccessManager.php
index baf9161..b816ab8 100644
--- a/core/lib/Drupal/Core/Access/AccessManager.php
+++ b/core/lib/Drupal/Core/Access/AccessManager.php
@@ -165,7 +165,7 @@ protected function performCheck($service_id, ArgumentsResolverInterface $argumen
     $callable = $this->checkProvider->loadCheck($service_id);
     $arguments = $arguments_resolver->getArguments($callable);
     /** @var \Drupal\Core\Access\AccessResultInterface $service_access **/
-    $service_access = call_user_func_array($callable, $arguments);
+    $service_access = $callable(...$arguments);
 
     if (!$service_access instanceof AccessResultInterface) {
       throw new AccessException("Access error in $service_id. Access services must return an object that implements AccessResultInterface.");
diff --git a/core/lib/Drupal/Core/Access/CustomAccessCheck.php b/core/lib/Drupal/Core/Access/CustomAccessCheck.php
index fb2ccdd..da9f783 100644
--- a/core/lib/Drupal/Core/Access/CustomAccessCheck.php
+++ b/core/lib/Drupal/Core/Access/CustomAccessCheck.php
@@ -68,7 +68,7 @@ public function access(Route $route, RouteMatchInterface $route_match, AccountIn
     $arguments_resolver = $this->argumentsResolverFactory->getArgumentsResolver($route_match, $account);
     $arguments = $arguments_resolver->getArguments($callable);
 
-    return call_user_func_array($callable, $arguments);
+    return $callable(...$arguments);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigImporter.php b/core/lib/Drupal/Core/Config/ConfigImporter.php
index e0d4e0d..96546f8 100644
--- a/core/lib/Drupal/Core/Config/ConfigImporter.php
+++ b/core/lib/Drupal/Core/Config/ConfigImporter.php
@@ -492,7 +492,7 @@ public function doSyncStep($sync_step, &$context) {
       $this->$sync_step($context);
     }
     elseif (is_callable($sync_step)) {
-      call_user_func_array($sync_step, array(&$context, $this));
+      $sync_step(...array(&$context, $this));
     }
     else {
       throw new \InvalidArgumentException('Invalid configuration synchronization step');
diff --git a/core/lib/Drupal/Core/Controller/TitleResolver.php b/core/lib/Drupal/Core/Controller/TitleResolver.php
index 4fe90a6..ae237fd 100644
--- a/core/lib/Drupal/Core/Controller/TitleResolver.php
+++ b/core/lib/Drupal/Core/Controller/TitleResolver.php
@@ -49,7 +49,7 @@ public function getTitle(Request $request, Route $route) {
     if ($callback = $route->getDefault('_title_callback')) {
       $callable = $this->controllerResolver->getControllerFromDefinition($callback);
       $arguments = $this->controllerResolver->getArguments($request, $callable);
-      $route_title = call_user_func_array($callable, $arguments);
+      $route_title = $callable(...$arguments);
     }
     elseif ($title = $route->getDefault('_title')) {
       $options = array();
diff --git a/core/lib/Drupal/Core/Database/Install/Tasks.php b/core/lib/Drupal/Core/Database/Install/Tasks.php
index fed2c5e..60ecfb2 100644
--- a/core/lib/Drupal/Core/Database/Install/Tasks.php
+++ b/core/lib/Drupal/Core/Database/Install/Tasks.php
@@ -140,7 +140,7 @@ public function runTasks() {
         }
         if (method_exists($this, $task['function'])) {
           // Returning false is fatal. No other tasks can run.
-          if (FALSE === call_user_func_array(array($this, $task['function']), $task['arguments'])) {
+          if (FALSE === $this->{$task['function']}(...$task['arguments'])) {
             break;
           }
         }
diff --git a/core/lib/Drupal/Core/Database/Query/AlterableInterface.php b/core/lib/Drupal/Core/Database/Query/AlterableInterface.php
index 36992f0..d1af32a 100644
--- a/core/lib/Drupal/Core/Database/Query/AlterableInterface.php
+++ b/core/lib/Drupal/Core/Database/Query/AlterableInterface.php
@@ -50,7 +50,7 @@ public function hasTag($tag);
    *   TRUE if this query has been marked with all specified tags, FALSE
    *   otherwise.
    */
-  public function hasAllTags();
+  public function hasAllTags(...$args);
 
   /**
    * Determines if a given query has any specified tag.
@@ -62,7 +62,7 @@ public function hasAllTags();
    *   TRUE if this query has been marked with at least one of the specified
    *   tags, FALSE otherwise.
    */
-  public function hasAnyTag();
+  public function hasAnyTag(...$args);
 
   /**
    * Adds additional metadata to the query.
diff --git a/core/lib/Drupal/Core/Database/Query/Select.php b/core/lib/Drupal/Core/Database/Query/Select.php
index 3be5a2f..90b30cf 100644
--- a/core/lib/Drupal/Core/Database/Query/Select.php
+++ b/core/lib/Drupal/Core/Database/Query/Select.php
@@ -157,15 +157,15 @@ public function hasTag($tag) {
   /**
    * {@inheritdoc}
    */
-  public function hasAllTags() {
-    return !(boolean)array_diff(func_get_args(), array_keys($this->alterTags));
+  public function hasAllTags(...$args) {
+    return !(boolean)array_diff($args, array_keys($this->alterTags));
   }
 
   /**
    * {@inheritdoc}
    */
-  public function hasAnyTag() {
-    return (boolean)array_intersect(func_get_args(), array_keys($this->alterTags));
+  public function hasAnyTag(...$args) {
+    return (boolean)array_intersect($args, array_keys($this->alterTags));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Database/Query/SelectExtender.php b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
index cca68c7..b8d5524 100644
--- a/core/lib/Drupal/Core/Database/Query/SelectExtender.php
+++ b/core/lib/Drupal/Core/Database/Query/SelectExtender.php
@@ -69,12 +69,12 @@ public function hasTag($tag) {
     return $this->query->hasTag($tag);
   }
 
-  public function hasAllTags() {
-    return call_user_func_array(array($this->query, 'hasAllTags'), func_get_args());
+  public function hasAllTags(...$args) {
+    return $this->query->hasAllTags($args);
   }
 
-  public function hasAnyTag() {
-    return call_user_func_array(array($this->query, 'hasAnyTag'), func_get_args());
+  public function hasAnyTag(...$args) {
+    return $this->query->hasAnyTag($args);
   }
 
   public function addMetaData($key, $object) {
@@ -360,7 +360,7 @@ public function __clone() {
    * to handle any additional methods.
    */
   public function __call($method, $args) {
-    $return = call_user_func_array(array($this->query, $method), $args);
+    $return = $this->query->$method(...$args);
 
     // Some methods will return the called object as part of a fluent interface.
     // Others will return some useful value.  If it's a value, then the caller
diff --git a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
index ce692b5..0136836 100644
--- a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
+++ b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
@@ -111,7 +111,7 @@ protected function callMethod($service, $call) {
       }
     }
 
-    call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
+    $service->{$call[0]}(...$this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
index 6e6a74f..dfe2166 100644
--- a/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
+++ b/core/lib/Drupal/Core/Entity/ContentEntityStorageBase.php
@@ -412,7 +412,7 @@ protected function invokeFieldMethod($method, ContentEntityInterface $entity) {
       foreach ($fields as $name => $items) {
         // call_user_func_array() is way slower than a direct call so we avoid
         // using it if have no parameters.
-        $result[$langcode][$name] = $args ? call_user_func_array([$items, $method], $args) : $items->{$method}();
+        $result[$langcode][$name] = $args ? $items->$method(...$args) : $items->{$method}();
       }
     }
     return $result;
diff --git a/core/lib/Drupal/Core/Entity/EntityForm.php b/core/lib/Drupal/Core/Entity/EntityForm.php
index 5450e25..cf39c12 100644
--- a/core/lib/Drupal/Core/Entity/EntityForm.php
+++ b/core/lib/Drupal/Core/Entity/EntityForm.php
@@ -290,7 +290,7 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
     // properties.
     if (isset($form['#entity_builders'])) {
       foreach ($form['#entity_builders'] as $function) {
-        call_user_func_array($function, array($entity->getEntityTypeId(), $entity, &$form, &$form_state));
+        $function(...array($entity->getEntityTypeId(), $entity, &$form, &$form_state));
       }
     }
 
@@ -376,7 +376,7 @@ protected function prepareInvokeAll($hook, FormStateInterface $form_state) {
         // Ensure we pass an updated translation object and form display at
         // each invocation, since they depend on form state which is alterable.
         $args = array($this->entity, $this->operation, &$form_state);
-        call_user_func_array($function, $args);
+        $function(...$args);
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Entity/Query/QueryBase.php b/core/lib/Drupal/Core/Entity/Query/QueryBase.php
index 6f3d6aa..c2a9ed2 100644
--- a/core/lib/Drupal/Core/Entity/Query/QueryBase.php
+++ b/core/lib/Drupal/Core/Entity/Query/QueryBase.php
@@ -352,15 +352,15 @@ public function hasTag($tag) {
   /**
    * Implements \Drupal\Core\Database\Query\AlterableInterface::hasAllTags().
    */
-  public function hasAllTags() {
-    return !(boolean)array_diff(func_get_args(), array_keys($this->alterTags));
+  public function hasAllTags(...$args) {
+    return !(boolean)array_diff($args, array_keys($this->alterTags));
   }
 
   /**
    * Implements \Drupal\Core\Database\Query\AlterableInterface::hasAnyTag().
    */
-  public function hasAnyTag() {
-    return (boolean)array_intersect(func_get_args(), array_keys($this->alterTags));
+  public function hasAnyTag(...$args) {
+    return (boolean)array_intersect($args, array_keys($this->alterTags));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php
index 0acda56..8b7092e 100644
--- a/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php
@@ -126,7 +126,7 @@ protected function wrapControllerExecutionInRenderContext($controller, array $ar
 
     $response = $this->renderer->executeInRenderContext($context, function() use ($controller, $arguments) {
       // Now call the actual controller, just like HttpKernel does.
-      return call_user_func_array($controller, $arguments);
+      return $controller(...$arguments);
     });
 
     // If early rendering happened, i.e. if code in the controller called
diff --git a/core/lib/Drupal/Core/Extension/Extension.php b/core/lib/Drupal/Core/Extension/Extension.php
index 3c765fe..ecf028c 100644
--- a/core/lib/Drupal/Core/Extension/Extension.php
+++ b/core/lib/Drupal/Core/Extension/Extension.php
@@ -157,7 +157,7 @@ public function __call($method, array $args) {
     if (!isset($this->splFileInfo)) {
       $this->splFileInfo = new \SplFileInfo($this->pathname);
     }
-    return call_user_func_array(array($this->splFileInfo, $method), $args);
+    return $this->splFileInfo->$method(...$args);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Extension/ModuleHandler.php b/core/lib/Drupal/Core/Extension/ModuleHandler.php
index f97897c..d4e08c4 100644
--- a/core/lib/Drupal/Core/Extension/ModuleHandler.php
+++ b/core/lib/Drupal/Core/Extension/ModuleHandler.php
@@ -380,7 +380,7 @@ public function invoke($module, $hook, array $args = array()) {
       return;
     }
     $function = $module . '_' . $hook;
-    return call_user_func_array($function, $args);
+    return $function(...$args);
   }
 
   /**
@@ -391,7 +391,7 @@ public function invokeAll($hook, array $args = array()) {
     $implementations = $this->getImplementations($hook);
     foreach ($implementations as $module) {
       $function = $module . '_' . $hook;
-      $result = call_user_func_array($function, $args);
+      $result = $function(...$args);
       if (isset($result) && is_array($result)) {
         $return = NestedArray::mergeDeep($return, $result);
       }
diff --git a/core/lib/Drupal/Core/Extension/ModuleInstaller.php b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
index 41e698c..21a68d8 100644
--- a/core/lib/Drupal/Core/Extension/ModuleInstaller.php
+++ b/core/lib/Drupal/Core/Extension/ModuleInstaller.php
@@ -449,7 +449,7 @@ protected function removeCacheBins($module) {
                 try {
                   $factory = \Drupal::service($definition['factory_service']);
                   if (method_exists($factory, $definition['factory_method'])) {
-                    $backend = call_user_func_array(array($factory, $definition['factory_method']), $definition['arguments']);
+                    $backend = $factory->{$definition['factory_method']}(...$definition['arguments']);
                     if ($backend instanceof CacheBackendInterface) {
                       $backend->removeBin();
                     }
diff --git a/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php
index 1067ae8..9c62e31 100644
--- a/core/lib/Drupal/Core/Field/FieldItemList.php
+++ b/core/lib/Drupal/Core/Field/FieldItemList.php
@@ -244,9 +244,7 @@ protected function delegateMethod($method) {
     $result = [];
     $args = array_slice(func_get_args(), 1);
     foreach ($this->list as $delta => $item) {
-      // call_user_func_array() is way slower than a direct call so we avoid
-      // using it if have no parameters.
-      $result[$delta] = $args ? call_user_func_array([$item, $method], $args) : $item->{$method}();
+      $result[$delta] = $item->$method(...$args);
     }
     return $result;
   }
diff --git a/core/lib/Drupal/Core/FileTransfer/Form/FileTransferAuthorizeForm.php b/core/lib/Drupal/Core/FileTransfer/Form/FileTransferAuthorizeForm.php
index 7bc0f1c..94222e5 100644
--- a/core/lib/Drupal/Core/FileTransfer/Form/FileTransferAuthorizeForm.php
+++ b/core/lib/Drupal/Core/FileTransfer/Form/FileTransferAuthorizeForm.php
@@ -348,7 +348,7 @@ protected function runOperation($filetransfer) {
     unset($_SESSION['authorize_operation']);
 
     require_once $this->root . '/' . $operation['file'];
-    return call_user_func_array($operation['callback'], array_merge(array($filetransfer), $operation['arguments']));
+    return $operation['callback'](...array_merge(array($filetransfer), $operation['arguments']));
   }
 
 }
diff --git a/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php b/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php
index 7d1c4b7..0c9030c 100644
--- a/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php
@@ -71,7 +71,7 @@ public function buildResponse(Request $request, array $form, FormStateInterface
     if (empty($callback) || !is_callable($callback)) {
       throw new HttpException(500, 'The specified #ajax callback is empty or not callable.');
     }
-    $result = call_user_func_array($callback, [&$form, &$form_state, $request]);
+    $result = $callback(...[&$form, &$form_state, $request]);
 
     // If the callback is an #ajax callback, the result is a render array, and
     // we need to turn it into an AJAX response, so that we can add any commands
diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php
index fe6d104..c04c6db 100644
--- a/core/lib/Drupal/Core/Form/FormBuilder.php
+++ b/core/lib/Drupal/Core/Form/FormBuilder.php
@@ -474,7 +474,7 @@ public function retrieveForm($form_id, FormStateInterface &$form_state) {
     // passed explicitly.
     $args = array_merge(array($form, &$form_state), $args);
 
-    $form = call_user_func_array($callback, $args);
+    $form = $callback(...$args);
     // If the form returns a response, skip subsequent page construction by
     // throwing an exception.
     // @see Drupal\Core\EventSubscriber\EnforcedFormResponseSubscriber
@@ -853,7 +853,8 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
     if (isset($element['#process']) && !$element['#processed']) {
       foreach ($element['#process'] as $callback) {
         $complete_form = &$form_state->getCompleteForm();
-        $element = call_user_func_array($form_state->prepareCallback($callback), array(&$element, &$form_state, &$complete_form));
+        $function = $form_state->prepareCallback($callback);
+        $element = $function(...[&$element, &$form_state, &$complete_form]);
       }
       $element['#processed'] = TRUE;
     }
@@ -924,7 +925,8 @@ public function doBuildForm($form_id, &$element, FormStateInterface &$form_state
     // after normal input parsing has been completed.
     if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
       foreach ($element['#after_build'] as $callback) {
-        $element = call_user_func_array($form_state->prepareCallback($callback), array($element, &$form_state));
+        $function = $form_state->prepareCallback($callback);
+        $element = $function(...[$element, &$form_state]);
       }
       $element['#after_build_done'] = TRUE;
     }
@@ -1077,7 +1079,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
         // If we have input for the current element, assign it to the #value
         // property, optionally filtered through $value_callback.
         if ($input_exists) {
-          $element['#value'] = call_user_func_array($value_callable, array(&$element, $input, &$form_state));
+          $element['#value'] = $value_callable(...[&$element, $input, &$form_state]);
 
           if (!isset($element['#value']) && isset($input)) {
             $element['#value'] = $input;
@@ -1092,7 +1094,7 @@ protected function handleInputElement($form_id, &$element, FormStateInterface &$
       if (!isset($element['#value'])) {
         // Call #type_value without a second argument to request default_value
         // handling.
-        $element['#value'] = call_user_func_array($value_callable, array(&$element, FALSE, &$form_state));
+        $element['#value'] = $value_callable(...[&$element, FALSE, &$form_state]);
 
         // Final catch. If we haven't set a value yet, use the explicit default
         // value. Avoid image buttons (which come with garbage value), so we
diff --git a/core/lib/Drupal/Core/Form/FormSubmitter.php b/core/lib/Drupal/Core/Form/FormSubmitter.php
index a9bd0ac..ba330bd 100644
--- a/core/lib/Drupal/Core/Form/FormSubmitter.php
+++ b/core/lib/Drupal/Core/Form/FormSubmitter.php
@@ -113,7 +113,8 @@ public function executeSubmitHandlers(&$form, FormStateInterface &$form_state) {
         $batch['has_form_submits'] = TRUE;
       }
       else {
-        call_user_func_array($form_state->prepareCallback($callback), array(&$form, &$form_state));
+        $function = $form_state->prepareCallback($callback);
+        $function(...[&$form, &$form_state]);
       }
     }
   }
diff --git a/core/lib/Drupal/Core/Form/FormValidator.php b/core/lib/Drupal/Core/Form/FormValidator.php
index 96f2320..a8efae9 100644
--- a/core/lib/Drupal/Core/Form/FormValidator.php
+++ b/core/lib/Drupal/Core/Form/FormValidator.php
@@ -85,7 +85,8 @@ public function executeValidateHandlers(&$form, FormStateInterface &$form_state)
     }
 
     foreach ($handlers as $callback) {
-      call_user_func_array($form_state->prepareCallback($callback), array(&$form, &$form_state));
+      $function = $form_state->prepareCallback($callback);
+      $function(...[&$form, &$form_state]);
     }
   }
 
@@ -270,7 +271,8 @@ protected function doValidateForm(&$elements, FormStateInterface &$form_state, $
       elseif (isset($elements['#element_validate'])) {
         foreach ($elements['#element_validate'] as $callback) {
           $complete_form = &$form_state->getCompleteForm();
-          call_user_func_array($form_state->prepareCallback($callback), array(&$elements, &$form_state, &$complete_form));
+          $function = $form_state->prepareCallback($callback);
+          $function(...[&$elements, &$form_state, &$complete_form]);
         }
       }
 
diff --git a/core/lib/Drupal/Core/Menu/LocalActionManager.php b/core/lib/Drupal/Core/Menu/LocalActionManager.php
index c387b15..47101f0 100644
--- a/core/lib/Drupal/Core/Menu/LocalActionManager.php
+++ b/core/lib/Drupal/Core/Menu/LocalActionManager.php
@@ -155,7 +155,7 @@ protected function getDiscovery() {
   public function getTitle(LocalActionInterface $local_action) {
     $controller = array($local_action, 'getTitle');
     $arguments = $this->controllerResolver->getArguments($this->requestStack->getCurrentRequest(), $controller);
-    return call_user_func_array($controller, $arguments);
+    return $controller(...$arguments);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Menu/LocalTaskManager.php b/core/lib/Drupal/Core/Menu/LocalTaskManager.php
index 5b12ac8..6f8e415 100644
--- a/core/lib/Drupal/Core/Menu/LocalTaskManager.php
+++ b/core/lib/Drupal/Core/Menu/LocalTaskManager.php
@@ -167,7 +167,7 @@ public function getTitle(LocalTaskInterface $local_task) {
     $controller = array($local_task, 'getTitle');
     $request = $this->requestStack->getCurrentRequest();
     $arguments = $this->controllerResolver->getArguments($request, $controller);
-    return call_user_func_array($controller, $arguments);
+    return $controller(...$arguments);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTree.php b/core/lib/Drupal/Core/Menu/MenuLinkTree.php
index 090293c..989b7d3 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkTree.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkTree.php
@@ -142,10 +142,10 @@ public function transform(array $tree, array $manipulators) {
       // argument is always the menu link tree.
       if (isset($manipulator['args'])) {
         array_unshift($manipulator['args'], $tree);
-        $tree = call_user_func_array($callable, $manipulator['args']);
+        $tree = $callable(...$manipulator['args']);
       }
       else {
-        $tree = call_user_func($callable, $tree);
+        $tree = $callable($tree);
       }
     }
     return $tree;
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php
index fb6c95b..7c9c6d2 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/InfoHookDecorator.php
@@ -60,7 +60,7 @@ public function getDefinitions() {
    * Passes through all unknown calls onto the decorated object.
    */
   public function __call($method, $args) {
-    return call_user_func_array(array($this->decorated, $method), $args);
+    return $this->decorated->$method(...$args);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscoveryDecorator.php b/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscoveryDecorator.php
index 2957dc0..2456c10 100644
--- a/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscoveryDecorator.php
+++ b/core/lib/Drupal/Core/Plugin/Discovery/YamlDiscoveryDecorator.php
@@ -52,7 +52,7 @@ public function getDefinitions() {
    * Passes through all unknown calls onto the decorated object.
    */
   public function __call($method, $args) {
-    return call_user_func_array(array($this->decorated, $method), $args);
+    return $this->decorated->$method(...$args);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Render/Renderer.php b/core/lib/Drupal/Core/Render/Renderer.php
index 2ef11d1..084918d 100644
--- a/core/lib/Drupal/Core/Render/Renderer.php
+++ b/core/lib/Drupal/Core/Render/Renderer.php
@@ -357,10 +357,17 @@ protected function doRender(&$elements, $is_root_call = FALSE) {
     if (isset($elements['#lazy_builder'])) {
       $callable = $elements['#lazy_builder'][0];
       $args = $elements['#lazy_builder'][1];
-      if (is_string($callable) && strpos($callable, '::') === FALSE) {
-        $callable = $this->controllerResolver->getControllerFromDefinition($callable);
+      if (is_string($callable)) {
+        if (strpos($callable, '::') === FALSE) {
+          $callable = $this->controllerResolver->getControllerFromDefinition($callable);
+        }
+        else {
+          // Variadics don't support interpreting Foo::bar as a static call, so
+          // we convert it manually.
+          $callable = explode('::', $callable);
+        }
       }
-      $new_elements = call_user_func_array($callable, $args);
+      $new_elements = $callable(...$args);
       // Retain the original cacheability metadata, plus cache keys.
       CacheableMetadata::createFromRenderArray($elements)
         ->merge(CacheableMetadata::createFromRenderArray($new_elements))
diff --git a/core/lib/Drupal/Core/Routing/AccessAwareRouter.php b/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
index 8a115b2..e9a7ed5 100644
--- a/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
+++ b/core/lib/Drupal/Core/Routing/AccessAwareRouter.php
@@ -62,7 +62,8 @@ public function __construct(ChainRouter $chain_router, AccessManagerInterface $a
   public function __call($name, $arguments) {
     // Ensure to call every other function to the chained router.
     // @todo Sadly does the ChainRouter not implement an interface in CMF.
-    return call_user_func_array([$this->chainRouter, $name], $arguments);
+    $this->chainRouter->$name(...$arguments);
+    //return call_user_func_array([$this->chainRouter, $name], $arguments);
   }
 
   /**
diff --git a/core/modules/color/color.module b/core/modules/color/color.module
index fa9499b..3939a2b 100644
--- a/core/modules/color/color.module
+++ b/core/modules/color/color.module
@@ -718,7 +718,7 @@ function _color_shift($given, $ref1, $ref2, $target) {
  */
 function _color_gd($img, $hex) {
   $c = array_merge(array($img), _color_unpack($hex));
-  return call_user_func_array('imagecolorallocate', $c);
+  return imagecolorallocate(...$c);
 }
 
 /**
@@ -732,7 +732,7 @@ function _color_blend($img, $hex1, $hex2, $alpha) {
     $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha;
   }
 
-  return call_user_func_array('imagecolorallocate', $out);
+  return imagecolorallocate(...$out);
 }
 
 /**
diff --git a/core/modules/file/file.module b/core/modules/file/file.module
index a995916..21da50d 100644
--- a/core/modules/file/file.module
+++ b/core/modules/file/file.module
@@ -288,7 +288,7 @@ function file_validate(FileInterface $file, $validators = array()) {
   foreach ($validators as $function => $args) {
     if (function_exists($function)) {
       array_unshift($args, $file);
-      $errors = array_merge($errors, call_user_func_array($function, $args));
+      $errors = array_merge($errors, $function(...$args));
     }
   }
 
diff --git a/core/modules/locale/src/Plugin/QueueWorker/LocaleTranslation.php b/core/modules/locale/src/Plugin/QueueWorker/LocaleTranslation.php
index a850b0d..a3fc486 100644
--- a/core/modules/locale/src/Plugin/QueueWorker/LocaleTranslation.php
+++ b/core/modules/locale/src/Plugin/QueueWorker/LocaleTranslation.php
@@ -109,7 +109,7 @@ public function processItem($data) {
     $args = array_merge($args, [&$batch_context]);
 
     // Call the batch operation function.
-    call_user_func_array($function, $args);
+    $function(...$args);
 
     // If the batch operation is not finished we create a new queue task to
     // continue the task. This is typically the translation import task.
diff --git a/core/modules/rest/src/RequestHandler.php b/core/modules/rest/src/RequestHandler.php
index ee4b890..6265b98 100644
--- a/core/modules/rest/src/RequestHandler.php
+++ b/core/modules/rest/src/RequestHandler.php
@@ -92,7 +92,7 @@ public function handle(RouteMatchInterface $route_match, Request $request) {
     // format requirement. If there is no format associated, just pick JSON.
     $format = $route_match->getRouteObject()->getRequirement('_format') ?: 'json';
     try {
-      $response = call_user_func_array(array($resource, $method), array_merge($parameters, array($unserialized, $request)));
+      $response = $resource->$method(...array_merge($parameters, array($unserialized, $request)));
     }
     catch (HttpException $e) {
       $error['error'] = $e->getMessage();
diff --git a/core/modules/simpletest/src/KernelTestBase.php b/core/modules/simpletest/src/KernelTestBase.php
index ba8622b..0e61cdc 100644
--- a/core/modules/simpletest/src/KernelTestBase.php
+++ b/core/modules/simpletest/src/KernelTestBase.php
@@ -238,7 +238,7 @@ protected function setUp() {
     // defined by base classes should be sorted first. Then, merge the results
     // together.
     $modules = array_reverse($modules);
-    $modules = call_user_func_array('array_merge_recursive', $modules);
+    $modules = array_merge_recursive(...$modules);
     if ($modules) {
       $this->enableModules($modules);
     }
diff --git a/core/modules/views/src/Plugin/views/HandlerBase.php b/core/modules/views/src/Plugin/views/HandlerBase.php
index f2e5604..31a502c 100644
--- a/core/modules/views/src/Plugin/views/HandlerBase.php
+++ b/core/modules/views/src/Plugin/views/HandlerBase.php
@@ -481,7 +481,7 @@ public function showExposeForm(&$form, FormStateInterface $form_state) {
   public function access(AccountInterface $account) {
     if (isset($this->definition['access callback']) && function_exists($this->definition['access callback'])) {
       if (isset($this->definition['access arguments']) && is_array($this->definition['access arguments'])) {
-        return call_user_func_array($this->definition['access callback'], array($account) + $this->definition['access arguments']);
+        return $this->definition['access callback'](...(array($account) + $this->definition['access arguments']));
       }
       return $this->definition['access callback']($account);
     }
diff --git a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
index a1f1c5e..0ebb8ab 100644
--- a/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
+++ b/core/modules/views/src/Plugin/views/argument/ArgumentPluginBase.php
@@ -643,7 +643,7 @@ public function defaultAction($info = NULL) {
     }
 
     if (!empty($info['method args'])) {
-      return call_user_func_array(array(&$this, $info['method']), $info['method args']);
+      return $this->{$info['method']}(...$info['method args']);
     }
     else {
       return $this->{$info['method']}();
diff --git a/core/modules/views/src/Plugin/views/field/MachineName.php b/core/modules/views/src/Plugin/views/field/MachineName.php
index 0c289cd..5cacd09 100644
--- a/core/modules/views/src/Plugin/views/field/MachineName.php
+++ b/core/modules/views/src/Plugin/views/field/MachineName.php
@@ -35,7 +35,8 @@ public function getValueOptions() {
 
     if (isset($this->definition['options callback']) && is_callable($this->definition['options callback'])) {
       if (isset($this->definition['options arguments']) && is_array($this->definition['options arguments'])) {
-        $this->valueOptions = call_user_func_array($this->definition['options callback'], $this->definition['options arguments']);
+        $function = $this->definition['options call back'];
+        $this->valueOptions = $function(...$this->definition['options arguments']);
       }
       else {
         $this->valueOptions = call_user_func($this->definition['options callback']);
diff --git a/core/modules/views/src/Plugin/views/filter/InOperator.php b/core/modules/views/src/Plugin/views/filter/InOperator.php
index d08aa00..cb82744 100644
--- a/core/modules/views/src/Plugin/views/filter/InOperator.php
+++ b/core/modules/views/src/Plugin/views/filter/InOperator.php
@@ -70,7 +70,8 @@ public function getValueOptions() {
 
     if (isset($this->definition['options callback']) && is_callable($this->definition['options callback'])) {
       if (isset($this->definition['options arguments']) && is_array($this->definition['options arguments'])) {
-        $this->valueOptions = call_user_func_array($this->definition['options callback'], $this->definition['options arguments']);
+        $function = $this->definition['options callback'];
+        $this->valueOptions = $function(...$this->definition['options arguments']);
       }
       else {
         $this->valueOptions = call_user_func($this->definition['options callback']);
diff --git a/core/modules/views_ui/src/ViewUI.php b/core/modules/views_ui/src/ViewUI.php
index 8168bf2..15f56bd 100644
--- a/core/modules/views_ui/src/ViewUI.php
+++ b/core/modules/views_ui/src/ViewUI.php
@@ -273,7 +273,7 @@ public function standardSubmit($form, FormStateInterface $form_state) {
     }
 
     $submit_handler = [$form_state->getFormObject(), 'submitForm'];
-    call_user_func_array($submit_handler, [&$form, $form_state]);
+    $submit_handler(...[&$form, $form_state]);
   }
 
   /**
@@ -930,7 +930,7 @@ public function isLocked() {
    * Passes through all unknown calls onto the storage object.
    */
   public function __call($method, $args) {
-    return call_user_func_array(array($this->storage, $method), $args);
+    return $this->storage->$method(...$args);
   }
 
   /**
diff --git a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php
index cb26b58..644751e 100644
--- a/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php
+++ b/core/modules/views_ui/tests/src/Unit/ViewUIObjectTest.php
@@ -65,7 +65,7 @@ public function testEntityDecoration() {
       foreach ($args as $arg) {
         $method_mock->with($this->equalTo($arg));
       }
-      call_user_func_array(array($view_ui, $method), $args);
+      $view_ui->$method(...$args);
     }
 
     $storage->expects($this->once())
