diff --git a/core/authorize.php b/core/authorize.php
index 8b44e36..0188cf8 100644
--- a/core/authorize.php
+++ b/core/authorize.php
@@ -21,6 +21,7 @@
  */
 
 use Drupal\Core\DrupalKernel;
+use Drupal\Core\Url;
 use Symfony\Component\HttpFoundation\Request;
 use Drupal\Core\Site\Settings;
 use Drupal\Core\Page\DefaultHtmlPageRenderer;
@@ -109,8 +110,8 @@ function authorize_access_allowed() {
     }
     else {
       $links = array_merge($links, array(
-        \Drupal::l(t('Administration pages'), 'system.admin'),
-        \Drupal::l(t('Front page'), '<front>'),
+        \Drupal::l(t('Administration pages'), new Url('system.admin')),
+        \Drupal::l(t('Front page'), new Url('<front>')),
       ));
     }
 
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index c726d07..976158b 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -949,7 +949,7 @@ function template_preprocess_status_messages(&$variables) {
  *   jQuery('li:has("a.active")')
  *
  * @see \Drupal\Core\Utility\LinkGenerator
- * @see \Drupal\Core\Utility\LinkGenerator::generate()
+ * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
  * @see system_page_build()
  */
 function template_preprocess_links(&$variables) {
diff --git a/core/lib/Drupal.php b/core/lib/Drupal.php
index b39663c..1844043 100644
--- a/core/lib/Drupal.php
+++ b/core/lib/Drupal.php
@@ -6,6 +6,7 @@
  */
 
 use Symfony\Component\DependencyInjection\ContainerInterface;
+use Drupal\Core\Url;
 
 /**
  * Static Service Container wrapper.
@@ -531,13 +532,9 @@ public static function linkGenerator() {
    *
    * @param string|array $text
    *   The link text for the anchor tag as a translated string or render array.
-   * @param string $route_name
-   *   The name of the route to use to generate the link.
-   * @param array $parameters
-   *   (optional) Any parameters needed to render the route path pattern.
-   * @param array $options
-   *   (optional) An associative array of additional options. Defaults to an
-   *   empty array. It may contain the following elements:
+   * @param \Drupal\Core\Url $url
+   *   The URL object used for the link. Amongst its options, the following may
+   *   be set to affect the generated link:
    *   - 'query': An array of query key/value-pairs (without any URL-encoding) to
    *     append to the URL.
    *   - absolute: Whether to force the output to be an absolute link (beginning
@@ -570,10 +567,10 @@ public static function linkGenerator() {
    *   does not match the requirement.
    *
    * @see \Drupal\Core\Routing\UrlGeneratorInterface::generateFromRoute()
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
+   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generateFromUrl()
    */
-  public static function l($text, $route_name, array $parameters = array(), array $options = array()) {
-    return static::$container->get('link_generator')->generate($text, $route_name, $parameters, $options);
+  public static function l($text, Url $url) {
+    return static::$container->get('link_generator')->generateFromUrl($text, $url);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Menu/ContextualLinkInterface.php b/core/lib/Drupal/Core/Menu/ContextualLinkInterface.php
index e5eecec..04c2f7d 100644
--- a/core/lib/Drupal/Core/Menu/ContextualLinkInterface.php
+++ b/core/lib/Drupal/Core/Menu/ContextualLinkInterface.php
@@ -50,9 +50,7 @@ public function getGroup();
    * Returns the link options passed to the link generator.
    *
    * @return array
-   *   The options as expected by LinkGeneratorInterface::generate()
-   *
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
+   *   An associative array of options.
    */
   public function getOptions();
 
diff --git a/core/lib/Drupal/Core/Menu/LocalActionInterface.php b/core/lib/Drupal/Core/Menu/LocalActionInterface.php
index 2595816..e6b5e58 100644
--- a/core/lib/Drupal/Core/Menu/LocalActionInterface.php
+++ b/core/lib/Drupal/Core/Menu/LocalActionInterface.php
@@ -30,8 +30,6 @@ public function getRouteName();
    *
    * @return array
    *   An array of parameter names and values.
-   *
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
    */
   public function getRouteParameters(Request $request);
 
@@ -50,8 +48,6 @@ public function getWeight();
    *
    * @return array
    *   An associative array of options.
-   *
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
    */
   public function getOptions(Request $request);
 
diff --git a/core/lib/Drupal/Core/Menu/LocalTaskInterface.php b/core/lib/Drupal/Core/Menu/LocalTaskInterface.php
index 790e801..8064596 100644
--- a/core/lib/Drupal/Core/Menu/LocalTaskInterface.php
+++ b/core/lib/Drupal/Core/Menu/LocalTaskInterface.php
@@ -41,8 +41,6 @@ public function getTitle();
    *
    * @return array
    *   An array of parameter names and values.
-   *
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
    */
   public function getRouteParameters(Request $request);
 
@@ -61,9 +59,7 @@ public function getWeight();
    *   The HttpRequest object representing the current request.
    *
    * @return array
-   *   An array of options.
-   *
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
+   *   An associative array of options.
    */
   public function getOptions(Request $request);
 
diff --git a/core/lib/Drupal/Core/Menu/MenuLinkInterface.php b/core/lib/Drupal/Core/Menu/MenuLinkInterface.php
index 5d10f4e..fdc61df 100644
--- a/core/lib/Drupal/Core/Menu/MenuLinkInterface.php
+++ b/core/lib/Drupal/Core/Menu/MenuLinkInterface.php
@@ -110,6 +110,7 @@ public function isDeletable();
    * Returns the route name, if available.
    *
    * @return string
+   *   The name of the route this menu link links to.
    */
   public function getRouteName();
 
@@ -117,6 +118,7 @@ public function getRouteName();
    * Returns the route parameters, if available.
    *
    * @return array
+   *   An array of parameter names and values.
    */
   public function getRouteParameters();
 
@@ -136,7 +138,7 @@ public function getUrlObject($title_attribute = TRUE);
    * Returns the options for this link.
    *
    * @return array
-   *   The options for the menu link.
+   *   An associative array of options.
    */
   public function getOptions();
 
diff --git a/core/lib/Drupal/Core/Render/Element/Link.php b/core/lib/Drupal/Core/Render/Element/Link.php
index 446b542..a61f845 100644
--- a/core/lib/Drupal/Core/Render/Element/Link.php
+++ b/core/lib/Drupal/Core/Render/Element/Link.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\Core\Render\Element;
+use Drupal\Core\Url;
 
 /**
  * Provides a link render element.
@@ -83,7 +84,7 @@ public static function preRenderLink($element) {
 
     if (isset($element['#route_name'])) {
       $element['#route_parameters'] = empty($element['#route_parameters']) ? array() : $element['#route_parameters'];
-      $element['#markup'] = \Drupal::linkGenerator()->generate($element['#title'], $element['#route_name'], $element['#route_parameters'], $element['#options']);
+      $element['#markup'] = \Drupal::l($element['#title'], new Url($element['#route_name'], $element['#route_parameters'], $element['#options']));
     }
     else {
       $element['#markup'] = l($element['#title'], $element['#href'], $element['#options']);
diff --git a/core/lib/Drupal/Core/Routing/LinkGeneratorTrait.php b/core/lib/Drupal/Core/Routing/LinkGeneratorTrait.php
index 4dda543..9869c57 100644
--- a/core/lib/Drupal/Core/Routing/LinkGeneratorTrait.php
+++ b/core/lib/Drupal/Core/Routing/LinkGeneratorTrait.php
@@ -7,6 +7,7 @@
 namespace Drupal\Core\Routing;
 
 
+use Drupal\Core\Url;
 use Drupal\Core\Utility\LinkGeneratorInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 
@@ -37,7 +38,7 @@
    *   An HTML string containing a link to the given route and parameters.
    */
   protected function l($text, $route_name, array $parameters = array(), array $options = array()) {
-    return $this->getLinkGenerator()->generate($text, $route_name, $parameters, $options);
+    return $this->getLinkGenerator()->generateFromUrl($text, new Url($route_name, $parameters, $options));
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Updater/Module.php b/core/lib/Drupal/Core/Updater/Module.php
index 3d3dd41..fe5aa86 100644
--- a/core/lib/Drupal/Core/Updater/Module.php
+++ b/core/lib/Drupal/Core/Updater/Module.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\Core\Updater;
+use Drupal\Core\Url;
 
 /**
  * Defines a class for updating modules using
@@ -98,9 +99,9 @@ public function getSchemaUpdates() {
    */
   public function postInstallTasks() {
     return array(
-      \Drupal::l(t('Install another module'), 'update.module_install'),
-      \Drupal::l(t('Enable newly added modules'), 'system.modules_list'),
-      \Drupal::l(t('Administration pages'), 'system.admin'),
+      \Drupal::l(t('Install another module'), new Url('update.module_install')),
+      \Drupal::l(t('Enable newly added modules'), new Url('system.modules_list')),
+      \Drupal::l(t('Administration pages'), new Url('system.admin')),
     );
   }
 
diff --git a/core/lib/Drupal/Core/Updater/Theme.php b/core/lib/Drupal/Core/Updater/Theme.php
index 0f1ea5b..6631190 100644
--- a/core/lib/Drupal/Core/Updater/Theme.php
+++ b/core/lib/Drupal/Core/Updater/Theme.php
@@ -6,6 +6,7 @@
  */
 
 namespace Drupal\Core\Updater;
+use Drupal\Core\Url;
 
 /**
  * Defines a class for updating themes using
@@ -82,8 +83,8 @@ public function postInstall() {
    */
   public function postInstallTasks() {
     return array(
-      \Drupal::l(t('Install newly added themes'), 'system.themes_page'),
-      \Drupal::l(t('Administration pages'), 'system.admin'),
+      \Drupal::l(t('Install newly added themes'), new Url('system.themes_page')),
+      \Drupal::l(t('Administration pages'), new Url('system.admin')),
     );
   }
 }
diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php
index f8660ab..15ee6b5 100644
--- a/core/lib/Drupal/Core/Utility/LinkGenerator.php
+++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php
@@ -11,7 +11,6 @@
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Extension\ModuleHandlerInterface;
-use Drupal\Core\Link;
 use Drupal\Core\Path\AliasManagerInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\Template\Attribute;
@@ -51,13 +50,6 @@ public function __construct(UrlGeneratorInterface $url_generator, ModuleHandlerI
 
   /**
    * {@inheritdoc}
-   */
-  public function generateFromLink(Link $link) {
-    return $this->generateFromUrl($link->getText(), $link->getUrl());
-  }
-
-  /**
-   * {@inheritdoc}
    *
    * For anonymous users, the "active" class will be calculated on the server,
    * because most sites serve each anonymous user the same cached page anyway.
@@ -136,13 +128,4 @@ public function generateFromUrl($text, Url $url) {
     return SafeMarkup::set('<a href="' . $url . '"' . $attributes . '>' . $text . '</a>');
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function generate($text, $route_name, array $parameters = array(), array $options = array()) {
-    $url = new Url($route_name, $parameters, $options);
-    $url->setUrlGenerator($this->urlGenerator);
-    return $this->generateFromUrl($text, $url);
-  }
-
 }
diff --git a/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php b/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php
index edce761..1cb2a22 100644
--- a/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php
+++ b/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php
@@ -16,11 +16,7 @@
 interface LinkGeneratorInterface {
 
   /**
-   * Renders a link to a route given a route name and its parameters.
-   *
-   * This function correctly handles aliased paths and sanitizing text, so all
-   * internal links output by modules should be generated by this function if
-   * possible.
+   * Renders a link to a URL.
    *
    * However, for links enclosed in translatable text you should use t() and
    * embed the HTML anchor tag directly in the translated string. For example:
@@ -32,18 +28,9 @@
    *
    * @param string|array $text
    *   The link text for the anchor tag as a translated string or render array.
-   * @param string $route_name
-   *   The name of the route to use to generate the link.
-   * @param array $parameters
-   *   (optional) Any parameters needed to render the route path pattern.
-   * @param array $options
-   *   (optional) An associative array of additional options. Defaults to an
-   *   empty array. It may contain the following elements:
-   *   - 'query': An array of query key/value-pairs (without any URL-encoding)
-   *     to append to the URL.
-   *   - absolute: Whether to force the output to be an absolute link (beginning
-   *     with http:). Useful for links that will be displayed outside the site,
-   *     such as in an RSS feed. Defaults to FALSE.
+   * @param \Drupal\Core\Url $url
+   *   The URL object used for the link. Amongst its options, the following may
+   *   be set to affect the generated link:
    *   - attributes: An associative array of HTML attributes to apply to the
    *     anchor tag. If element 'class' is included, it must be an array; 'title'
    *     must be a string; other elements are more flexible, as they just need
@@ -75,33 +62,7 @@
    * @throws \Symfony\Component\Routing\Exception\InvalidParameterException
    *   Thrown when a parameter value for a placeholder is not correct because it
    *   does not match the requirement.
-   *
-   * @see \Drupal\Core\Routing\UrlGenerator::generateFromRoute()
-   */
-  public function generate($text, $route_name, array $parameters = array(), array $options = array());
-
-  /**
-   * Renders a link to a URL.
-   *
-   * @param string $text
-   *   The link text for the anchor tag as a translated string.
-   * @param \Drupal\Core\Url $url
-   *   The URL object used for the link.
-   *
-   * @return string
-   *   An HTML string containing a link to the given route and parameters.
    */
   public function generateFromUrl($text, Url $url);
 
-  /**
-   * Renders a link from a link object.
-   *
-   * @param \Drupal\Core\Link $link
-   *   A link object to convert to a string.
-   *
-   * @return string
-   *   An HTML string containing a link to the given link.
-   */
-  public function generateFromLink(Link $link);
-
 }
diff --git a/core/modules/aggregator/src/FeedForm.php b/core/modules/aggregator/src/FeedForm.php
index 71acbbd..5f58d8c 100644
--- a/core/modules/aggregator/src/FeedForm.php
+++ b/core/modules/aggregator/src/FeedForm.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Entity\EntityManagerInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -70,7 +71,7 @@ public function save(array $form, FormStateInterface $form_state) {
       $form_state->setRedirectUrl($feed->urlInfo('canonical'));
     }
     else {
-      $this->logger('aggregator')->notice('Feed %feed added.', array('%feed' => $feed->label(), 'link' => \Drupal::l($this->t('View'), 'aggregator.admin_overview')));
+      $this->logger('aggregator')->notice('Feed %feed added.', array('%feed' => $feed->label(), 'link' => \Drupal::l($this->t('View'), new Url('aggregator.admin_overview'))));
       drupal_set_message($this->t('The feed %feed has been added.', array('%feed' => $feed->label())));
     }
   }
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 2b6d8bd..cbf56ab 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -7,6 +7,7 @@
 
 use Drupal\block\BlockInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
 use Drupal\language\Entity\ConfigurableLanguage;
 use Drupal\system\Entity\Menu;
 use Drupal\block\Entity\Block;
@@ -41,7 +42,7 @@ function block_help($route_name, RouteMatchInterface $route_match) {
     $demo_theme = $route_match->getParameter('theme') ?: \Drupal::config('system.theme')->get('default');
     $themes = list_themes();
     $output = '<p>' . t('This page provides a drag-and-drop interface for adding a block to a region, and for controlling the order of blocks within regions. To add a block to a region, or to configure its specific title and visibility settings, click the block title under <em>Place blocks</em>. Since not all themes implement the same regions, or display regions in the same way, blocks are positioned on a per-theme basis. Remember that your changes will not be saved until you click the <em>Save blocks</em> button at the bottom of the page.') . '</p>';
-    $output .= '<p>' . \Drupal::l(t('Demonstrate block regions (!theme)', array('!theme' => $themes[$demo_theme]->info['name'])), 'block.admin_demo', array('theme' => $demo_theme)) . '</p>';
+    $output .= '<p>' . \Drupal::l(t('Demonstrate block regions (!theme)', array('!theme' => $themes[$demo_theme]->info['name'])), new Url('block.admin_demo', array('theme' => $demo_theme))) . '</p>';
     return $output;
   }
 }
diff --git a/core/modules/block_content/block_content.pages.inc b/core/modules/block_content/block_content.pages.inc
index d2dc0c4..187ce68 100644
--- a/core/modules/block_content/block_content.pages.inc
+++ b/core/modules/block_content/block_content.pages.inc
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Component\Utility\Xss;
+use Drupal\Core\Url;
 use Drupal\block_content\Entity\BlockContentType;
 use Drupal\block_content\Entity\BlockContent;
 use Symfony\Component\HttpFoundation\RedirectResponse;
@@ -26,7 +27,7 @@ function template_preprocess_block_content_add_list(&$variables) {
   $query = \Drupal::request()->query->all();
   foreach ($variables['content'] as $type) {
     $variables['types'][$type->id()] = array(
-      'link' => \Drupal::l($type->label(), 'block_content.add_form', array('block_content_type' => $type->id()), array('query' => $query)),
+      'link' => \Drupal::l($type->label(), new Url('block_content.add_form', array('block_content_type' => $type->id()), array('query' => $query))),
       'description' => Xss::filterAdmin($type->description),
       'title' => $type->label(),
       'localized_options' => array(
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index d838125..164e240 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -727,8 +727,8 @@ function template_preprocess_comment(&$variables) {
     $variables['signature'] = '';
   }
   if (isset($comment->in_preview)) {
-    $variables['title'] = \Drupal::l($comment->getSubject(), '<front>');
-    $variables['permalink'] = \Drupal::l(t('Permalink'), '<front>');
+    $variables['title'] = \Drupal::l($comment->getSubject(), new Url('<front>'));
+    $variables['permalink'] = \Drupal::l(t('Permalink'), new Url('<front>'));
   }
   else {
     $uri = $comment->urlInfo();
diff --git a/core/modules/dblog/src/Tests/Views/ViewsIntegrationTest.php b/core/modules/dblog/src/Tests/Views/ViewsIntegrationTest.php
index 7878f00..e856696 100644
--- a/core/modules/dblog/src/Tests/Views/ViewsIntegrationTest.php
+++ b/core/modules/dblog/src/Tests/Views/ViewsIntegrationTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\String;
 use Drupal\Component\Utility\Xss;
+use Drupal\Core\Url;
 use Drupal\views\Views;
 use Drupal\views\Tests\ViewTestData;
 use Drupal\views\Tests\ViewUnitTestBase;
@@ -60,12 +61,12 @@ public function testIntegration() {
     // Setup a watchdog entry without tokens.
     $entries[] = array(
       'message' => $this->randomMachineName(),
-      'variables' => array('link' => \Drupal::l('Link', '<front>')),
+      'variables' => array('link' => \Drupal::l('Link', new Url('<front>'))),
     );
     // Setup a watchdog entry with one token.
     $entries[] = array(
       'message' => '@token1',
-      'variables' => array('@token1' => $this->randomMachineName(), 'link' => \Drupal::l('Link', '<front>')),
+      'variables' => array('@token1' => $this->randomMachineName(), 'link' => \Drupal::l('Link', new Url('<front>'))),
     );
     // Setup a watchdog entry with two tokens.
     $entries[] = array(
@@ -75,7 +76,7 @@ public function testIntegration() {
       'variables' => array(
         '@token1' => $this->randomMachineName(),
         '!token2' => $this->randomMachineName(),
-        'link' => \Drupal::l('<object>Link</object>', '<front>'),
+        'link' => \Drupal::l('<object>Link</object>', new Url('<front>')),
       ),
     );
     $logger_factory = $this->container->get('logger.factory');
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 980ec21..134b255 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -9,6 +9,7 @@
 use Drupal\Core\Extension\Extension;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Url;
 
 /*
  * Load all public Field API functions. Drupal currently has no
@@ -86,7 +87,7 @@ function field_help($route_name, RouteMatchInterface $route_match) {
         if (isset($info[$provider]['name'])) {
           $display = $info[$provider]['name'];
           if (\Drupal::moduleHandler()->implementsHook($provider, 'help')) {
-            $items[] = \Drupal::l($display, 'help.page', array('name' => $provider));
+            $items[] = \Drupal::l($display, new Url('help.page', array('name' => $provider)));
           }
           else {
             $items[] = $display;
diff --git a/core/modules/filter/src/Element/TextFormat.php b/core/modules/filter/src/Element/TextFormat.php
index 14b03d7..72019fc 100644
--- a/core/modules/filter/src/Element/TextFormat.php
+++ b/core/modules/filter/src/Element/TextFormat.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element\RenderElement;
 use Drupal\Core\Render\Element;
+use Drupal\Core\Url;
 
 /**
  * Provides a text format render element.
@@ -179,7 +180,7 @@ public static function processFormat(&$element, FormStateInterface $form_state,
     $element['format']['help'] = array(
       '#type' => 'container',
       '#attributes' => array('class' => array('filter-help')),
-      '#markup' => \Drupal::l(t('About text formats'), 'filter.tips_all', array(), array('attributes' => array('target' => '_blank'))),
+      '#markup' => \Drupal::l(t('About text formats'), new Url('filter.tips_all', array(), array('attributes' => array('target' => '_blank')))),
       '#weight' => 0,
     );
 
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index f81f6a8..5e966d4 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -9,6 +9,7 @@
 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
 use Drupal\Component\Utility\Xss;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Url;
 use Drupal\Component\Utility\String;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
@@ -536,7 +537,7 @@ function template_preprocess_forums(&$variables) {
         if ($variables['tid'] != $topic->forum_tid) {
           $variables['topics'][$id]->moved = TRUE;
           $variables['topics'][$id]->title = String::checkPlain($topic->getTitle());
-          $variables['topics'][$id]->message = \Drupal::l(t('This topic has been moved'), 'forum.page', ['taxonomy_term' => $topic->forum_tid]);
+          $variables['topics'][$id]->message = \Drupal::l(t('This topic has been moved'), new Url('forum.page', ['taxonomy_term' => $topic->forum_tid]));
         }
         else {
           $variables['topics'][$id]->moved = FALSE;
diff --git a/core/modules/forum/src/Form/ForumForm.php b/core/modules/forum/src/Form/ForumForm.php
index eaa6e09..405c13c 100644
--- a/core/modules/forum/src/Form/ForumForm.php
+++ b/core/modules/forum/src/Form/ForumForm.php
@@ -8,6 +8,7 @@
 namespace Drupal\forum\Form;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
 use Drupal\taxonomy\TermForm;
 
 /**
@@ -81,7 +82,7 @@ public function save(array $form, FormStateInterface $form_state) {
 
     $route_name = $this->urlStub == 'container' ? 'forum.edit_container' : 'forum.edit_forum';
     $route_parameters  = ['taxonomy_term' => $term->id()];
-    $link = \Drupal::l($this->t('Edit'), $route_name, $route_parameters);
+    $link = \Drupal::l($this->t('Edit'), new Url($route_name, $route_parameters));
     switch ($status) {
       case SAVED_NEW:
         drupal_set_message($this->t('Created new @type %term.', array('%term' => $term->getName(), '@type' => $this->forumFormType)));
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index c4a9246..b9804d6 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -5,6 +5,7 @@
  * Install, update, and uninstall functions for the Locale module.
  */
 
+use Drupal\Core\Url;
 use Drupal\Core\Language\Language;
 use Drupal\language\Plugin\LanguageNegotiation\LanguageNegotiationSelected;
 
@@ -260,7 +261,7 @@ function locale_requirements($phase) {
           if ($available_updates) {
             $requirements['locale_translation'] = array(
               'title' => 'Translation update status',
-              'value' => \Drupal::l(t('Updates available'), 'locale.translate_status'),
+              'value' => \Drupal::l(t('Updates available'), new Url('locale.translate_status')),
               'severity' => REQUIREMENT_WARNING,
               'description' => t('Updates available for: @languages. See the <a href="@updates">Available translation updates</a> page for more information.', array('@languages' => implode(', ', $available_updates), '@updates' => \Drupal::url('locale.translate_status'))),
             );
@@ -285,7 +286,7 @@ function locale_requirements($phase) {
       else {
         $requirements['locale_translation'] = array(
           'title' => 'Translation update status',
-          'value' => \Drupal::l(t('Can not determine status'), 'locale.translate_status'),
+          'value' => \Drupal::l(t('Can not determine status'), new Url('locale.translate_status')),
           'severity' => REQUIREMENT_WARNING,
           'description' => t('No translation status is available. See the <a href="@updates">Available translation updates</a> page for more information.', array('@updates' => \Drupal::url('locale.translate_status'))),
         );
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index d2db127..3bfd29d 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -13,6 +13,7 @@
 use Drupal\Component\Serialization\Json;
 use Drupal\Component\Utility\UrlHelper;
 use Drupal\Component\Utility\Xss;
+use Drupal\Core\Url;
 use Drupal\Core\Cache\Cache;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\Language;
@@ -600,8 +601,7 @@ function locale_form_language_admin_overview_form_alter(&$form, FormStateInterfa
             '@total' => $total_strings,
             '@ratio' => $stats[$langcode]['ratio'],
           )),
-          'locale.translate_page', array(),
-          array('query' => array('langcode' => $langcode))
+          new Url('locale.translate_page', array(), array('query' => array('langcode' => $langcode)))
         ),
       );
     }
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index d76a741..3ff2a15 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Url;
 use Drupal\Core\Render\Element;
 use Drupal\locale\SourceString;
 use Drupal\locale\TranslationString;
@@ -157,5 +158,5 @@ function template_preprocess_locale_translation_last_check(&$variables) {
   $last = $variables['last'];
   $variables['last_checked'] = ($last != NULL);
   $variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $last);
-  $variables['link'] = \Drupal::l(t('Check manually'), 'locale.check_translation', array(), array('query' => drupal_get_destination()));
+  $variables['link'] = \Drupal::l(t('Check manually'), new Url('locale.check_translation', array(), array('query' => drupal_get_destination())));
 }
diff --git a/core/modules/node/node.install b/core/modules/node/node.install
index fbe4313..36c7d75 100644
--- a/core/modules/node/node.install
+++ b/core/modules/node/node.install
@@ -7,6 +7,7 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Uuid\Uuid;
+use Drupal\Core\Url;
 use Drupal\Core\Language\Language;
 
 /**
@@ -32,7 +33,7 @@ function node_requirements($phase) {
       'value' => $value,
       // The result of t() is safe and so is the result of l(). Preserving
       // safe object.
-      'description' => SafeMarkup::set($description . ' ' . \Drupal::l(t('Rebuild permissions'), 'node.configure_rebuild_confirm')),
+      'description' => SafeMarkup::set($description . ' ' . \Drupal::l(t('Rebuild permissions'), new Url('node.configure_rebuild_confirm'))),
     );
   }
   return $requirements;
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index c51640c..4e3bc46 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -205,7 +205,7 @@ function node_title_list(StatementInterface $result, $title = NULL) {
     // Do not use $node->label() or $node->urlInfo() here, because we only have
     // database rows, not actual nodes.
     $options = !empty($row->comment_count) ? array('attributes' => array('title' => format_plural($row->comment_count, '1 comment', '@count comments'))) : array();
-    $items[] = \Drupal::linkGenerator()->generate($row->title, 'entity.node.canonical', ['node' => $row->nid], $options);
+    $items[] = \Drupal::l($row->title, new Url('entity.node.canonical', ['node' => $row->nid], $options));
     $num_rows = TRUE;
   }
 
diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc
index a7d7769..112e9c2 100644
--- a/core/modules/node/node.pages.inc
+++ b/core/modules/node/node.pages.inc
@@ -10,6 +10,7 @@
  */
 
 use Drupal\Component\Utility\Xss;
+use Drupal\Core\Url;
 use Drupal\Core\Form\FormStateInterface;
 use Symfony\Component\HttpFoundation\RedirectResponse;
 use Drupal\node\NodeInterface;
@@ -31,7 +32,7 @@ function template_preprocess_node_add_list(&$variables) {
     foreach ($variables['content'] as $type) {
       $variables['types'][$type->type] = array(
         'type' => $type->type,
-        'add_link' => \Drupal::l($type->name, 'node.add', array('node_type' => $type->type)),
+        'add_link' => \Drupal::l($type->name, new Url('node.add', array('node_type' => $type->type))),
         'description' => Xss::filterAdmin($type->description),
       );
     }
diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php
index e99d860..ba7b088 100644
--- a/core/modules/node/src/NodeTypeForm.php
+++ b/core/modules/node/src/NodeTypeForm.php
@@ -12,6 +12,7 @@
 use Drupal\Component\Utility\String;
 use Drupal\Core\Entity\EntityTypeInterface;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -230,7 +231,7 @@ public function save(array $form, FormStateInterface $form_state) {
     }
     elseif ($status == SAVED_NEW) {
       drupal_set_message(t('The content type %name has been added.', $t_args));
-      $context = array_merge($t_args, array('link' => \Drupal::l(t('View'), 'node.overview_types')));
+      $context = array_merge($t_args, array('link' => \Drupal::l(t('View'), new Url('node.overview_types'))));
       $this->logger('node')->notice('Added content type %name.', $context);
     }
 
diff --git a/core/modules/search/src/Tests/SearchRankingTest.php b/core/modules/search/src/Tests/SearchRankingTest.php
index c3c1c25..669e6c4 100644
--- a/core/modules/search/src/Tests/SearchRankingTest.php
+++ b/core/modules/search/src/Tests/SearchRankingTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\search\Tests;
 
 use Drupal\comment\Plugin\Field\FieldType\CommentItemInterface;
+use Drupal\Core\Url;
 
 /**
  * Indexes content and tests ranking factors.
@@ -218,7 +219,7 @@ public function testHTMLRankings() {
     foreach ($shuffled_tags as $tag) {
       switch ($tag) {
         case 'a':
-          $settings['body'] = array(array('value' => \Drupal::l('Drupal Rocks', '<front>'), 'format' => 'full_html'));
+          $settings['body'] = array(array('value' => \Drupal::l('Drupal Rocks', new Url('<front>')), 'format' => 'full_html'));
           break;
         case 'notag':
           $settings['body'] = array(array('value' => 'Drupal Rocks'));
diff --git a/core/modules/syslog/syslog.module b/core/modules/syslog/syslog.module
index 3124b50..aad4060 100644
--- a/core/modules/syslog/syslog.module
+++ b/core/modules/syslog/syslog.module
@@ -5,6 +5,7 @@
  * Redirects logging messages to syslog.
  */
 
+use Drupal\Core\Url;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 
@@ -33,7 +34,7 @@ function syslog_help($route_name, RouteMatchInterface $route_match) {
  */
 function syslog_form_system_logging_settings_alter(&$form, FormStateInterface $form_state) {
   $config = \Drupal::config('syslog.settings');
-  $help = \Drupal::moduleHandler()->moduleExists('help') ? ' ' . \Drupal::l(t('More information'), 'help.page', ['name' => 'syslog']) . '.' : NULL;
+  $help = \Drupal::moduleHandler()->moduleExists('help') ? ' ' . \Drupal::l(t('More information'), new Url('help.page', ['name' => 'syslog'])) . '.' : NULL;
   $form['syslog_identity'] = array(
     '#type'          => 'textfield',
     '#title'         => t('Syslog identity'),
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index ebe1b15..fdc3e87 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -6,6 +6,7 @@
  */
 
 use Drupal\Component\Utility\String;
+use Drupal\Core\Url;
 use Drupal\Core\Utility\UpdateException;
 
 /**
@@ -1565,7 +1566,7 @@ function hook_requirements($phase) {
   // Test PHP version
   $requirements['php'] = array(
     'title' => t('PHP'),
-    'value' => ($phase == 'runtime') ? \Drupal::l(phpversion(), 'system.php') : phpversion(),
+    'value' => ($phase == 'runtime') ? \Drupal::l(phpversion(), new Url('system.php')) : phpversion(),
   );
   if (version_compare(phpversion(), DRUPAL_MINIMUM_PHP) < 0) {
     $requirements['php']['description'] = t('Your PHP installation is too old. Drupal requires at least PHP %version.', array('%version' => DRUPAL_MINIMUM_PHP));
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 4d3ba7e..788b9e1 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -8,6 +8,7 @@
 use Drupal\Component\Utility\Crypt;
 use Drupal\Component\Utility\Environment;
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Url;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Site\Settings;
@@ -59,7 +60,7 @@ function system_requirements($phase) {
     $requirements['php'] = array(
       'title' => t('PHP'),
       // $phpversion is safe and output of l() is safe, so this value is safe.
-      'value' => SafeMarkup::set(($phase == 'runtime') ? $phpversion . ' (' . \Drupal::l(t('more information'), 'system.php') . ')' : $phpversion),
+      'value' => SafeMarkup::set(($phase == 'runtime') ? $phpversion . ' (' . \Drupal::l(t('more information'), new Url('system.php')) . ')' : $phpversion),
     );
   }
   else {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 3f19f14..40a557c 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1175,10 +1175,10 @@ function system_time_zones($blank = NULL) {
 function theme_system_compact_link() {
   $output = '<div class="compact-link">';
   if (system_admin_compact_mode()) {
-    $output .= \Drupal::l(t('Show descriptions'), 'system.admin_compact_page', array('mode' => 'off'), array('attributes' => array('title' => t('Expand layout to include descriptions.')), 'query' => drupal_get_destination()));
+    $output .= \Drupal::l(t('Show descriptions'), new Url('system.admin_compact_page', array('mode' => 'off'), array('attributes' => array('title' => t('Expand layout to include descriptions.')), 'query' => drupal_get_destination())));
   }
   else {
-    $output .= \Drupal::l(t('Hide descriptions'), 'system.admin_compact_page', array('mode' => 'on'), array('attributes' => array('title' => t('Compress layout by hiding descriptions.')), 'query' => drupal_get_destination()));
+    $output .= \Drupal::l(t('Hide descriptions'), new Url('system.admin_compact_page', array('mode' => 'on'), array('attributes' => array('title' => t('Compress layout by hiding descriptions.')), 'query' => drupal_get_destination())));
   }
   $output .= '</div>';
 
diff --git a/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php b/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php
index 4a98207..e37ea51 100644
--- a/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php
+++ b/core/modules/taxonomy/src/Plugin/views/field/LinkEdit.php
@@ -8,6 +8,7 @@
 namespace Drupal\taxonomy\Plugin\views\field;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Url;
 use Drupal\views\Plugin\views\field\FieldPluginBase;
 use Drupal\views\Plugin\views\display\DisplayPluginBase;
 use Drupal\views\ResultRow;
@@ -68,7 +69,7 @@ public function render(ResultRow $values) {
       ));
       if ($term->access('update')) {
         $text = !empty($this->options['text']) ? $this->options['text'] : $this->t('Edit');
-        return \Drupal::l($text, 'entity.taxonomy.edit_form', ['taxonomy_term' => $tid], array('query' => drupal_get_destination()));
+        return \Drupal::l($text, new Url('entity.taxonomy.edit_form', ['taxonomy_term' => $tid], array('query' => drupal_get_destination())));
       }
     }
   }
diff --git a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module
index d167f92..69dac7a 100644
--- a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module
+++ b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module
@@ -5,6 +5,8 @@
  * A dummy module to test API interaction with the Toolbar module.
  */
 
+use Drupal\Core\Url;
+
 /**
  * Implements hook_toolbar().
  */
@@ -32,9 +34,9 @@ function toolbar_test_toolbar() {
       'content' => array(
         '#theme' => 'item_list',
         '#items' => array(
-          \Drupal::l(t('link 1'), '<front>', [], array('attributes' => array('title' => 'Test link 1 title'))),
-          \Drupal::l(t('link 2'), '<front>', [], array('attributes' => array('title' => 'Test link 2 title'))),
-          \Drupal::l(t('link 3'), '<front>', [], array('attributes' => array('title' => 'Test link 3 title'))),
+          \Drupal::l(t('link 1'), new Url('<front>', [], array('attributes' => array('title' => 'Test link 1 title')))),
+          \Drupal::l(t('link 2'), new Url('<front>', [], array('attributes' => array('title' => 'Test link 2 title')))),
+          \Drupal::l(t('link 3'), new Url('<front>', [], array('attributes' => array('title' => 'Test link 3 title')))),
         ),
         '#attributes' => array(
           'class' => array('menu'),
diff --git a/core/modules/update/update.install b/core/modules/update/update.install
index fa04937..328288b 100644
--- a/core/modules/update/update.install
+++ b/core/modules/update/update.install
@@ -5,6 +5,8 @@
  * Install, update, and uninstall functions for the Update Manager module.
  */
 
+use Drupal\Core\Url;
+
 /**
  * Implements hook_requirements().
  *
@@ -134,6 +136,6 @@ function _update_requirement_check($project, $type) {
   if ($status != UPDATE_CURRENT && $type == 'core' && isset($project['recommended'])) {
     $requirement_label .= ' ' . t('(version @version available)', array('@version' => $project['recommended']));
   }
-  $requirement['value'] = \Drupal::l($requirement_label, update_manager_access() ? 'update.report_update' : 'update.status');
+  $requirement['value'] = \Drupal::l($requirement_label, new Url(update_manager_access() ? 'update.report_update' : 'update.status'));
   return $requirement;
 }
diff --git a/core/modules/update/update.module b/core/modules/update/update.module
index 65e1364..aded319 100644
--- a/core/modules/update/update.module
+++ b/core/modules/update/update.module
@@ -12,6 +12,7 @@
  */
 
 use Drupal\Component\Utility\SafeMarkup;
+use Drupal\Core\Url;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Site\Settings;
@@ -592,7 +593,7 @@ function _update_project_status_sort($a, $b) {
  */
 function template_preprocess_update_last_check(&$variables) {
   $variables['time'] = \Drupal::service('date.formatter')->formatInterval(REQUEST_TIME - $variables['last']);
-  $variables['link'] = \Drupal::l(t('Check manually'), 'update.manual_status', array(), array('query' => drupal_get_destination()));
+  $variables['link'] = \Drupal::l(t('Check manually'), new Url('update.manual_status', array(), array('query' => drupal_get_destination())));
 }
 
 /**
diff --git a/core/modules/user/src/AccountForm.php b/core/modules/user/src/AccountForm.php
index 57b29f4..bb4d763 100644
--- a/core/modules/user/src/AccountForm.php
+++ b/core/modules/user/src/AccountForm.php
@@ -132,7 +132,7 @@ public function form(array $form, FormStateInterface $form_state) {
       if (!$pass_reset) {
         $protected_values['mail'] = $form['account']['mail']['#title'];
         $protected_values['pass'] = $this->t('Password');
-        $request_new = \Drupal::l($this->t('Request new password'), 'user.pass', array(), array('attributes' => array('title' => $this->t('Request new password via email.'))));
+        $request_new = \Drupal::l($this->t('Request new password'), new Url('user.pass', array(), array('attributes' => array('title' => $this->t('Request new password via email.')))));
         $current_pass_description = $this->t('Required if you want to change the %mail or %pass below. !request_new.', array('%mail' => $protected_values['mail'], '%pass' => $protected_values['pass'], '!request_new' => $request_new));
       }
 
diff --git a/core/modules/user/src/Plugin/Block/UserLoginBlock.php b/core/modules/user/src/Plugin/Block/UserLoginBlock.php
index d93ee2f..ed40273 100644
--- a/core/modules/user/src/Plugin/Block/UserLoginBlock.php
+++ b/core/modules/user/src/Plugin/Block/UserLoginBlock.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\user\Plugin\Block;
 
+use Drupal\Core\Url;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Block\BlockBase;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
@@ -44,19 +45,19 @@ public function build() {
     // Build action links.
     $items = array();
     if (\Drupal::config('user.settings')->get('register') != USER_REGISTER_ADMINISTRATORS_ONLY) {
-      $items['create_account'] = \Drupal::l(t('Create new account'), 'user.register', array(), array(
+      $items['create_account'] = \Drupal::l(t('Create new account'), new Url('user.register', array(), array(
         'attributes' => array(
           'title' => t('Create a new user account.'),
           'class' => array('create-account-link'),
         ),
-      ));
+      )));
     }
-    $items['request_password'] = \Drupal::l(t('Request new password'), 'user.pass', array(), array(
+    $items['request_password'] = \Drupal::l(t('Request new password'), new Url('user.pass', array(), array(
       'attributes' => array(
         'title' => t('Request new password via email.'),
         'class' => array('request-password-link'),
       ),
-    ));
+    )));
     return array(
       'user_login_form' => $form,
       'user_links' => array(
diff --git a/core/modules/user/src/RegisterForm.php b/core/modules/user/src/RegisterForm.php
index fbf0900..650c668 100644
--- a/core/modules/user/src/RegisterForm.php
+++ b/core/modules/user/src/RegisterForm.php
@@ -115,7 +115,7 @@ public function save(array $form, FormStateInterface $form_state) {
     $form_state->set('user', $account);
     $form_state->setValue('uid', $account->id());
 
-    $this->logger('user')->notice('New user: %name %email.', array('%name' => $form_state->getValue('name'), '%email' => '<' . $form_state->getValue('mail') . '>', 'type' => \Drupal::l($this->t('Edit'), 'entity.user.edit_form', array('user' => $account->id()))));
+    $this->logger('user')->notice('New user: %name %email.', array('%name' => $form_state->getValue('name'), '%email' => '<' . $form_state->getValue('mail') . '>', 'type' => \Drupal::l($this->t('Edit'), new Url('entity.user.edit_form', array('user' => $account->id())))));
 
     // Add plain text password into user account to generate mail tokens.
     $account->password = $pass;
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 5348df1..cd13a56 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Theme\Registry;
+use Drupal\Core\Url;
 use Drupal\views\Form\ViewsForm;
 use Drupal\views\Plugin\views\area\AreaPluginBase;
 use Drupal\views\ViewExecutable;
@@ -1034,7 +1035,7 @@ public function optionLink($text, $section, $class = '', $title = '') {
       $title = $text;
     }
 
-    return \Drupal::l($text, 'views_ui.form_display', ['js' => 'nojs', 'view' => $this->view->storage->id(), 'display_id' => $this->display['id'], 'type' => $section], array('attributes' => array('class' => array('views-ajax-link', $class), 'title' => $title, 'id' => drupal_html_id('views-' . $this->display['id'] . '-' . $section)), 'html' => TRUE));
+    return \Drupal::l($text, new Url('views_ui.form_display', ['js' => 'nojs', 'view' => $this->view->storage->id(), 'display_id' => $this->display['id'], 'type' => $section], array('attributes' => array('class' => array('views-ajax-link', $class), 'title' => $title, 'id' => drupal_html_id('views-' . $this->display['id'] . '-' . $section)), 'html' => TRUE)));
   }
 
   /**
diff --git a/core/modules/views/src/Tests/DefaultViewsTest.php b/core/modules/views/src/Tests/DefaultViewsTest.php
index 2fa2e1e..1f75f7d 100644
--- a/core/modules/views/src/Tests/DefaultViewsTest.php
+++ b/core/modules/views/src/Tests/DefaultViewsTest.php
@@ -9,6 +9,7 @@
 
 use Drupal\comment\CommentInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Url;
 use Drupal\simpletest\WebTestBase;
 use Drupal\views\ViewExecutable;
 use Drupal\views\Views;
@@ -94,7 +95,7 @@ protected function setUp() {
       if ($i % 2) {
         $values['promote'] = TRUE;
       }
-      $values['body'][]['value'] = \Drupal::l('Node ' . 1, 'entity.node.canonical', ['node' => 1]);
+      $values['body'][]['value'] = \Drupal::l('Node ' . 1, new Url('entity.node.canonical', ['node' => 1]));
 
       $node = $this->drupalCreateNode($values);
 
diff --git a/core/modules/views_ui/src/ViewEditForm.php b/core/modules/views_ui/src/ViewEditForm.php
index 12083cf..8622c41 100644
--- a/core/modules/views_ui/src/ViewEditForm.php
+++ b/core/modules/views_ui/src/ViewEditForm.php
@@ -1062,13 +1062,13 @@ public function getFormBucket(ViewUI $view, $type, $display) {
       if ($handler->broken()) {
         $build['fields'][$id]['#class'][] = 'broken';
         $field_name = $handler->adminLabel();
-        $build['fields'][$id]['#link'] = \Drupal::l($field_name, 'views_ui.form_handler', array(
+        $build['fields'][$id]['#link'] = \Drupal::l($field_name, new Url('views_ui.form_handler', array(
           'js' => 'nojs',
           'view' => $view->id(),
           'display_id' => $display['id'],
           'type' => $type,
           'id' => $id,
-        ), array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE));
+        ), array('attributes' => array('class' => array('views-ajax-link')), 'html' => TRUE)));
         continue;
       }
 
@@ -1085,33 +1085,33 @@ public function getFormBucket(ViewUI $view, $type, $display) {
         // Add a [hidden] marker, if the field is excluded.
         $link_text .= ' [' . $this->t('hidden') . ']';
       }
-      $build['fields'][$id]['#link'] = \Drupal::l($link_text, 'views_ui.form_handler', array(
+      $build['fields'][$id]['#link'] = \Drupal::l($link_text, new Url('views_ui.form_handler', array(
         'js' => 'nojs',
         'view' => $view->id(),
         'display_id' => $display['id'],
         'type' => $type,
         'id' => $id,
-      ), array('attributes' => $link_attributes, 'html' => TRUE));
+      ), array('attributes' => $link_attributes, 'html' => TRUE)));
       $build['fields'][$id]['#class'][] = drupal_clean_css_identifier($display['id']. '-' . $type . '-' . $id);
 
       if ($executable->display_handler->useGroupBy() && $handler->usesGroupBy()) {
-        $build['fields'][$id]['#settings_links'][] = \Drupal::l('<span class="label">' . $this->t('Aggregation settings') . '</span>', 'views_ui.form_handler_group', array(
+        $build['fields'][$id]['#settings_links'][] = \Drupal::l('<span class="label">' . $this->t('Aggregation settings') . '</span>', new Url('views_ui.form_handler_group', array(
           'js' => 'nojs',
           'view' => $view->id(),
           'display_id' => $display['id'],
           'type' => $type,
           'id' => $id,
-        ), array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => $this->t('Aggregation settings')), 'html' => TRUE));
+        ), array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => $this->t('Aggregation settings')), 'html' => TRUE)));
       }
 
       if ($handler->hasExtraOptions()) {
-        $build['fields'][$id]['#settings_links'][] = \Drupal::l('<span class="label">' . $this->t('Settings') . '</span>', 'views_ui.form_handler_extra', array(
+        $build['fields'][$id]['#settings_links'][] = \Drupal::l('<span class="label">' . $this->t('Settings') . '</span>', new Url('views_ui.form_handler_extra', array(
           'js' => 'nojs',
           'view' => $view->id(),
           'display_id' => $display['id'],
           'type' => $type,
           'id' => $id,
-        ), array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => $this->t('Settings')), 'html' => TRUE));
+        ), array('attributes' => array('class' => array('views-button-configure', 'views-ajax-link'), 'title' => $this->t('Settings')), 'html' => TRUE)));
       }
 
       if ($grouping) {
diff --git a/core/tests/Drupal/Tests/Core/DrupalTest.php b/core/tests/Drupal/Tests/Core/DrupalTest.php
index 4ca6f09..03f6174 100644
--- a/core/tests/Drupal/Tests/Core/DrupalTest.php
+++ b/core/tests/Drupal/Tests/Core/DrupalTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\Tests\Core;
 
 use Drupal\Tests\UnitTestCase;
+use Drupal\Core\Url;
 use Symfony\Component\HttpFoundation\RequestStack;
 
 /**
@@ -277,19 +278,20 @@ public function testLinkGenerator() {
   /**
    * Tests the l() method.
    *
-   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generate()
+   * @see \Drupal\Core\Utility\LinkGeneratorInterface::generateFromUrl()
    */
   public function testL() {
     $route_parameters = array('test_parameter' => 'test');
     $options = array('test_option' => 'test');
     $generator = $this->getMock('Drupal\Core\Utility\LinkGeneratorInterface');
+    $url = new Url('test_route', $route_parameters, $options);
     $generator->expects($this->once())
-      ->method('generate')
-      ->with('Test title', 'test_route', $route_parameters, $options)
+      ->method('generateFromUrl')
+      ->with('Test title', $url)
       ->will($this->returnValue('link_html_string'));
     $this->setMockContainerService('link_generator', $generator);
 
-    $this->assertInternalType('string', \Drupal::l('Test title', 'test_route', $route_parameters, $options));
+    $this->assertInternalType('string', \Drupal::l('Test title', $url));
   }
 
   /**
diff --git a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
index 7926b2f..061d282 100644
--- a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
@@ -84,24 +84,26 @@ public function providerTestGenerateHrefs() {
   /**
    * Tests the link method with certain hrefs.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    * @see \Drupal\Tests\Core\Utility\LinkGeneratorTest::providerTestGenerate()
    *
    * @dataProvider providerTestGenerateHrefs
    */
-  public function testGenerateHrefs($route_name, array $parameters, $absolute, $url) {
+  public function testGenerateHrefs($route_name, array $parameters, $absolute, $expected_url) {
     $this->urlGenerator->expects($this->once())
       ->method('generateFromRoute')
       ->with($route_name, $parameters, array('absolute' => $absolute) + $this->defaultOptions)
-      ->will($this->returnValue($url));
+      ->will($this->returnValue($expected_url));
 
     $this->moduleHandler->expects($this->once())
       ->method('alter');
 
-    $result = $this->linkGenerator->generate('Test', $route_name, $parameters, array('absolute' => $absolute));
+    $url = new Url($route_name, $parameters, array('absolute' => $absolute));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
-      'attributes' => array('href' => $url),
+      'attributes' => array('href' => $expected_url),
       ), $result);
   }
 
@@ -168,7 +170,7 @@ public function testGenerateFromUrlExternal() {
   /**
    * Tests the link method with additional attributes.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    */
   public function testGenerateAttributes() {
     $this->urlGenerator->expects($this->once())
@@ -179,9 +181,11 @@ public function testGenerateAttributes() {
       ));
 
     // Test that HTML attributes are added to the anchor.
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array(
+    $url = new Url('test_route_1', array(), array(
       'attributes' => array('title' => 'Tooltip'),
     ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -194,7 +198,7 @@ public function testGenerateAttributes() {
   /**
    * Tests the link method with passed query options.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    */
   public function testGenerateQuery() {
     $this->urlGenerator->expects($this->once())
@@ -204,9 +208,11 @@ public function testGenerateQuery() {
         '/test-route-1?test=value'
       ));
 
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array(
+    $url = new Url('test_route_1', array(), array(
       'query' => array('test' => 'value'),
     ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -218,7 +224,7 @@ public function testGenerateQuery() {
   /**
    * Tests the link method with passed query options via parameters.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    */
   public function testGenerateParametersAsQuery() {
     $this->urlGenerator->expects($this->once())
@@ -228,7 +234,9 @@ public function testGenerateParametersAsQuery() {
         '/test-route-1?test=value'
       ));
 
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array('test' => 'value'), array());
+    $url = new Url('test_route_1', array('test' => 'value'), array());
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -240,7 +248,7 @@ public function testGenerateParametersAsQuery() {
   /**
    * Tests the link method with arbitrary passed options.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    */
   public function testGenerateOptions() {
     $this->urlGenerator->expects($this->once())
@@ -250,9 +258,11 @@ public function testGenerateOptions() {
         '/test-route-1?test=value'
       ));
 
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array(
+    $url = new Url('test_route_1', array(), array(
       'key' => 'value',
     ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -264,7 +274,7 @@ public function testGenerateOptions() {
   /**
    * Tests the link method with a script tab.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    */
   public function testGenerateXss() {
     $this->urlGenerator->expects($this->once())
@@ -275,7 +285,9 @@ public function testGenerateXss() {
       ));
 
     // Test that HTML link text is escaped by default.
-    $result = $this->linkGenerator->generate("<script>alert('XSS!')</script>", 'test_route_4');
+    $url = new Url('test_route_4');
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl("<script>alert('XSS!')</script>", $url);
     $this->assertNotTag(array(
       'tag' => 'a',
       'attributes' => array('href' => '/test-route-4'),
@@ -288,7 +300,7 @@ public function testGenerateXss() {
   /**
    * Tests the link method with html.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    */
   public function testGenerateWithHtml() {
     $this->urlGenerator->expects($this->at(0))
@@ -305,9 +317,11 @@ public function testGenerateWithHtml() {
       ));
 
     // Test that HTML tags are stripped from the 'title' attribute.
-    $result = $this->linkGenerator->generate('Test', 'test_route_5', array(), array(
+    $url = new Url('test_route_5', array(), array(
       'attributes' => array('title' => '<em>HTML Tooltip</em>'),
     ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -317,7 +331,9 @@ public function testGenerateWithHtml() {
     ), $result);
 
     // Test that the 'html' option allows unsanitized HTML link text.
-    $result = $this->linkGenerator->generate('<em>HTML output</em>', 'test_route_5', array(), array('html' => TRUE));
+    $url = new Url('test_route_5', array(), array('html' => TRUE));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('<em>HTML output</em>', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array('href' => '/test-route-5'),
@@ -330,14 +346,14 @@ public function testGenerateWithHtml() {
   /**
    * Tests the active class on the link method.
    *
-   * @see \Drupal\Core\Utility\LinkGenerator::generate()
+   * @see \Drupal\Core\Utility\LinkGenerator::generateFromUrl()
    *
    * @todo Test that the active class is added on the front page when generating
    *   links to the front page when drupal_is_front_page() is converted to a
    *   service.
    */
   public function testGenerateActive() {
-    $this->urlGenerator->expects($this->exactly(8))
+    $this->urlGenerator->expects($this->exactly(5))
       ->method('generateFromRoute')
       ->will($this->returnValueMap(array(
         array('test_route_1', array(), FALSE, '/test-route-1'),
@@ -345,7 +361,7 @@ public function testGenerateActive() {
         array('test_route_4', array('object' => '1'), FALSE, '/test-route-4/1'),
       )));
 
-    $this->urlGenerator->expects($this->exactly(7))
+    $this->urlGenerator->expects($this->exactly(4))
       ->method('getPathFromRoute')
       ->will($this->returnValueMap(array(
         array('test_route_1', array(), 'test-route-1'),
@@ -353,49 +369,34 @@ public function testGenerateActive() {
         array('test_route_4', array('object' => '1'), 'test-route-4/1'),
       )));
 
-    $this->moduleHandler->expects($this->exactly(8))
+    $this->moduleHandler->expects($this->exactly(5))
       ->method('alter');
 
-    // Render a link with a path different from the current path.
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array('set_active_class' => TRUE));
-    $this->assertTag(array(
-      'tag' => 'a',
-      'attributes' => array('data-drupal-link-system-path' => 'test-route-1'),
-    ), $result);
-
-    // Render a link with the same path as the current path.
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array('set_active_class' => TRUE));
+    // Render a link.
+    $url = new Url('test_route_1', array(), array('set_active_class' => TRUE));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array('data-drupal-link-system-path' => 'test-route-1'),
     ), $result);
 
-    // Render a link with the same path as the current path, but with the
-    // set_active_class option disabled.
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array('set_active_class' => FALSE));
+    // Render a link with the set_active_class option disabled.
+    $url = new Url('test_route_1', array(), array('set_active_class' => FALSE));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertNotTag(array(
       'tag' => 'a',
       'attributes' => array('data-drupal-link-system-path' => 'test-route-1'),
     ), $result);
 
-    // Render a link with the same path and language as the current path.
-    $result = $this->linkGenerator->generate('Test', 'test_route_1', array(), array('set_active_class' => TRUE));
-    $this->assertTag(array(
-      'tag' => 'a',
-      'attributes' => array('data-drupal-link-system-path' => 'test-route-1'),
-    ), $result);
-
-    // Render a link with the same path but a different language than the current
-    // path.
-    $result = $this->linkGenerator->generate(
-      'Test',
-      'test_route_1',
-      array(),
-      array(
-        'language' => new Language(array('id' => 'de')),
-        'set_active_class' => TRUE,
-      )
-    );
+    // Render a link with an associated language.
+    $url = new Url('test_route_1', array(), array(
+      'language' => new Language(array('id' => 'de')),
+      'set_active_class' => TRUE,
+    ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -404,16 +405,13 @@ public function testGenerateActive() {
       ),
     ), $result);
 
-    // Render a link with the same path and query parameter as the current path.
-    $result = $this->linkGenerator->generate(
-      'Test',
-      'test_route_3',
-      array(),
-      array(
-        'query' => array('value' => 'example_1'),
-        'set_active_class' => TRUE,
-      )
-    );
+    // Render a link with a query parameter.
+    $url = new Url('test_route_3', array(), array(
+      'query' => array('value' => 'example_1'),
+      'set_active_class' => TRUE,
+    ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
@@ -422,35 +420,13 @@ public function testGenerateActive() {
       ),
     ), $result);
 
-    // Render a link with the same path but a different query parameter than the
-    // current path.
-    $result = $this->linkGenerator->generate(
-      'Test',
-      'test_route_3',
-      array(),
-      array(
-        'query' => array('value' => 'example_2'),
-        'set_active_class' => TRUE,
-      )
-    );
-    $this->assertTag(array(
-      'tag' => 'a',
-      'attributes' => array(
-        'data-drupal-link-system-path' => 'test-route-3',
-        'data-drupal-link-query' => 'regexp:/.*value.*example_2.*/',
-      ),
-    ), $result);
-
-    // Render a link with the same path and query parameter as the current path.
-    $result = $this->linkGenerator->generate(
-      'Test',
-      'test_route_4',
-      array('object' => '1'),
-      array(
-        'query' => array('value' => 'example_1'),
-        'set_active_class' => TRUE,
-      )
-    );
+    // Render a link with route parameters and a query parameter.
+    $url = new Url('test_route_4', array('object' => '1'), array(
+      'query' => array('value' => 'example_1'),
+      'set_active_class' => TRUE,
+    ));
+    $url->setUrlGenerator($this->urlGenerator);
+    $result = $this->linkGenerator->generateFromUrl('Test', $url);
     $this->assertTag(array(
       'tag' => 'a',
       'attributes' => array(
