diff --git a/core/core.services.yml b/core/core.services.yml
index 2b31f93..0c038ec 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -212,7 +212,7 @@ services:
     arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
   plugin.manager.menu.local_task:
     class: Drupal\Core\Menu\LocalTaskManager
-    arguments: ['@controller_resolver', '@request', '@router.route_provider', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
+    arguments: ['@controller_resolver', '@request', '@router.route_provider', '@router.builder', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
   plugin.manager.menu.contextual_link:
     class: Drupal\Core\Menu\ContextualLinkManager
     arguments: ['@controller_resolver', '@module_handler', '@cache.cache', '@language_manager', '@access_manager', '@current_user']
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 8619448..3665322 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -431,78 +431,6 @@ function menu_unserialize($data, $map) {
   }
 }
 
-
-
-/**
- * Replaces the statically cached item for a given path.
- *
- * @param $path
- *   The path.
- * @param $router_item
- *   The router item. Usually a router entry from menu_get_item() is either
- *   modified or set to a different path. This allows the navigation block,
- *   the page title, the active trail, and the page help to be modified in one
- *   call.
- */
-function menu_set_item($path, $router_item) {
-  menu_get_item($path, $router_item);
-}
-
-/**
- * Gets a router item.
- *
- * @param $path
- *   The path; for example, 'node/5'. The function will find the corresponding
- *   node/% item and return that.
- * @param $router_item
- *   Internal use only.
- *
- * @return
- *   The router item or, if an error occurs in _menu_translate(), FALSE. A
- *   router item is an associative array corresponding to one row in the
- *   menu_router table. The value corresponding to the key 'map' holds the
- *   loaded objects. The value corresponding to the key 'access' is TRUE if the
- *   current user can access this page. The values corresponding to the keys
- *   'title', 'page_arguments', and 'access_arguments', will be filled in based
- *   on the database values and the objects loaded.
- */
-function menu_get_item($path = NULL, $router_item = NULL) {
-  $router_items = &drupal_static(__FUNCTION__);
-  if (!isset($path)) {
-    $path = current_path();
-  }
-  if (isset($router_item)) {
-    $router_items[$path] = $router_item;
-  }
-  if (!isset($router_items[$path])) {
-    \Drupal::service('router.builder')->rebuildIfNeeded();
-    $original_map = arg(NULL, $path);
-
-    $parts = array_slice($original_map, 0, MENU_MAX_PARTS);
-    $ancestors = menu_get_ancestors($parts);
-    $router_item = db_query_range('SELECT * FROM {menu_router} WHERE path IN (:ancestors) ORDER BY fit DESC', 0, 1, array(':ancestors' => $ancestors))->fetchAssoc();
-
-    if ($router_item) {
-      // Allow modules to alter the router item before it is translated and
-      // checked for access.
-      drupal_alter('menu_get_item', $router_item, $path, $original_map);
-
-      $map = _menu_translate($router_item, $original_map);
-      $router_item['original_map'] = $original_map;
-      if ($map === FALSE) {
-        $router_items[$path] = FALSE;
-        return FALSE;
-      }
-      if ($router_item['access']) {
-        $router_item['map'] = $map;
-        $router_item['page_arguments'] = array_merge(menu_unserialize($router_item['page_arguments'], $map), array_slice($map, $router_item['number_parts']));
-      }
-    }
-    $router_items[$path] = $router_item;
-  }
-  return $router_items[$path];
-}
-
 /**
  * Loads objects into the map as defined in the $item['load_functions'].
  *
@@ -1006,8 +934,6 @@ function menu_tree_output($tree) {
     }
   }
 
-  $router_item = menu_get_item();
-  $num_items = count($items);
   foreach ($items as $data) {
     $class = array();
     // Set a class for the <li>-tag. Since $data['below'] may contain local
@@ -1198,16 +1124,6 @@ function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail =
     $system_path = $request->attributes->get('_system_path');
     $page_not_403 = 1;
   }
-  // @todo Remove once the old router system is removed.
-  elseif ($request->attributes->has('_legacy')) {
-    // Page is a 404 if no item is loaded.
-    if ($item = menu_get_item($active_path)) {
-      $system_path = $item['href'];
-      // Variable to indicate that we are not serving an access denied response
-      // for this page. Used to limit the number of links rendered.
-      $page_not_403 = (int) $item['access'];
-    }
-  }
   if (isset($system_path)) {
     if (isset($max_depth)) {
       $max_depth = min($max_depth, MENU_MAX_DEPTH);
@@ -1765,7 +1681,6 @@ function menu_navigation_links($menu_name, $level = 0) {
   }
 
   // Create a single level of links.
-  $router_item = menu_get_item();
   $links = array();
   foreach ($tree as $item) {
     if (!$item['link']['hidden']) {
@@ -1781,7 +1696,7 @@ function menu_navigation_links($menu_name, $level = 0) {
       // sets the active class accordingly. But local tasks do not appear in
       // menu trees, so if the current path is a local task, and this link is
       // its tab root, then we have to set the class manually.
-      if ($item['link']['href'] == $router_item['tab_root_href'] && $item['link']['href'] != current_path()) {
+      if ($item['link']['href'] != current_path()) {
         $l['attributes']['class'][] = 'active';
       }
       // Keyed with the unique mlid to generate classes in links.html.twig.
@@ -1830,22 +1745,6 @@ function menu_local_tasks($level = 0) {
       }
     }
 
-    // @todo Remove when all local tasks/actions are converted to plugins.
-    $router_item = menu_get_item();
-    // If this router item points to its parent, start from the parents to
-    // compute tabs and actions.
-    if ($router_item && ($router_item['type'] & MENU_LINKS_TO_PARENT)) {
-      $router_item = menu_get_item($router_item['tab_parent_href']);
-    }
-    // If we failed to fetch a router item or the current user doesn't have
-    // access to it, don't bother computing the tabs.
-    if ((!$route_name && !$router_item) || ($router_item && !$router_item['access'])) {
-      return $empty;
-    }
-    if ($router_item) {
-      _menu_get_legacy_tasks($router_item, $data, $root_path);
-    }
-
     // Allow modules to dynamically add further tasks.
     $module_handler = \Drupal::moduleHandler();
     foreach ($module_handler->getImplementations('menu_local_tasks') as $module) {
@@ -1870,170 +1769,6 @@ function menu_local_tasks($level = 0) {
 }
 
 /**
- * Finds legacy local tasks/actions.
- *
- * @param array $router_item
- *   The current router item.
- * @param array $data
- *   An associative array of local tasks/actions.
- * @param string $root_path
- *
- * @deprecated Remove once all local tasks/actions are converted to plugins.
- */
-function _menu_get_legacy_tasks($router_item, &$data, &$root_path) {
-  // Get all tabs (also known as local tasks) and the root page.
-  $result = db_select('menu_router', NULL, array('fetch' => PDO::FETCH_ASSOC))
-    ->fields('menu_router')
-    ->condition('tab_root', $router_item['tab_root'])
-    ->orderBy('weight')
-    ->orderBy('title')
-    ->execute();
-  $map = $router_item['original_map'];
-  $children = array();
-  $tasks = array();
-  $root_path = $router_item['path'];
-
-  foreach ($result as $item) {
-    _menu_translate($item, $map, TRUE);
-    if ($item['tab_parent']) {
-      // All tabs, but not the root page.
-      $children[$item['tab_parent']][$item['path']] = $item;
-    }
-    // Store the translated item for later use.
-    $tasks[$item['path']] = $item;
-  }
-
-  // Find all tabs below the current path.
-  $path = $router_item['path'];
-  // Tab parenting may skip levels, so the number of parts in the path may not
-  // equal the depth. Thus we use the $depth counter (offset by 1000 for ksort).
-  $depth = 1001;
-  $tabs = array();
-  $actions = array();
-  while (isset($children[$path])) {
-    $tabs_current = array();
-    $actions_current = array();
-    $next_path = '';
-    $tab_count = 0;
-    $action_count = 0;
-    foreach ($children[$path] as $item) {
-      // Local tasks can be normal items too, so bitmask with
-      // MENU_IS_LOCAL_TASK before checking.
-      if (!($item['type'] & MENU_IS_LOCAL_TASK)) {
-        // This item is not a tab, skip it.
-        continue;
-      }
-      if ($item['access']) {
-        $link = $item;
-        // The default task is always active. As tabs can be normal items
-        // too, so bitmask with MENU_LINKS_TO_PARENT before checking.
-        if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
-          // Find the first parent which is not a default local task or action.
-          for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
-          // Use the path of the parent instead.
-          $link['href'] = $tasks[$p]['href'];
-          // Mark the link as active, if the current path happens to be the
-          // path of the default local task itself (i.e., instead of its
-          // tab_parent_href or tab_root_href). Normally, links for default
-          // local tasks link to their parent, but the path of default local
-          // tasks can still be accessed directly, in which case this link
-          // would not be marked as active, since l() only compares the href
-          // with current_path().
-          if ($link['href'] != current_path()) {
-            $link['localized_options']['attributes']['class'][] = 'active';
-          }
-          $tabs_current[$link['href']] = array(
-            '#theme' => 'menu_local_task',
-            '#link' => $link,
-            '#active' => TRUE,
-            '#weight' => isset($link['weight']) ? $link['weight'] : NULL,
-          );
-          $next_path = $item['path'];
-          $tab_count++;
-        }
-        else {
-          $tabs_current[$link['href']] = array(
-            '#theme' => 'menu_local_task',
-            '#link' => $link,
-            '#weight' => isset($link['weight']) ? $link['weight'] : NULL,
-          );
-          $tab_count++;
-        }
-      }
-    }
-    $path = $next_path;
-    $tabs[$depth] = $tabs_current;
-    $actions = array_merge($actions, $actions_current);
-    $depth++;
-  }
-  $data['actions'] = $actions;
-  // Find all tabs at the same level or above the current one.
-  $parent = $router_item['tab_parent'];
-  $path = $router_item['path'];
-  $current = $router_item;
-  $depth = 1000;
-  while (isset($children[$parent])) {
-    $tabs_current = array();
-    $next_path = '';
-    $next_parent = '';
-    $count = 0;
-    foreach ($children[$parent] as $item) {
-      if ($item['access']) {
-        $count++;
-        $link = $item;
-        // Local tasks can be normal items too, so bitmask with
-        // MENU_LINKS_TO_PARENT before checking.
-        if (($item['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT) {
-          // Find the first parent which is not a default local task.
-          for ($p = $item['tab_parent']; ($tasks[$p]['type'] & MENU_LINKS_TO_PARENT) == MENU_LINKS_TO_PARENT; $p = $tasks[$p]['tab_parent']);
-          // Use the path of the parent instead.
-          $link['href'] = $tasks[$p]['href'];
-          if ($item['path'] == $router_item['path']) {
-            $root_path = $tasks[$p]['path'];
-          }
-        }
-        // We check for the active tab.
-        if ($item['path'] == $path) {
-          // Mark the link as active, if the current path is a (second-level)
-          // local task of a default local task. Since this default local task
-          // links to its parent, l() will not mark it as active, as it only
-          // compares the link's href to current_path().
-          if ($link['href'] != current_path()) {
-            $link['localized_options']['attributes']['class'][] = 'active';
-          }
-          $tabs_current[$link['href']] = array(
-            '#theme' => 'menu_local_task',
-            '#link' => $link,
-            '#active' => TRUE,
-            '#weight' => isset($link['weight']) ? $link['weight'] : NULL,
-          );
-          $next_path = $item['tab_parent'];
-          if (isset($tasks[$next_path])) {
-            $next_parent = $tasks[$next_path]['tab_parent'];
-          }
-        }
-        else {
-          $tabs_current[$link['href']] = array(
-            '#theme' => 'menu_local_task',
-            '#link' => $link,
-            '#weight' => isset($link['weight']) ? $link['weight'] : NULL,
-          );
-        }
-      }
-    }
-    $path = $next_path;
-    $parent = $next_parent;
-    $tabs[$depth] = $tabs_current;
-    $depth--;
-  }
-  // Sort by depth.
-  ksort($tabs);
-  // Remove the depth, we are interested only in their relative placement.
-  $tabs = array_values($tabs);
-  $data['tabs'] += $tabs;
-}
-
-/**
  * Returns the rendered local tasks at the top level.
  */
 function menu_primary_local_tasks() {
@@ -2562,6 +2297,10 @@ function menu_link_get_defaults() {
  * Builds menu links for the items returned from hook_menu_link_defaults().
  */
 function menu_link_rebuild_defaults() {
+  // Ensure that all configuration used to build the menu items are loaded
+  // without overrides.
+  $old_state = \Drupal::configFactory()->getOverrideState();
+  \Drupal::configFactory()->setOverrideState(FALSE);
   $module_handler = \Drupal::moduleHandler();
   if (!$module_handler->moduleExists('menu_link')) {
     // The Menu link module may not be available during install, so rebuild
@@ -2668,6 +2407,7 @@ function menu_link_rebuild_defaults() {
   if ($result) {
     menu_link_delete_multiple($result, TRUE);
   }
+  \Drupal::configFactory()->setOverrideState($old_state);
 }
 
 /**
diff --git a/core/includes/path.inc b/core/includes/path.inc
index 533dcd9..00cbe3f 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -224,10 +224,6 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) {
       $route_name = $item['route_name'];
     }
   }
-  else {
-    $item = menu_get_item($path);
-    $route_name = $item['route_name'];
-  }
   // Check the new routing system.
   if (!empty($route_name)) {
     $map = array();
@@ -239,5 +235,5 @@ function drupal_valid_path($path, $dynamic_allowed = FALSE) {
     $item['access'] = menu_item_route_access($route, $path, $map, $request);
   }
   $menu_admin = FALSE;
-  return $item && $item['access'];
+  return !empty($item['access']);
 }
diff --git a/core/lib/Drupal/Core/Menu/LocalTaskManager.php b/core/lib/Drupal/Core/Menu/LocalTaskManager.php
index a436d57..fde294f 100644
--- a/core/lib/Drupal/Core/Menu/LocalTaskManager.php
+++ b/core/lib/Drupal/Core/Menu/LocalTaskManager.php
@@ -18,6 +18,7 @@
 use Drupal\Core\Plugin\Discovery\ContainerDerivativeDiscoveryDecorator;
 use Drupal\Core\Plugin\Discovery\YamlDiscovery;
 use Drupal\Core\Plugin\Factory\ContainerFactory;
+use Drupal\Core\Routing\RouteBuilderInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
 use Drupal\Core\Session\AccountInterface;
 use Symfony\Component\HttpFoundation\Request;
@@ -84,6 +85,13 @@ class LocalTaskManager extends DefaultPluginManager {
   protected $routeProvider;
 
   /**
+   * The route builder.
+   *
+   * @var \Drupal\Core\Routing\RouteBuilderInterface
+   */
+  protected $routeBuilder;
+
+  /**
    * The access manager.
    *
    * @var \Drupal\Core\Access\AccessManager
@@ -106,6 +114,8 @@ class LocalTaskManager extends DefaultPluginManager {
    *   The request object to use for building titles and paths for plugin instances.
    * @param \Drupal\Core\Routing\RouteProviderInterface $route_provider
    *   The route provider to load routes by name.
+   * @param \Drupal\Core\Routing\RouteBuilderInterface $route_builder
+   *   The route builder.
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
    *   The module handler.
    * @param \Drupal\Core\Cache\CacheBackendInterface $cache
@@ -117,13 +127,14 @@ class LocalTaskManager extends DefaultPluginManager {
    * @param \Drupal\Core\Session\AccountInterface $account
    *   The current user.
    */
-  public function __construct(ControllerResolverInterface $controller_resolver, Request $request, RouteProviderInterface $route_provider, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManager $language_manager, AccessManager $access_manager, AccountInterface $account) {
+  public function __construct(ControllerResolverInterface $controller_resolver, Request $request, RouteProviderInterface $route_provider, RouteBuilderInterface $route_builder, ModuleHandlerInterface $module_handler, CacheBackendInterface $cache, LanguageManager $language_manager, AccessManager $access_manager, AccountInterface $account) {
     $this->discovery = new YamlDiscovery('local_tasks', $module_handler->getModuleDirectories());
     $this->discovery = new ContainerDerivativeDiscoveryDecorator($this->discovery);
     $this->factory = new ContainerFactory($this);
     $this->controllerResolver = $controller_resolver;
     $this->request = $request;
     $this->routeProvider = $route_provider;
+    $this->routeBuilder = $route_builder;
     $this->accessManager = $access_manager;
     $this->account = $account;
     $this->alterInfo($module_handler, 'local_tasks');
@@ -177,6 +188,9 @@ public function getLocalTasksForRoute($route_name) {
         $children = $cache->data['children'];
       }
       else {
+        // Maybe some code asked to rebuild the routes, so rebuild the router
+        // as we rely on having proper existing routes in dynamic local tasks.
+        $this->routeBuilder->rebuildIfNeeded();
         $definitions = $this->getDefinitions();
         // We build the hierarchy by finding all tabs that should
         // appear on the current route.
diff --git a/core/modules/block/custom_block/custom_block.local_actions.yml b/core/modules/block/custom_block/custom_block.local_actions.yml
index b12329c..e3b57c6 100644
--- a/core/modules/block/custom_block/custom_block.local_actions.yml
+++ b/core/modules/block/custom_block/custom_block.local_actions.yml
@@ -10,5 +10,5 @@ custom_block_add_action:
   appears_on:
     - block.admin_display
     - block.admin_display_theme
+    - custom_block.list
   class: \Drupal\custom_block\Plugin\Menu\LocalAction\CustomBlockAddLocalAction
-
diff --git a/core/modules/block/custom_block/custom_block.module b/core/modules/block/custom_block/custom_block.module
index cdf90c7..4b16ed1 100644
--- a/core/modules/block/custom_block/custom_block.module
+++ b/core/modules/block/custom_block/custom_block.module
@@ -38,25 +38,6 @@ function custom_block_help($path, $arg) {
 }
 
 /**
- * Implements hook_menu_local_tasks().
- */
-function custom_block_menu_local_tasks(&$data, $route_name) {
-  if ($route_name == 'custom_block.list') {
-    // @todo Move to a LocalAction plugin when https://drupal.org/node/2045267
-    //   allows local actions to work with query strings.
-    $item = menu_get_item('block/add');
-    if ($item['access']) {
-      // Add a destination parameter.
-      $item['localized_options']['query']['destination'] = 'admin/structure/block/custom-blocks';
-      $data['actions']['block/add'] = array(
-        '#theme' => 'menu_local_action',
-        '#link' => $item,
-      );
-    }
-  }
-}
-
-/**
  * Implements hook_menu().
  */
 function custom_block_menu() {
diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php
index c2b773a..1f4d86f 100644
--- a/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php
+++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Plugin/Menu/LocalAction/CustomBlockAddLocalAction.php
@@ -8,6 +8,7 @@
 namespace Drupal\custom_block\Plugin\Menu\LocalAction;
 
 use Drupal\Core\Menu\LocalActionDefault;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -24,6 +25,10 @@ public function getOptions(Request $request) {
     if ($request->attributes->has('theme')) {
       $options['query']['theme'] = $request->attributes->get('theme');
     }
+    // Adds a destination on custom block listing.
+    if ($request->attributes->get(RouteObjectInterface::ROUTE_NAME) == 'custom_block.list') {
+      $options['query']['destination'] = 'admin/structure/block/custom-blocks';
+    }
     return $options;
   }
 
diff --git a/core/modules/node/node.local_actions.yml b/core/modules/node/node.local_actions.yml
index feb2028..af8a56d 100644
--- a/core/modules/node/node.local_actions.yml
+++ b/core/modules/node/node.local_actions.yml
@@ -3,3 +3,8 @@ node.type_add:
   title: 'Add content type'
   appears_on:
     - node.overview_types
+node.add_page:
+  route_name: node.add_page
+  title: 'Add content'
+  appears_on:
+    - node.content_overview
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index c1b67b0..07d32cb 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -1009,23 +1009,6 @@ function node_menu_link_defaults() {
 }
 
 /**
- * Implements hook_menu_local_tasks().
- */
-function node_menu_local_tasks(&$data, $route_name) {
-  // Add action link to 'node/add' on 'admin/content' page.
-  // @todo Switch to inspecting route name in https://drupal.org/node/2021161.
-  if (current_path() == 'admin/content') {
-    $item = menu_get_item('node/add');
-    if ($item['access']) {
-      $data['actions'][] = array(
-        '#theme' => 'menu_local_action',
-        '#link' => $item,
-      );
-    }
-  }
-}
-
-/**
  * Title callback: Displays the node's title.
  *
  * @param \Drupal\node\NodeInterface $node
diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module
index b520e08..2e333e2 100644
--- a/core/modules/shortcut/shortcut.module
+++ b/core/modules/shortcut/shortcut.module
@@ -329,7 +329,7 @@ function shortcut_valid_link($path) {
   }
 
   // An empty path is valid too and will be converted to <front>.
-  return (!url_is_external($path) && (\Drupal::service('router.route_provider')->getRoutesByPattern('/' . $path)->count() > 0 || menu_get_item($path))) || empty($path) || $path == '<front>';
+  return (!url_is_external($path) && (\Drupal::service('router.route_provider')->getRoutesByPattern('/' . $path)->count() > 0)) || empty($path) || $path == '<front>';
 }
 
 /**
diff --git a/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php b/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
index a090c67..704a078 100644
--- a/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
+++ b/core/modules/system/lib/Drupal/system/Form/ModulesListForm.php
@@ -8,6 +8,9 @@
 namespace Drupal\system\Form;
 
 use Drupal\Component\Utility\Unicode;
+use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Entity\Query\QueryFactory;
+use Drupal\Core\Entity\Query\QueryFactoryInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Form\FormBase;
 use Drupal\Core\KeyValueStore\KeyValueStoreExpirableInterface;
@@ -39,13 +42,29 @@ class ModulesListForm extends FormBase {
   protected $keyValueExpirable;
 
   /**
+   * The entity manager.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface
+   */
+  protected $entityManager;
+
+  /**
+   * The query factory.
+   *
+   * @var \Drupal\Core\Entity\Query\QueryFactory
+   */
+  protected $queryFactory;
+
+  /**
    * {@inheritdoc}
    */
   public static function create(ContainerInterface $container) {
     return new static(
       $container->get('module_handler'),
       $container->get('keyvalue.expirable')->get('module_list'),
-      $container->get('access_manager')
+      $container->get('access_manager'),
+      $container->get('entity.manager'),
+      $container->get('entity.query')
     );
   }
 
@@ -58,11 +77,17 @@ public static function create(ContainerInterface $container) {
    *   The key value expirable factory.
    * @param \Drupal\Core\Access\AccessManager $access_manager
    *   Access manager.
+   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
+   *   The entity manager.
+   * @param \Drupal\Core\Entity\Query\QueryFactory $query_factory
+   *   The entity query factory.
    */
-  public function __construct(ModuleHandlerInterface $module_handler, KeyValueStoreExpirableInterface $key_value_expirable, AccessManager $access_manager) {
+  public function __construct(ModuleHandlerInterface $module_handler, KeyValueStoreExpirableInterface $key_value_expirable, AccessManager $access_manager, EntityManagerInterface $entity_manager, QueryFactory $query_factory) {
     $this->moduleHandler = $module_handler;
     $this->keyValueExpirable = $key_value_expirable;
     $this->accessManager = $access_manager;
+    $this->entityManager = $entity_manager;
+    $this->queryFactory = $query_factory;
   }
 
   /**
@@ -199,7 +224,11 @@ protected function buildRow(array $modules, $module, $distribution) {
     $row['links']['configure'] = array();
     if ($module->status && isset($module->info['configure'])) {
       if ($this->accessManager->checkNamedRoute($module->info['configure'], array(), \Drupal::currentUser())) {
-        $item = menu_get_item(trim($this->url($module->info['configure']), '/'));
+        $result = $this->queryFactory->get('menu_link')
+          ->condition('route_name', $module->info['configure'])
+          ->execute();
+        $menu_items = $this->entityManager->getStorageController('menu_link')->loadMultiple($result);
+        $item = reset($menu_items);
         $row['links']['configure'] = array(
           '#type' => 'link',
           '#title' => $this->t('Configure'),
diff --git a/core/modules/system/lib/Drupal/system/SystemManager.php b/core/modules/system/lib/Drupal/system/SystemManager.php
index fd8f77e..eb14718 100644
--- a/core/modules/system/lib/Drupal/system/SystemManager.php
+++ b/core/modules/system/lib/Drupal/system/SystemManager.php
@@ -8,9 +8,11 @@
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Drupal\Core\Database\Connection;
 use Drupal\Core\Extension\ModuleHandlerInterface;
+use Symfony\Component\HttpFoundation\Request;
 
 /**
  * System Manager Service.
@@ -61,6 +63,13 @@ class SystemManager {
   const REQUIREMENT_ERROR = 2;
 
   /**
+   * The request object.
+   *
+   * @var \Symfony\Component\HttpFoundation\Request
+   */
+  protected $request;
+
+  /**
    * Constructs a SystemManager object.
    *
    * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
@@ -77,6 +86,16 @@ public function __construct(ModuleHandlerInterface $module_handler, Connection $
   }
 
   /**
+   * Sets the current request.
+   *
+   * @param \Symfony\Component\HttpFoundation\Request $request
+   *   The request object.
+   */
+  public function setRequest(Request $request) {
+    $this->request = $request;
+  }
+
+  /**
    * Checks for requirement severity.
    *
    * @return boolean
@@ -160,7 +179,9 @@ public function getMaxSeverity(&$requirements) {
    *   A render array suitable for drupal_render.
    */
   public function getBlockContents() {
-    $item = menu_get_item();
+    $route_name = $this->request->attributes->get(RouteObjectInterface::ROUTE_NAME);
+    $items = $this->menuLinkStorage->loadByProperties(array('route_name' => $route_name));
+    $item = reset($items);
     if ($content = $this->getAdminBlock($item)) {
       $output = array(
         '#theme' => 'admin_block_content',
@@ -185,14 +206,6 @@ public function getBlockContents() {
    *   An array of menu items, as expected by theme_admin_block_content().
    */
   public function getAdminBlock($item) {
-    // If we are calling this function for a menu item that corresponds to a
-    // local task (for example, admin/tasks), then we want to retrieve the
-    // parent item's child links, not this item's (since this item won't have
-    // any).
-    if ($item['tab_root'] != $item['path']) {
-      $item = menu_get_item($item['tab_root_href']);
-    }
-
     if (!isset($item['mlid'])) {
       $menu_links = $this->menuLinkStorage->loadByProperties(array('link_path' => $item['path'], 'module' => 'system'));
       if ($menu_links) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/LocalTasksTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/LocalTasksTest.php
index bf51856..92de333 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/LocalTasksTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/LocalTasksTest.php
@@ -25,96 +25,6 @@ public static function getInfo() {
   }
 
   /**
-   * Tests appearance of local tasks.
-   *
-   * @see menu_test_menu()
-   * @see menu_test_menu_local_tasks()
-   * @see menu_test_menu_local_tasks_alter()
-   */
-  function testLocalTasks() {
-    // Verify that there is no local tasks markup if none are defined in the
-    // router and no module adds any dynamically.
-    $this->drupalGet('menu-test/tasks/empty');
-    $this->assertNoRaw('tabs');
-    $this->drupalGet('menu-test/tasks/default');
-    $this->assertNoRaw('tabs');
-
-    // Verify that local tasks appear as defined in the router.
-    $this->drupalGet('menu-test/tasks/tasks');
-    $this->assertLocalTasks(array(
-      // MENU_DEFAULT_LOCAL_TASK is expected to get a default weight of -10
-      // (without having to define it manually), so it should appear first,
-      // despite that its label is "View".
-      'menu-test/tasks/tasks',
-      'menu-test/tasks/tasks/edit',
-      'menu-test/tasks/tasks/settings',
-    ));
-
-    // Enable addition of tasks in menu_test_menu_local_tasks().
-    \Drupal::config('menu_test.settings')->set('tasks.add', TRUE)->save();
-
-    // Verify that the added tasks appear even if there are no tasks normally.
-    $this->drupalGet('menu-test/tasks/empty');
-    $this->assertLocalTasks(array(
-      'task/foo',
-      'task/bar',
-    ));
-
-    // Verify that the default local task appears before the added tasks.
-    $this->drupalGet('menu-test/tasks/default');
-    $this->assertLocalTasks(array(
-      'menu-test/tasks/default',
-      'task/foo',
-      'task/bar',
-    ));
-
-    // Verify that the added tasks appear within normal tasks.
-    $this->drupalGet('menu-test/tasks/tasks');
-    $this->assertLocalTasks(array(
-      'menu-test/tasks/tasks',
-      // The Edit task defines no weight, which is expected to sort as 0.
-      'menu-test/tasks/tasks/edit',
-      'task/foo',
-      'task/bar',
-      'menu-test/tasks/tasks/settings',
-    ));
-
-    // Enable manipulation of tasks in menu_test_menu_local_tasks_alter().
-    \Drupal::config('menu_test.settings')->set('tasks.alter', TRUE)->save();
-
-    // Verify that the added tasks appear even if there are no tasks normally.
-    $this->drupalGet('menu-test/tasks/empty');
-    $this->assertLocalTasks(array(
-      'task/bar',
-      'task/foo',
-    ));
-    $this->assertNoText('Show it');
-    $this->assertText('Advanced settings');
-
-    // Verify that the default local task appears before the added tasks.
-    $this->drupalGet('menu-test/tasks/default');
-    $this->assertLocalTasks(array(
-      'menu-test/tasks/default',
-      'task/bar',
-      'task/foo',
-    ));
-    $this->assertText('Show it');
-    $this->assertText('Advanced settings');
-
-    // Verify that the added tasks appear within normal tasks.
-    $this->drupalGet('menu-test/tasks/tasks');
-    $this->assertLocalTasks(array(
-      'menu-test/tasks/tasks',
-      'menu-test/tasks/tasks/edit',
-      'task/bar',
-      'menu-test/tasks/tasks/settings',
-      'task/foo',
-    ));
-    $this->assertText('Show it');
-    $this->assertText('Advanced settings');
-  }
-
-  /**
    * Asserts local tasks in the page output.
    *
    * @param array $hrefs
diff --git a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
index 7cb4df5..418c451 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Menu/MenuRouterRebuildTest.php
@@ -52,8 +52,9 @@ public function testMenuRouterRebuildContext() {
     menu_router_rebuild();
 
     // Check that the language context was not used for building the menu item.
-    $menu_item = menu_get_item('menu-test/context');
-    $this->assertTrue($menu_item['title'] == 'English', 'Config context overrides are ignored when rebuilding menu router items.');
+    $menu_items = \Drupal::entityManager()->getStorageController('menu_link')->loadByProperties(array('route_name' => 'menu_test.context'));
+    $menu_item = reset($menu_items);
+    $this->assertTrue($menu_item['link_title'] == 'English', 'Config context overrides are ignored when rebuilding menu router items.');
   }
 
 }
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 59dfce0..b51591f 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -478,8 +478,6 @@ function hook_page_build(&$page) {
  *   The originally passed path, for which $router_item is responsible.
  * @param $original_map
  *   The path argument map, as contained in $path.
- *
- * @see menu_get_item()
  */
 function hook_menu_get_item_alter(&$router_item, $path, $original_map) {
   // When retrieving the router item for the current path...
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 5e23103..3215949 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2927,14 +2927,23 @@ function system_get_module_admin_tasks($module, $info) {
 
   // Append link for permissions.
   if (\Drupal::moduleHandler()->implementsHook($module, 'permission')) {
-    $item = menu_get_item('admin/people/permissions');
-    if (!empty($item['access'])) {
-      $item['link_path'] = $item['href'];
-      $item['title'] = t('Configure @module permissions', array('@module' => $info['name']));
-      unset($item['description']);
-      $item['localized_options']['fragment'] = 'module-' . $module;
-      $item = entity_create('menu_link', $item);
-      $admin_tasks["admin/people/permissions#module-$module"] = $item;
+    /** @var \Drupal\Core\Access\AccessManager $access_manager */
+    $access_manager = \Drupal::service('access_manager');
+    /** @var \Drupal\menu_link\MenuLinkStorageControllerInterface $menu_link_storage_controller */
+    $menu_link_storage_controller = \Drupal::entityManager()
+      ->getStorageController('menu_link');
+    if ($access_manager->checkNamedRoute('user.admin_permissions', array(), \Drupal::currentUser())) {
+      $path = \Drupal::urlGenerator()
+        ->getPathFromRoute('user.admin_permissions');
+      $options = array();
+      $options['fragment'] = 'module-' . $module;
+      $menu_link = $menu_link_storage_controller->create(array(
+        'route_name' => 'user.admin_permissions',
+        'link_path' => $path,
+        'title' => t('Configure @module permissions', array('@module' => $info['name'])),
+        'localized_options' => $options
+      ));
+      $admin_tasks["user.admin.people.permissions.$module"] = $menu_link;
     }
   }
 
diff --git a/core/modules/system/system.services.yml b/core/modules/system/system.services.yml
index 179bb27..8eebd29 100644
--- a/core/modules/system/system.services.yml
+++ b/core/modules/system/system.services.yml
@@ -6,6 +6,8 @@ services:
   system.manager:
     class: Drupal\system\SystemManager
     arguments: ['@module_handler', '@database', '@entity.manager']
+    calls:
+      - [setRequest, ['@?request=']]
   system.breadcrumb.default:
     class: Drupal\system\PathBasedBreadcrumbBuilder
     arguments: ['@request', '@entity.manager', '@access_manager', '@router', '@path_processor_manager', '@config.factory',  '@title_resolver']
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.local_tasks.yml b/core/modules/system/tests/modules/menu_test/menu_test.local_tasks.yml
index eaa9aae..f4faf95 100644
--- a/core/modules/system/tests/modules/menu_test/menu_test.local_tasks.yml
+++ b/core/modules/system/tests/modules/menu_test/menu_test.local_tasks.yml
@@ -67,3 +67,18 @@ menu_test.tasks_settings_tab:
   title: 'Settings'
   weight: 100
   base_route: menu_test.tasks_tasks
+
+menu_test.router_test1:
+  route_name: menu_test.router_test1
+  title: 'Local task A'
+  base_route: menu_test.router_test1
+
+menu_test.router_test2:
+  route_name: menu_test.router_test2
+  title: 'Local task B'
+  base_route: menu_test.router_test1
+
+menu_test.router_test3:
+  route_name: menu_test.router_test3
+  title: 'Local task C'
+  base_route: menu_test.router_test1
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.module b/core/modules/system/tests/modules/menu_test/menu_test.module
index 5eb3098..30dffdc 100644
--- a/core/modules/system/tests/modules/menu_test/menu_test.module
+++ b/core/modules/system/tests/modules/menu_test/menu_test.module
@@ -88,122 +88,6 @@ function menu_test_menu() {
     'title' => 'Menu test root',
     'route_name' => 'menu_test.menu_test',
   );
-  $items['menu-test/hidden'] = array(
-    'title' => 'Hidden test root',
-    'route_name' => 'menu_test.hidden',
-  );
-
-  // Hidden tests; one dynamic argument.
-  $items['menu-test/hidden/menu'] = array(
-    'title' => 'Menus',
-    'route_name' => 'menu_test.hidden_menu',
-  );
-  $items['menu-test/hidden/menu/list'] = array(
-    'title' => 'List menus',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-  );
-  $items['menu-test/hidden/menu/settings'] = array(
-    'title' => 'Settings',
-    'route_name' => 'menu_test.hidden_menu_settings',
-    'type' => MENU_LOCAL_TASK,
-    'weight' => 5,
-  );
-  $items['menu-test/hidden/menu/manage/%menu'] = array(
-    'title' => 'Customize menu',
-    'route_name' => 'menu_test.hidden_manage',
-  );
-  $items['menu-test/hidden/menu/manage/%menu/list'] = array(
-    'title' => 'List links',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'context' => MENU_CONTEXT_PAGE,
-  );
-  $items['menu-test/hidden/menu/manage/%menu/edit'] = array(
-    'title' => 'Edit menu',
-    'route_name' => 'menu_test.hidden_manage_edit',
-    'type' => MENU_LOCAL_TASK,
-    'context' => MENU_CONTEXT_PAGE,
-  );
-  $items['menu-test/hidden/menu/manage/%menu/delete'] = array(
-    'title' => 'Delete menu',
-    'route_name' => 'menu_test.hidden_manage_delete',
-  );
-
-  // Hidden tests; two dynamic arguments.
-  $items['menu-test/hidden/block'] = array(
-    'title' => 'Blocks',
-    'route_name' => 'menu_test.hidden_block',
-  );
-  $items['menu-test/hidden/block/list'] = array(
-    'title' => 'List',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-  );
-  $items['menu-test/hidden/block/manage/%/%'] = array(
-    'title' => 'Configure block',
-    'route_name' => 'menu_test.hidden_block_configure',
-  );
-  $items['menu-test/hidden/block/manage/%/%/delete'] = array(
-    'title' => 'Delete block',
-    'route_name' => 'menu_test.hidden_block_delete',
-    'type' => MENU_LOCAL_TASK,
-    'context' => MENU_CONTEXT_NONE,
-  );
-
-  // Breadcrumbs tests.
-  // @see \Drupal\system\Tests\Menu\BreadcrumbTest
-  // Local tasks: Second level below default local task.
-  $items['menu-test/breadcrumb/tasks'] = array(
-    'title' => 'Breadcrumbs test: Local tasks',
-    'route_name' => 'menu_test.breadcrumbs',
-  );
-  $items['menu-test/breadcrumb/tasks/first'] = array(
-    'title' => 'First',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'route_name' => 'menu_test.breadcrumbs_first',
-  );
-  $items['menu-test/breadcrumb/tasks/second'] = array(
-    'title' => 'Second',
-    'type' => MENU_LOCAL_TASK,
-    'route_name' => 'menu_test.breadcrumbs_second',
-  );
-  $items['menu-test/breadcrumb/tasks/first/first'] = array(
-    'title' => 'First first',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'route_name' => 'menu_test.breadcrumbs_first_first',
-  );
-  $items['menu-test/breadcrumb/tasks/first/second'] = array(
-    'title' => 'First second',
-    'type' => MENU_LOCAL_TASK,
-    'route_name' => 'menu_test.breadcrumbs_first_second',
-  );
-  $items['menu-test/breadcrumb/tasks/second/first'] = array(
-    'title' => 'Second first',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-    'route_name' => 'menu_test.breadcrumbs_second_first',
-  );
-  $items['menu-test/breadcrumb/tasks/second/second'] = array(
-    'title' => 'Second second',
-    'type' => MENU_LOCAL_TASK,
-    'route_name' => 'menu_test.breadcrumbs_second_second',
-  );
-
-  // Menu local tasks tests.
-  // @see \Drupal\system\Tests\Menu\TrailTest
-  $items['menu-test/tasks'] = array(
-    'title' => 'Local tasks',
-    'route_name' => 'menu_test.tasks',
-  );
-  $items['menu-test/tasks/empty'] = array(
-    'title' => 'Empty',
-    'route_name' => 'menu_test.tasks_empty',
-  );
-  $items['menu-test/tasks/default'] = array(
-    'title' => 'Default only',
-    'route_name' => 'menu_test.tasks_default',
-  );
-  $items['menu-test/tasks/tasks'] = array(
-    'title' => 'With tasks',
-    'route_name' => 'menu_test.tasks_tasks',
-  );
 
   // Menu trail tests.
   // @see MenuTrailTestCase
@@ -241,28 +125,6 @@ function menu_test_menu() {
     'route_name' => 'menu_test.title_test_case3',
   );
 
-  // Parent page for controller-based local tasks.
-  $items['foo/%'] = array(
-    'title' => 'Controller-based local tasks',
-    'route_name' => 'menu_test.router_test1',
-  );
-  // Controller-based local task.
-  $items['foo/%/a'] = array(
-    'title' => 'Local task A',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-  );
-  // Controller-based local task.
-  $items['foo/%/b'] = array(
-    'title' => 'Local task B',
-    'route_name' => 'menu_test.router_test2',
-    'type' => MENU_LOCAL_TASK,
-  );
-  $items['foo/%/c'] = array(
-    'title' => 'Local task C',
-    'route_name' => 'menu_test.router_test3',
-    'type' => MENU_LOCAL_TASK,
-  );
-
   $items['menu-test-local-action'] = array(
     'title' => 'Local action parent',
     'route_name' => 'menu_test.local_action1',
@@ -411,6 +273,11 @@ function menu_test_menu_link_defaults() {
     'link_title' => 'Bike sheds full of blue smurfs',
     'route_name' => 'menu_test.title_test_case3',
   );
+  $items['menu_test.context'] = array(
+    'link_title' => \Drupal::config('menu_test.menu_item')->get('title'),
+    'route_name' => 'menu_test.context',
+  );
+
   return $items;
 }
 
diff --git a/core/modules/system/tests/modules/menu_test/menu_test.routing.yml b/core/modules/system/tests/modules/menu_test/menu_test.routing.yml
index 2c87481..637be3c 100644
--- a/core/modules/system/tests/modules/menu_test/menu_test.routing.yml
+++ b/core/modules/system/tests/modules/menu_test/menu_test.routing.yml
@@ -262,55 +262,6 @@ menu_test.hidden_menu:
     _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
   requirements:
     _access: 'TRUE'
-
-menu_test.hidden_menu_add:
-  path: '/menu-test/hidden/menu/add'
-  defaults:
-    _title: 'Add menu'
-    _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.hidden_menu_settings:
-  path: '/menu-test/hidden/menu/settings'
-  defaults:
-    _title: 'Settings'
-    _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.hidden_manage:
-  path: '/menu-test/hidden/menu/manage/{menu}'
-  defaults:
-    _title: 'Customize menu'
-    _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.hidden_manage_add:
-  path: '/menu-test/hidden/menu/manage/{menu}/add'
-  defaults:
-    _title: 'Add link'
-    _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.hidden_manage_edit:
-  path: '/menu-test/hidden/menu/manage/{menu}/edit'
-  defaults:
-    _title: 'Edit menu'
-    _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.hidden_manage_delete:
-  path: '/menu-test/hidden/menu/manage/{menu}/delete'
-  defaults:
-    _title: 'Delete menu'
-    _content: '\Drupal\test_page_test\Controller\TestPageTestController::testPage'
-  requirements:
-    _access: 'TRUE'
-
 menu_test.hidden_block:
   path: '/menu-test/hidden/block'
   defaults:
@@ -343,110 +294,6 @@ menu_test.hidden_block_delete:
   requirements:
     _access: 'TRUE'
 
-menu_test.breadcrumbs:
-  path: '/menu-test/breadcrumb/tasks'
-  defaults:
-    _title: 'Breadcrumbs test: Local tasks'
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.breadcrumbs_first:
-  path: '/menu-test/breadcrumb/tasks/first'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.breadcrumbs_second:
-  path: '/menu-test/breadcrumb/tasks/second'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.breadcrumbs_first_first:
-  path: '/menu-test/breadcrumb/tasks/first/first'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.breadcrumbs_first_second:
-  path: '/menu-test/breadcrumb/tasks/first/second'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.breadcrumbs_second_first:
-  path: '/menu-test/breadcrumb/tasks/second/first'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.breadcrumbs_second_second:
-  path: '/menu-test/breadcrumb/tasks/second/second'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks:
-  path: '/menu-test/tasks'
-  defaults:
-    _title: 'Local tasks'
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks_empty:
-  path: '/menu-test/tasks/empty'
-  defaults:
-    _title: 'Empty'
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks_default:
-  path: '/menu-test/tasks/default'
-  defaults:
-    _title: 'Default only'
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks_tasks:
-  path: '/menu-test/tasks/tasks'
-  defaults:
-    _title: 'With tasks'
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks_tasks:
-  path: '/menu-test/tasks/tasks'
-  defaults:
-    _title: 'With tasks'
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks_edit:
-  path: '/menu-test/tasks/tasks/edit'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
-menu_test.tasks_settings:
-  path: '/menu-test/tasks/tasks/settings'
-  defaults:
-    _content: '\Drupal\menu_test\Controller\MenuTestController::menuTestCallback'
-  requirements:
-    _access: 'TRUE'
-
 menu_test.custom_403:
   path: '/menu-test/custom-403-page'
   defaults:
diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTest.php
index d590e06..f8dea85 100644
--- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTest.php
+++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskIntegrationTest.php
@@ -73,6 +73,16 @@ protected function getLocalTaskManager($module_dirs, $route_name, $route_params)
     $property->setAccessible(TRUE);
     $property->setValue($manager, $accessManager);
 
+    $route_provider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
+    $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'routeProvider');
+    $property->setAccessible(TRUE);
+    $property->setValue($manager, $route_provider);
+
+    $route_builder = $this->getMock('Drupal\Core\Routing\RouteBuilderInterface');
+    $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'routeBuilder');
+    $property->setAccessible(TRUE);
+    $property->setValue($manager, $route_builder);
+
     $this->moduleHandler = $this->getMockBuilder('Drupal\Core\Extension\ModuleHandlerInterface')
       ->disableOriginalConstructor()
       ->getMock();
diff --git a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php
index 2d0315b..579700c 100644
--- a/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php
+++ b/core/tests/Drupal/Tests/Core/Menu/LocalTaskManagerTest.php
@@ -49,6 +49,13 @@ class LocalTaskManagerTest extends UnitTestCase {
   protected $routeProvider;
 
   /**
+   * The mocked route builder.
+   *
+   * @var \Drupal\Core\Routing\RouteBuilderInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $routeBuilder;
+
+  /**
    * The mocked plugin discovery.
    *
    * @var \PHPUnit_Framework_MockObject_MockObject
@@ -93,6 +100,7 @@ protected function setUp() {
     $this->controllerResolver = $this->getMock('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface');
     $this->request = new Request();
     $this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
+    $this->routeBuilder = $this->getMock('Drupal\Core\Routing\RouteBuilderInterface');
     $this->pluginDiscovery = $this->getMock('Drupal\Component\Plugin\Discovery\DiscoveryInterface');
     $this->factory = $this->getMock('Drupal\Component\Plugin\Factory\FactoryInterface');
     $this->cacheBackend = $this->getMock('Drupal\Core\Cache\CacheBackendInterface');
@@ -180,6 +188,9 @@ public function testGetLocalTaskForRouteWithEmptyCache() {
       ->method('set')
       ->with('local_task:en', $definitions, Cache::PERMANENT);
 
+    $this->routeBuilder->expects($this->once())
+      ->method('rebuildIfNeeded');
+
     $expected_set = $this->getLocalTasksCache();
 
     $this->cacheBackend->expects($this->at(3))
@@ -212,6 +223,9 @@ public function testGetLocalTaskForRouteWithFilledCache() {
     $this->cacheBackend->expects($this->never())
       ->method('set');
 
+    $this->routeBuilder->expects($this->never())
+      ->method('rebuildIfNeeded');
+
     $result = $this->getLocalTasksForRouteResult($mock_plugin);
     $local_tasks = $this->manager->getLocalTasksForRoute('menu_local_task_test_tasks_view');
     $this->assertEquals($result, $local_tasks);
@@ -257,6 +271,10 @@ protected function setupLocalTaskManager() {
     $property->setAccessible(TRUE);
     $property->setValue($this->manager, $this->accessManager);
 
+    $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'routeBuilder');
+    $property->setAccessible(TRUE);
+    $property->setValue($this->manager, $this->routeBuilder);
+
     $property = new \ReflectionProperty('Drupal\Core\Menu\LocalTaskManager', 'discovery');
     $property->setAccessible(TRUE);
     $property->setValue($this->manager, $this->pluginDiscovery);
