diff --git a/core/core.services.yml b/core/core.services.yml
index 1a5a621e75dfd30ebf6555b33302446c7a36d331..496a3b0ca70cb17474218784d5d54c7837036ae0 100644
--- a/core/core.services.yml
+++ b/core/core.services.yml
@@ -774,7 +774,7 @@ services:
   Drupal\Core\Menu\MenuLinkManagerInterface: '@plugin.manager.menu.link'
   menu.link_tree:
     class: Drupal\Core\Menu\MenuLinkTree
-    arguments: ['@menu.tree_storage', '@plugin.manager.menu.link', '@router.route_provider', '@menu.active_trail', '@controller_resolver']
+    arguments: ['@menu.tree_storage', '@plugin.manager.menu.link', '@router.route_provider', '@menu.active_trail', '@callable_resolver']
   Drupal\Core\Menu\MenuLinkTreeInterface: '@menu.link_tree'
   menu.default_tree_manipulators:
     class: Drupal\Core\Menu\DefaultMenuLinkTreeManipulators
diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTree.php b/core/lib/Drupal/Core/Menu/MenuLinkTree.php
index 52991cefa61ec8035044ed017817bfe4c8309365..15d9c71050848c3d2ff7aee268891de2c55da2a5 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkTree.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkTree.php
@@ -9,6 +9,7 @@
 use Drupal\Core\Routing\PreloadableRouteProviderInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
 use Drupal\Core\Template\Attribute;
+use Drupal\Core\Utility\CallableResolver;
 
 /**
  * Implements the loading, transforming and rendering of menu link trees.
@@ -44,11 +45,11 @@ class MenuLinkTree implements MenuLinkTreeInterface {
   protected $menuActiveTrail;
 
   /**
-   * The controller resolver.
+   * The callable resolver.
    *
-   * @var \Drupal\Core\Controller\ControllerResolverInterface
+   * @var \Drupal\Core\Utility\CallableResolver
    */
-  protected $controllerResolver;
+  protected CallableResolver $callableResolver;
 
   /**
    * Constructs a \Drupal\Core\Menu\MenuLinkTree object.
@@ -61,15 +62,19 @@ class MenuLinkTree implements MenuLinkTreeInterface {
    *   The route provider to load routes by name.
    * @param \Drupal\Core\Menu\MenuActiveTrailInterface $menu_active_trail
    *   The active menu trail service.
-   * @param \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver
-   *   The controller resolver.
+   * @param \Drupal\Core\Utility\CallableResolver|\Drupal\Core\Controller\ControllerResolverInterface $callable_resolver
+   *   The callable resolver.
    */
-  public function __construct(MenuTreeStorageInterface $tree_storage, MenuLinkManagerInterface $menu_link_manager, RouteProviderInterface $route_provider, MenuActiveTrailInterface $menu_active_trail, ControllerResolverInterface $controller_resolver) {
+  public function __construct(MenuTreeStorageInterface $tree_storage, MenuLinkManagerInterface $menu_link_manager, RouteProviderInterface $route_provider, MenuActiveTrailInterface $menu_active_trail, ControllerResolverInterface|CallableResolver $callable_resolver) {
     $this->treeStorage = $tree_storage;
     $this->menuLinkManager = $menu_link_manager;
     $this->routeProvider = $route_provider;
     $this->menuActiveTrail = $menu_active_trail;
-    $this->controllerResolver = $controller_resolver;
+    if ($callable_resolver instanceof ControllerResolverInterface) {
+      @trigger_error('Calling ' . __METHOD__ . '() with an argument of ControllerResolverInterface is deprecated in drupal:10.2.0 and is removed in drupal:11.0.0. Use \Drupal\Core\Utility\CallableResolver instead. See https://www.drupal.org/node/3395294', E_USER_DEPRECATED);
+      $callable_resolver = \Drupal::service('callable_resolver');
+    }
+    $this->callableResolver = $callable_resolver;
   }
 
   /**
@@ -137,8 +142,7 @@ protected function createInstances(array $data_tree) {
    */
   public function transform(array $tree, array $manipulators) {
     foreach ($manipulators as $manipulator) {
-      $callable = $manipulator['callable'];
-      $callable = $this->controllerResolver->getControllerFromDefinition($callable);
+      $callable = $this->callableResolver->getCallableFromDefinition($manipulator['callable']);
       // Prepare the arguments for the menu tree manipulator callable; the first
       // argument is always the menu link tree.
       if (isset($manipulator['args'])) {
diff --git a/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php b/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php
index 32a06833e80f65b2bd4ba6878a26667ef75b66fc..73651a0a97c5a302d9bf53ce029adaac0879102c 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkTreeInterface.php
@@ -68,7 +68,7 @@ public function load($menu_name, MenuTreeParameters $parameters);
    * @param array $manipulators
    *   The menu link tree manipulators to apply. Each is an array with keys:
    *   - callable: a callable or a string that can be resolved to a callable
-   *     by \Drupal\Core\Controller\ControllerResolverInterface::getControllerFromDefinition()
+   *     by Drupal\Core\Utility\CallableResolver::getCallableFromDefinition()
    *   - args: optional array of arguments to pass to the callable after $tree.
    *
    * @return \Drupal\Core\Menu\MenuLinkTreeElement[]
diff --git a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
index fce63ffde228a32b833366623855d6faa32a6fc2..6032ff399dc0268170f70ffd58bf925397c1f619 100644
--- a/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
+++ b/core/modules/system/tests/src/Unit/Menu/MenuLinkTreeTest.php
@@ -9,6 +9,7 @@
 use Drupal\Core\Menu\MenuLinkTreeElement;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Url;
+use Drupal\Core\Utility\CallableResolver;
 use Drupal\Tests\Core\Menu\MenuLinkMock;
 use Drupal\Tests\UnitTestCase;
 
@@ -36,7 +37,7 @@ protected function setUp(): void {
       $this->createMock('\Drupal\Core\Menu\MenuLinkManagerInterface'),
       $this->createMock('\Drupal\Core\Routing\RouteProviderInterface'),
       $this->createMock('\Drupal\Core\Menu\MenuActiveTrailInterface'),
-      $this->createMock('\Drupal\Core\Controller\ControllerResolverInterface')
+      $this->createMock(CallableResolver::class)
     );
 
     $cache_contexts_manager = $this->getMockBuilder('Drupal\Core\Cache\Context\CacheContextsManager')
diff --git a/core/modules/toolbar/toolbar.services.yml b/core/modules/toolbar/toolbar.services.yml
index a2cceff403d7cc34f1cb905e23c28bc2a774fbc2..b70f8b9df9c164d4ceb3cd01d7181c67f7ba2e4e 100644
--- a/core/modules/toolbar/toolbar.services.yml
+++ b/core/modules/toolbar/toolbar.services.yml
@@ -11,4 +11,4 @@ services:
       - { name: page_cache_request_policy }
   toolbar.menu_tree:
     class: Drupal\toolbar\Menu\ToolbarMenuLinkTree
-    arguments: ['@menu.tree_storage', '@plugin.manager.menu.link', '@router.route_provider', '@menu.active_trail', '@controller_resolver']
+    arguments: ['@menu.tree_storage', '@plugin.manager.menu.link', '@router.route_provider', '@menu.active_trail', '@callable_resolver']