diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 79f7107..015b517 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1964,7 +1964,7 @@ function template_preprocess_page(&$variables) {
   if (!defined('MAINTENANCE_MODE')) {
     $variables['breadcrumb'] = array(
       '#theme' => 'breadcrumb',
-      '#breadcrumb' => \Drupal::service('breadcrumb')->build(\Drupal::routeMatch()),
+      '#links' => \Drupal::service('breadcrumb')->build(\Drupal::routeMatch()),
     );
   }
 }
@@ -2305,6 +2305,23 @@ function template_preprocess_field_multiple_value_form(&$variables) {
 }
 
 /**
+ * Prepares variables for breadcrumb templates.
+ *
+ * Default template: breadcrumb.html.twig.
+ *
+ * @param array $variables
+ *   An associative array containing:
+ *   - links: A list of \Drupal\Core\Link objects which should be rendered.
+ */
+function template_preprocess_breadcrumb(&$variables) {
+  /** @var \Drupal\Core\Link[] $links */
+  $links = $variables['links'];
+  foreach ($links as $key => $link) {
+    $variables['breadcrumb'][$key] = array('text' => $link->getText(), 'url' => $link->getUrl()->toString());
+  }
+}
+
+/**
  * Callback for usort() within template_preprocess_field_multiple_value_form().
  *
  * Sorts using ['_weight']['#value']
@@ -2366,7 +2383,7 @@ function drupal_common_theme() {
       'template' => 'image',
     ),
     'breadcrumb' => array(
-      'variables' => array('breadcrumb' => NULL),
+      'variables' => array('links' => array(), 'breadcrumb' => array()),
       'template' => 'breadcrumb',
     ),
     'table' => array(
diff --git a/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php
index c808ce6..ebdfa55 100644
--- a/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php
+++ b/core/lib/Drupal/Core/Breadcrumb/BreadcrumbBuilderInterface.php
@@ -32,8 +32,8 @@ public function applies(RouteMatchInterface $route_match);
    * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
    *   The current route match.
    *
-   * @return array
-   *   An array of HTML links for the breadcrumb. Returning an empty array will
+   * @return \Drupal\Core\Link[]
+   *   An array of links for the breadcrumb. Returning an empty array will
    *   suppress all breadcrumbs.
    */
   public function build(RouteMatchInterface $route_match);
diff --git a/core/lib/Drupal/Core/Link.php b/core/lib/Drupal/Core/Link.php
new file mode 100644
index 0000000..d08675b
--- /dev/null
+++ b/core/lib/Drupal/Core/Link.php
@@ -0,0 +1,106 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Link.
+ */
+
+namespace Drupal\Core;
+
+/**
+ * Defines an object that holds information about a link.
+ */
+class Link {
+
+  /**
+   * The text of the link.
+   *
+   * @var string
+   */
+  protected $text;
+
+  /**
+   * The URL of the link.
+   *
+   * @var \Drupal\Core\Url
+   */
+  protected $url;
+
+  /**
+   * Constructs a new Link object.
+   *
+   * @param string $text
+   *   The text of the link.
+   * @param \Drupal\Core\Url $url
+   *   The url object.
+   */
+  public function __construct($text, Url $url) {
+    $this->text = $text;
+    $this->url = $url;
+  }
+
+  /**
+   * Creates a link object from a given route name and parameters.
+   *
+   * @param string $text
+   *   The text of the link.
+   * @param string $route_name
+   *   The name of the route
+   * @param array $route_parameters
+   *   (optional) An associative array of parameter names and values.
+   * @param array $options
+   *   (optional) An associative array of additional options, with the following
+   *   elements:
+   *   - 'query': An array of query key/value-pairs (without any URL-encoding)
+   *     to append to the URL. Merged with the parameters array.
+   *   - 'fragment': A fragment identifier (named anchor) to append to the URL.
+   *     Do not include the leading '#' character.
+   *   - 'absolute': Defaults to FALSE. 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.
+   *   - 'language': An optional language object used to look up the alias
+   *     for the URL. If $options['language'] is omitted, it defaults to the
+   *     current language for the language type LanguageInterface::TYPE_URL.
+   *   - 'https': Whether this URL should point to a secure location. If not
+   *     defined, the current scheme is used, so the user stays on HTTP or HTTPS
+   *     respectively. if mixed mode sessions are permitted, TRUE enforces HTTPS
+   *     and FALSE enforces HTTP.
+   *
+   * @return static
+   */
+  public static function createFromRouteArray($text, $route_name, $route_parameters = array(), $options = array()) {
+    return new static($text, new Url($route_name, $route_parameters, $options));
+  }
+
+  /**
+   * Returns the text of the link.
+   *
+   * @return string
+   */
+  public function getText() {
+    return $this->text;
+  }
+
+  /**
+   * Sets the new text of the link.
+   *
+   * @param string $text
+   *   The new text.
+   *
+   * @return $this
+   */
+  public function setText($text) {
+    $this->text = $text;
+    return $this;
+  }
+
+  /**
+   * Returns the URL of the link.
+   *
+   * @return \Drupal\Core\Url
+   */
+  public function getUrl() {
+    return $this->url;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php
index d3093ac..f8660ab 100644
--- a/core/lib/Drupal/Core/Utility/LinkGenerator.php
+++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php
@@ -11,6 +11,7 @@
 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;
@@ -50,6 +51,13 @@ 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.
diff --git a/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php b/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php
index e6e74a7..edce761 100644
--- a/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php
+++ b/core/lib/Drupal/Core/Utility/LinkGeneratorInterface.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\Core\Utility;
 
+use Drupal\Core\Link;
 use Drupal\Core\Url;
 
 /**
@@ -92,4 +93,15 @@ public function generate($text, $route_name, array $parameters = array(), array
    */
   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/book/src/BookBreadcrumbBuilder.php b/core/modules/book/src/BookBreadcrumbBuilder.php
index 9708b3d..9f731a8 100644
--- a/core/modules/book/src/BookBreadcrumbBuilder.php
+++ b/core/modules/book/src/BookBreadcrumbBuilder.php
@@ -10,7 +10,7 @@
 use Drupal\Core\Access\AccessManagerInterface;
 use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Routing\LinkGeneratorTrait;
+use Drupal\Core\Link;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
@@ -21,7 +21,6 @@
  */
 class BookBreadcrumbBuilder implements BreadcrumbBuilderInterface {
   use StringTranslationTrait;
-  use LinkGeneratorTrait;
 
   /**
    * The node storage.
@@ -73,7 +72,7 @@ public function applies(RouteMatchInterface $route_match) {
    */
   public function build(RouteMatchInterface $route_match) {
     $book_nids = array();
-    $links = array($this->l($this->t('Home'), '<front>'));
+    $links = array(Link::createFromRouteArray($this->t('Home'), '<front>'));
     $book = $route_match->getParameter('node')->book;
     $depth = 1;
     // We skip the current node.
@@ -87,7 +86,7 @@ public function build(RouteMatchInterface $route_match) {
       while (!empty($book['p' . ($depth + 1)])) {
         if (!empty($parent_books[$book['p' . $depth]]) && ($parent_book = $parent_books[$book['p' . $depth]])) {
           if ($parent_book->access('view', $this->account)) {
-            $links[] = $this->l($parent_book->label(), 'entity.node.canonical', array('node' => $parent_book->id()));
+            $links[] = Link::createFromRouteArray($parent_book->label(), 'entity.node.canonical', array('node' => $parent_book->id()));
           }
         }
         $depth++;
diff --git a/core/modules/comment/src/CommentBreadcrumbBuilder.php b/core/modules/comment/src/CommentBreadcrumbBuilder.php
index 54f4d1f..929f0cd 100644
--- a/core/modules/comment/src/CommentBreadcrumbBuilder.php
+++ b/core/modules/comment/src/CommentBreadcrumbBuilder.php
@@ -9,8 +9,8 @@
 
 use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Link;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Routing\LinkGeneratorTrait;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 
 /**
@@ -18,7 +18,6 @@
  */
 class CommentBreadcrumbBuilder implements BreadcrumbBuilderInterface {
   use StringTranslationTrait;
-  use LinkGeneratorTrait;
 
   /**
    * Stores the Entity manager service.
@@ -53,11 +52,11 @@ public function applies(RouteMatchInterface $route_match) {
   public function build(RouteMatchInterface $route_match) {
     $breadcrumb = array();
 
-    $breadcrumb[] = $this->l($this->t('Home'), '<front>');
+    $breadcrumb[] = Link::createFromRouteArray($this->t('Home'), '<front>');
     $entity = $this->entityManager
       ->getStorage($route_match->getParameter('entity_type'))
       ->load($route_match->getParameter('entity_id'));
-    $breadcrumb[] = \Drupal::linkGenerator()->generateFromUrl($entity->label(), $entity->urlInfo());
+    $breadcrumb[] = new Link($entity->label(), $entity->urlInfo());
     return $breadcrumb;
   }
 
diff --git a/core/modules/forum/src/Breadcrumb/ForumBreadcrumbBuilderBase.php b/core/modules/forum/src/Breadcrumb/ForumBreadcrumbBuilderBase.php
index 05af222..085070c 100644
--- a/core/modules/forum/src/Breadcrumb/ForumBreadcrumbBuilderBase.php
+++ b/core/modules/forum/src/Breadcrumb/ForumBreadcrumbBuilderBase.php
@@ -10,8 +10,8 @@
 use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityManagerInterface;
+use Drupal\Core\Link;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Routing\LinkGeneratorTrait;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\forum\ForumManagerInterface;
 
@@ -23,7 +23,6 @@
  */
 abstract class ForumBreadcrumbBuilderBase  implements BreadcrumbBuilderInterface {
   use StringTranslationTrait;
-  use LinkGeneratorTrait;
 
   /**
    * Configuration object for this builder.
@@ -66,12 +65,12 @@ public function __construct(EntityManagerInterface $entity_manager, ConfigFactor
    * {@inheritdoc}
    */
   public function build(RouteMatchInterface $route_match) {
-    $breadcrumb[] = $this->l($this->t('Home'), '<front>');
+    $breadcrumb[] = Link::createFromRouteArray($this->t('Home'), '<front>');
 
     $vocabulary = $this->entityManager
       ->getStorage('taxonomy_vocabulary')
       ->load($this->config->get('vocabulary'));
-    $breadcrumb[] = $this->l($vocabulary->label(), 'forum.index');
+    $breadcrumb[] = Link::createFromRouteArray($vocabulary->label(), 'forum.index');
 
     return $breadcrumb;
   }
diff --git a/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php b/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php
index 8f14417..3a78534 100644
--- a/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php
+++ b/core/modules/forum/src/Breadcrumb/ForumListingBreadcrumbBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\forum\Breadcrumb;
 
+use Drupal\Core\Link;
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
@@ -33,7 +34,7 @@ public function build(RouteMatchInterface $route_match) {
     if ($parents) {
       foreach (array_reverse($parents) as $parent) {
         if ($parent->id() != $term_id) {
-          $breadcrumb[] = $this->l($parent->label(), 'forum.page', array(
+          $breadcrumb[] = Link::createFromRouteArray($parent->label(), 'forum.page', array(
             'taxonomy_term' => $parent->id(),
           ));
         }
diff --git a/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php b/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php
index 48d2b38..f1d17fa 100644
--- a/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php
+++ b/core/modules/forum/src/Breadcrumb/ForumNodeBreadcrumbBuilder.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\forum\Breadcrumb;
 
+use Drupal\Core\Link;
 use Drupal\Core\Routing\RouteMatchInterface;
 
 /**
@@ -33,7 +34,7 @@ public function build(RouteMatchInterface $route_match) {
     if ($parents) {
       $parents = array_reverse($parents);
       foreach ($parents as $parent) {
-        $breadcrumb[] = $this->l($parent->label(), 'forum.page',
+        $breadcrumb[] = Link::createFromRouteArray($parent->label(), 'forum.page',
           array(
             'taxonomy_term' => $parent->id(),
           )
diff --git a/core/modules/forum/src/Tests/ForumTest.php b/core/modules/forum/src/Tests/ForumTest.php
index 2a4c499..f920ee2 100644
--- a/core/modules/forum/src/Tests/ForumTest.php
+++ b/core/modules/forum/src/Tests/ForumTest.php
@@ -8,6 +8,7 @@
 namespace Drupal\forum\Tests;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Link;
 use Drupal\simpletest\WebTestBase;
 
 /**
@@ -550,14 +551,14 @@ private function verifyForums(EntityInterface $node, $admin, $response = 200) {
     $this->assertResponse(200);
     $this->assertTitle($node->label() . ' | Drupal', 'Forum node was displayed');
     $breadcrumb_build = array(
-      l(t('Home'), NULL),
-      l(t('Forums'), 'forum'),
-      l($this->forumContainer['name'], 'forum/' . $this->forumContainer['tid']),
-      l($this->forum['name'], 'forum/' . $this->forum['tid']),
+      Link::createFromRouteArray(t('Home'), '<front>'),
+      Link::createFromRouteArray(t('Forums'), 'forum.index'),
+      Link::createFromRouteArray($this->forumContainer['name'], 'forum.page', array('taxonomy_term' => $this->forumContainer['tid'])),
+      Link::createFromRouteArray($this->forum['name'], 'forum.page', array('taxonomy_term' => $this->forum['tid'])),
     );
     $breadcrumb = array(
       '#theme' => 'breadcrumb',
-      '#breadcrumb' => $breadcrumb_build,
+      '#links' => $breadcrumb_build,
     );
     $this->assertRaw(drupal_render($breadcrumb), 'Breadcrumbs were displayed');
 
@@ -608,16 +609,16 @@ private function verifyForumView($forum, $parent = NULL) {
     $this->assertTitle($forum['name'] . ' | Drupal');
 
     $breadcrumb_build = array(
-      l(t('Home'), NULL),
-      l(t('Forums'), 'forum'),
+      Link::createFromRouteArray(t('Home'), '<front>'),
+      Link::createFromRouteArray(t('Forums'), 'forum.index'),
     );
     if (isset($parent)) {
-      $breadcrumb_build[] = l($parent['name'], 'forum/' . $parent['tid']);
+      $breadcrumb_build[] = Link::createFromRouteArray($parent['name'], 'forum.page', array('taxonomy_term' => $parent['tid']));
     }
 
     $breadcrumb = array(
       '#theme' => 'breadcrumb',
-      '#breadcrumb' => $breadcrumb_build,
+      '#links' => $breadcrumb_build,
     );
     $this->assertRaw(drupal_render($breadcrumb), 'Breadcrumbs were displayed');
   }
diff --git a/core/modules/forum/tests/src/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php b/core/modules/forum/tests/src/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php
index ad5840b..7ea9088 100644
--- a/core/modules/forum/tests/src/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php
+++ b/core/modules/forum/tests/src/Breadcrumb/ForumBreadcrumbBuilderBaseTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\forum\Tests\Breadcrumb;
 
+use Drupal\Core\Link;
 use Drupal\Tests\UnitTestCase;
 
 /**
@@ -115,32 +116,19 @@ public function testBuild() {
 
     // Add a translation manager for t().
     $translation_manager = $this->getStringTranslationStub();
-    $property = new \ReflectionProperty('Drupal\forum\Breadcrumb\ForumNodeBreadcrumbBuilder', 'stringTranslation');
-    $property->setAccessible(TRUE);
-    $property->setValue($breadcrumb_builder, $translation_manager);
-
-    // Add a link generator for l().
-    $link_generator = $this->getMockBuilder('Drupal\Core\Utility\LinkGeneratorInterface')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $link_generator->expects($this->any())
-      ->method('generate')
-      ->will($this->returnArgument(0));
-    $property = new \ReflectionProperty('Drupal\forum\Breadcrumb\ForumNodeBreadcrumbBuilder', 'linkGenerator');
-    $property->setAccessible(TRUE);
-    $property->setValue($breadcrumb_builder, $link_generator);
+    $breadcrumb_builder->setStringTranslation($translation_manager);
 
     // Our empty data set.
     $route_match = $this->getMock('Drupal\Core\Routing\RouteMatchInterface');
 
     // Expected result set.
     $expected = array(
-      'Home',
-      'Fora_is_the_plural_of_forum',
+      Link::createFromRouteArray('Home', '<front>'),
+      Link::createFromRouteArray('Fora_is_the_plural_of_forum', 'forum.index'),
     );
 
     // And finally, the test.
-    $this->assertSame($expected, $breadcrumb_builder->build($route_match));
+    $this->assertEquals($expected, $breadcrumb_builder->build($route_match));
   }
 
 }
diff --git a/core/modules/forum/tests/src/Breadcrumb/ForumListingBreadcrumbBuilderTest.php b/core/modules/forum/tests/src/Breadcrumb/ForumListingBreadcrumbBuilderTest.php
index e32e287..a8522af 100644
--- a/core/modules/forum/tests/src/Breadcrumb/ForumListingBreadcrumbBuilderTest.php
+++ b/core/modules/forum/tests/src/Breadcrumb/ForumListingBreadcrumbBuilderTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\forum\Tests\Breadcrumb;
 
+use Drupal\Core\Link;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 
@@ -172,20 +173,7 @@ public function testBuild() {
 
     // Add a translation manager for t().
     $translation_manager = $this->getStringTranslationStub();
-    $property = new \ReflectionProperty('Drupal\forum\Breadcrumb\ForumNodeBreadcrumbBuilder', 'stringTranslation');
-    $property->setAccessible(TRUE);
-    $property->setValue($breadcrumb_builder, $translation_manager);
-
-    // Add a link generator for l().
-    $link_generator = $this->getMockBuilder('Drupal\Core\Utility\LinkGeneratorInterface')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $link_generator->expects($this->any())
-      ->method('generate')
-      ->will($this->returnArgument(0));
-    $property = new \ReflectionProperty('Drupal\forum\Breadcrumb\ForumNodeBreadcrumbBuilder', 'linkGenerator');
-    $property->setAccessible(TRUE);
-    $property->setValue($breadcrumb_builder, $link_generator);
+    $breadcrumb_builder->setStringTranslation($translation_manager);
 
     // The forum listing we need a breadcrumb back from.
     $forum_listing = $this->getMockBuilder('Drupal\taxonomy\Entity\Term')
@@ -205,20 +193,20 @@ public function testBuild() {
 
     // First test.
     $expected1 = array(
-      'Home',
-      'Fora_is_the_plural_of_forum',
-      'Something',
+      Link::createFromRouteArray('Home', '<front>'),
+      Link::createFromRouteArray('Fora_is_the_plural_of_forum', 'forum.index'),
+      Link::createFromRouteArray('Something', 'forum.page', array('taxonomy_term' => 1)),
     );
-    $this->assertSame($expected1, $breadcrumb_builder->build($route_match));
+    $this->assertEquals($expected1, $breadcrumb_builder->build($route_match));
 
     // Second test.
     $expected2 = array(
-      'Home',
-      'Fora_is_the_plural_of_forum',
-      'Something else',
-      'Something',
+      Link::createFromRouteArray('Home', '<front>'),
+      Link::createFromRouteArray('Fora_is_the_plural_of_forum', 'forum.index'),
+      Link::createFromRouteArray('Something else', 'forum.page', array('taxonomy_term' => 2)),
+      Link::createFromRouteArray('Something', 'forum.page', array('taxonomy_term' => 1)),
     );
-    $this->assertSame($expected2, $breadcrumb_builder->build($route_match));
+    $this->assertEquals($expected2, $breadcrumb_builder->build($route_match));
   }
 
 }
diff --git a/core/modules/forum/tests/src/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php b/core/modules/forum/tests/src/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php
index 86cad8e..c83831f 100644
--- a/core/modules/forum/tests/src/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php
+++ b/core/modules/forum/tests/src/Breadcrumb/ForumNodeBreadcrumbBuilderTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\forum\Tests\Breadcrumb;
 
+use Drupal\Core\Link;
 use Drupal\Tests\UnitTestCase;
 use Symfony\Cmf\Component\Routing\RouteObjectInterface;
 
@@ -184,17 +185,6 @@ public function testBuild() {
     $property->setAccessible(TRUE);
     $property->setValue($breadcrumb_builder, $translation_manager);
 
-    // Add a link generator for l().
-    $link_generator = $this->getMockBuilder('Drupal\Core\Utility\LinkGeneratorInterface')
-      ->disableOriginalConstructor()
-      ->getMock();
-    $link_generator->expects($this->any())
-      ->method('generate')
-      ->will($this->returnArgument(0));
-    $property = new \ReflectionProperty('Drupal\forum\Breadcrumb\ForumNodeBreadcrumbBuilder', 'linkGenerator');
-    $property->setAccessible(TRUE);
-    $property->setValue($breadcrumb_builder, $link_generator);
-
     // The forum node we need a breadcrumb back from.
     $forum_node = $this->getMockBuilder('Drupal\node\Entity\Node')
       ->disableOriginalConstructor()
@@ -209,20 +199,20 @@ public function testBuild() {
 
     // First test.
     $expected1 = array(
-      'Home',
-      'Forums',
-      'Something',
+      Link::createFromRouteArray('Home', '<front>'),
+      Link::createFromRouteArray('Forums', 'forum.index'),
+      Link::createFromRouteArray('Something', 'forum.page', array('taxonomy_term' => 1)),
     );
-    $this->assertSame($expected1, $breadcrumb_builder->build($route_match));
+    $this->assertEquals($expected1, $breadcrumb_builder->build($route_match));
 
     // Second test.
     $expected2 = array(
-      'Home',
-      'Forums',
-      'Something else',
-      'Something',
+      Link::createFromRouteArray('Home', '<front>'),
+      Link::createFromRouteArray('Forums', 'forum.index'),
+      Link::createFromRouteArray('Something else', 'forum.page', array('taxonomy_term' => 2)),
+      Link::createFromRouteArray('Something', 'forum.page', array('taxonomy_term' => 1)),
     );
-    $this->assertSame($expected2, $breadcrumb_builder->build($route_match));
+    $this->assertEquals($expected2, $breadcrumb_builder->build($route_match));
   }
 
 }
diff --git a/core/modules/menu_ui/menu_ui.module b/core/modules/menu_ui/menu_ui.module
index 76aee08..fea96d1 100644
--- a/core/modules/menu_ui/menu_ui.module
+++ b/core/modules/menu_ui/menu_ui.module
@@ -10,6 +10,7 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Block\BlockPluginInterface;
+use Drupal\Core\Link;
 use Drupal\Core\Menu\MenuLinkInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Render\Element;
@@ -566,7 +567,7 @@ function menu_ui_system_breadcrumb_alter(array &$breadcrumb, RouteMatchInterface
     if (($menu_link instanceof MenuLinkInterface)) {
       // Add a link to the menu admin screen.
       $menu = Menu::load($menu_link->getMenuName());
-      $breadcrumb[] = \Drupal::l($menu->label(), 'menu_ui.menu_edit', array('menu' => $menu->id()));
+      $breadcrumb[] = Link::createFromRouteArray($menu->label(), 'menu_ui.menu_edit', array('menu' => $menu->id()));
     }
   }
 }
diff --git a/core/modules/system/src/PathBasedBreadcrumbBuilder.php b/core/modules/system/src/PathBasedBreadcrumbBuilder.php
index 46c4ca0..aac4c6a 100644
--- a/core/modules/system/src/PathBasedBreadcrumbBuilder.php
+++ b/core/modules/system/src/PathBasedBreadcrumbBuilder.php
@@ -11,10 +11,10 @@
 use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Controller\TitleResolverInterface;
+use Drupal\Core\Link;
 use Drupal\Core\ParamConverter\ParamNotConvertedException;
 use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Routing\LinkGeneratorTrait;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Component\Utility\Unicode;
@@ -31,7 +31,6 @@
  */
 class PathBasedBreadcrumbBuilder implements BreadcrumbBuilderInterface {
   use StringTranslationTrait;
-  use LinkGeneratorTrait;
 
   /**
    * The router request context.
@@ -154,16 +153,14 @@ public function build(RouteMatchInterface $route_match) {
             // route is missing a _title or _title_callback attribute.
             $title = str_replace(array('-', '_'), ' ', Unicode::ucfirst(end($path_elements)));
           }
-          // @todo Replace with a #type => link render element so that the alter
-          // hook can work with the actual data.
-          $links[] = $this->l($title, $route_request->attributes->get(RouteObjectInterface::ROUTE_NAME), $route_request->attributes->get('_raw_variables')->all(), array('html' => TRUE));
+          $links[] = Link::createFromRouteArray($title, $route_request->attributes->get(RouteObjectInterface::ROUTE_NAME), $route_request->attributes->get('_raw_variables')->all());
         }
       }
 
     }
     if ($path && $path != $front) {
       // Add the Home link, except for the front page.
-      $links[] = $this->l($this->t('Home'), '<front>');
+      $links[] = Link::createFromRouteArray($this->t('Home'), '<front>');
     }
     return array_reverse($links);
   }
diff --git a/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php b/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php
index ebdb677..e822a72 100644
--- a/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php
+++ b/core/modules/system/src/Plugin/Block/SystemBreadcrumbBlock.php
@@ -79,7 +79,7 @@ public function build() {
       // $breadcrumb is expected to be an array of rendered breadcrumb links.
       return array(
         '#theme' => 'breadcrumb',
-        '#breadcrumb' => $breadcrumb,
+        '#links' => $breadcrumb,
       );
     }
   }
diff --git a/core/modules/system/templates/breadcrumb.html.twig b/core/modules/system/templates/breadcrumb.html.twig
index 8a4f438..f6a1705 100644
--- a/core/modules/system/templates/breadcrumb.html.twig
+++ b/core/modules/system/templates/breadcrumb.html.twig
@@ -14,7 +14,13 @@
     <h2 id="system-breadcrumb" class="visually-hidden">{{ 'Breadcrumb'|t }}</h2>
     <ol>
     {% for item in breadcrumb %}
-      <li>{{ item }}</li>
+      <li>
+        {% if item.url %}
+          <a href="{{ item.url }}">{{ item.text }}</a>
+        {% else %}
+          {{ item.text }}
+        {% endif %}
+      </li>
     {% endfor %}
     </ol>
   </nav>
diff --git a/core/modules/system/tests/src/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php b/core/modules/system/tests/src/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php
index 1b521ca..fce97dc 100644
--- a/core/modules/system/tests/src/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php
+++ b/core/modules/system/tests/src/Breadcrumbs/PathBasedBreadcrumbBuilderTest.php
@@ -7,8 +7,10 @@
 
 namespace Drupal\system\Tests\Breadcrumbs;
 
+use Drupal\Core\Link;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\TranslationInterface;
+use Drupal\Core\Url;
 use Drupal\Core\Utility\LinkGeneratorInterface;
 use Drupal\system\PathBasedBreadcrumbBuilder;
 use Drupal\Tests\UnitTestCase;
@@ -60,13 +62,6 @@ class PathBasedBreadcrumbBuilderTest extends UnitTestCase {
   protected $context;
 
   /**
-   * The mocked link generator.
-   *
-   * @var \Drupal\Core\Utility\LinkGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject
-   */
-  protected $linkGenerator;
-
-  /**
    * The mocked current user.
    *
    * @var \Drupal\Core\Session\AccountInterface|\PHPUnit_Framework_MockObject_MockObject
@@ -109,9 +104,6 @@ protected function setUp() {
     );
 
     $this->builder->setStringTranslation($this->getStringTranslationStub());
-
-    $this->linkGenerator = $this->getMock('Drupal\Core\Utility\LinkGeneratorInterface');
-    $this->builder->setLinkGenerator($this->linkGenerator);
   }
 
   /**
@@ -138,10 +130,8 @@ public function testBuildWithOnePathElement() {
       ->method('getPathInfo')
       ->will($this->returnValue('/example'));
 
-    $this->setupLinkGeneratorWithFrontpage();
-
     $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
-    $this->assertEquals(array(0 => '<a href="/">Home</a>'), $links);
+    $this->assertEquals(array(0 => new Link('Home', new Url('<front>'))), $links);
   }
 
   /**
@@ -170,20 +160,10 @@ public function testBuildWithTwoPathElements() {
         }
       }));
 
-    $link_example = '<a href="/example">Example</a>';
-    $link_front = '<a href="/">Home</a>';
-    $this->linkGenerator->expects($this->at(0))
-      ->method('generate')
-      ->with('Example', 'example', array(), array('html' => TRUE))
-      ->will($this->returnValue($link_example));
-    $this->linkGenerator->expects($this->at(1))
-      ->method('generate')
-      ->with('Home', '<front>', array(), array())
-      ->will($this->returnValue($link_front));
     $this->setupAccessManagerWithTrue();
 
     $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
-    $this->assertEquals(array(0 => '<a href="/">Home</a>', 1 => $link_example), $links);
+    $this->assertEquals(array(0 => new Link('Home', new Url('<front>')), 1 => new Link('Example', new Url('example'))), $links);
   }
 
   /**
@@ -220,26 +200,14 @@ public function testBuildWithThreePathElements() {
         }
       }));
 
-    $link_example_bar = '<a href="/example/bar">Bar</a>';
-    $link_example = '<a href="/example">Example</a>';
-    $link_front = '<a href="/">Home</a>';
-    $this->linkGenerator->expects($this->at(0))
-      ->method('generate')
-      ->with('Bar', 'example_bar', array(), array('html' => TRUE))
-      ->will($this->returnValue($link_example_bar));
-
-    $this->linkGenerator->expects($this->at(1))
-      ->method('generate')
-      ->with('Example', 'example', array(), array('html' => TRUE))
-      ->will($this->returnValue($link_example));
-    $this->linkGenerator->expects($this->at(2))
-      ->method('generate')
-      ->with('Home', '<front>', array(), array())
-      ->will($this->returnValue($link_front));
     $this->setupAccessManagerWithTrue();
 
     $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
-    $this->assertEquals(array(0 => '<a href="/">Home</a>', 1 => $link_example, 2 => $link_example_bar), $links);
+    $this->assertEquals(array(
+      new Link('Home', new Url('<front>')),
+      new Link('Example', new Url('example')),
+      new Link('Bar', new Url('example_bar')),
+    ), $links);
   }
 
   /**
@@ -259,12 +227,11 @@ public function testBuildWithException($exception_class, $exception_argument) {
     $this->requestMatcher->expects($this->any())
       ->method('matchRequest')
       ->will($this->throwException(new $exception_class($exception_argument)));
-    $this->setupLinkGeneratorWithFrontpage();
 
     $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
 
     // No path matched, though at least the frontpage is displayed.
-    $this->assertEquals(array(0 => '<a href="/">Home</a>'), $links);
+    $this->assertEquals(array(0 => new Link('Home', new Url('<front>'))), $links);
   }
 
   /**
@@ -301,12 +268,11 @@ public function testBuildWithNonProcessedPath() {
     $this->requestMatcher->expects($this->any())
       ->method('matchRequest')
       ->will($this->returnValue(array()));
-    $this->setupLinkGeneratorWithFrontpage();
 
     $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
 
     // No path matched, though at least the frontpage is displayed.
-    $this->assertEquals(array(0 => '<a href="/">Home</a>'), $links);
+    $this->assertEquals(array(0 => new Link('Home', new Url('<front>'))), $links);
   }
 
   /**
@@ -344,17 +310,6 @@ public function testBuildWithUserPath() {
         }
       }));
 
-    $link_user = '<a href="/user/1">Admin</a>';
-    $link_front = '<a href="/">Home</a>';
-    $this->linkGenerator->expects($this->at(0))
-      ->method('generate')
-      ->with('Admin', 'user_page', array(), array('html' => TRUE))
-      ->will($this->returnValue($link_user));
-
-    $this->linkGenerator->expects($this->at(1))
-      ->method('generate')
-      ->with('Home', '<front>', array(), array())
-      ->will($this->returnValue($link_front));
     $this->setupAccessManagerWithTrue();
     $this->titleResolver->expects($this->once())
       ->method('getTitle')
@@ -362,19 +317,7 @@ public function testBuildWithUserPath() {
       ->will($this->returnValue('Admin'));
 
     $links = $this->builder->build($this->getMock('Drupal\Core\Routing\RouteMatchInterface'));
-    $this->assertEquals(array(0 => '<a href="/">Home</a>', 1 => $link_user), $links);
-  }
-
-  /**
-   * Setup the link generator with a frontpage route.
-   */
-  public function setupLinkGeneratorWithFrontpage() {
-    $this->linkGenerator->expects($this->once())
-      ->method('generate')
-      ->with($this->anything(), '<front>', array())
-      ->will($this->returnCallback(function($title) {
-        return '<a href="/">' . $title . '</a>';
-      }));
+    $this->assertEquals(array(0 => new Link('Home', new Url('<front>')), 1 => new Link('Admin', new Url('user_page'))), $links);
   }
 
   /**
diff --git a/core/modules/taxonomy/src/TermBreadcrumbBuilder.php b/core/modules/taxonomy/src/TermBreadcrumbBuilder.php
index a14041b..0cb36ed 100644
--- a/core/modules/taxonomy/src/TermBreadcrumbBuilder.php
+++ b/core/modules/taxonomy/src/TermBreadcrumbBuilder.php
@@ -8,8 +8,8 @@
 namespace Drupal\taxonomy;
 
 use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
+use Drupal\Core\Link;
 use Drupal\Core\Routing\RouteMatchInterface;
-use Drupal\Core\Routing\LinkGeneratorTrait;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 
 /**
@@ -17,7 +17,6 @@
  */
 class TermBreadcrumbBuilder implements BreadcrumbBuilderInterface {
   use StringTranslationTrait;
-  use LinkGeneratorTrait;
 
   /**
    * {@inheritdoc}
@@ -38,9 +37,9 @@ public function build(RouteMatchInterface $route_match) {
     $breadcrumb = array();
     while ($parents = taxonomy_term_load_parents($term->id())) {
       $term = array_shift($parents);
-      $breadcrumb[] = $this->l($term->getName(), 'taxonomy.term_page', array('taxonomy_term' => $term->id()));
+      $breadcrumb[] = Link::createFromRouteArray($term->getName(), 'taxonomy.term_page', array('taxonomy_term' => $term->id()));
     }
-    $breadcrumb[] = $this->l($this->t('Home'), '<front>');
+    $breadcrumb[] = Link::createFromRouteArray($this->t('Home'), '<front>');
     $breadcrumb = array_reverse($breadcrumb);
 
     return $breadcrumb;
