diff --git a/core/lib/Drupal/Core/Link.php b/core/lib/Drupal/Core/Link.php
index 05869a2..3b0eb1f 100644
--- a/core/lib/Drupal/Core/Link.php
+++ b/core/lib/Drupal/Core/Link.php
@@ -7,13 +7,17 @@
 
 namespace Drupal\Core;
 
+use Drupal\Core\Render\RenderableInterface;
 use Drupal\Core\Routing\LinkGeneratorTrait;
 
 /**
  * Defines an object that holds information about a link.
  */
-class Link {
+class Link implements RenderableInterface  {
 
+  /**
+   * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0.
+   */
   use LinkGeneratorTrait;
 
   /**
@@ -44,7 +48,7 @@ public function __construct($text, Url $url) {
   }
 
   /**
-   * Creates a link object from a given route name and parameters.
+   * Creates a Link object from a given route name and parameters.
    *
    * @param string $text
    *   The text of the link.
@@ -76,6 +80,20 @@ public static function createFromRoute($text, $route_name, $route_parameters = a
   }
 
   /**
+   * Creates a Link object from a given Url object.
+   *
+   * @param string $text
+   *   The text of the link.
+   * @param \Drupal\Core\Url $url
+   *   The Url to create the link for.
+   *
+   * @return static
+   */
+  public static function fromTextAndUrl($text, Url $url) {
+    return new static($text, $url);
+  }
+
+  /**
    * Returns the text of the link.
    *
    * @return string
@@ -130,9 +148,23 @@ public function setUrl(Url $url) {
    *   The link HTML markup.
    *   When $collect_bubbleable_metadata is TRUE, a GeneratedLink object is
    *   returned, containing the generated link plus bubbleable metadata.
+   *
+   * @deprecated in Drupal 8.0.x-dev, will be removed before Drupal 9.0.0. Use
+   *   ::build() instead.
    */
   public function toString($collect_bubbleable_metadata = FALSE) {
     return $this->getLinkGenerator()->generateFromLink($this, $collect_bubbleable_metadata);
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function toRenderable() {
+    return [
+      '#type' => 'link',
+      '#url' => $this->url,
+      '#title' => $this->text,
+    ];
+  }
+
 }
diff --git a/core/lib/Drupal/Core/Render/RenderableInterface.php b/core/lib/Drupal/Core/Render/RenderableInterface.php
new file mode 100644
index 0000000..eee8329
--- /dev/null
+++ b/core/lib/Drupal/Core/Render/RenderableInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Render\RenderableInterface.
+ */
+
+namespace Drupal\Core\Render;
+
+/**
+ * Defines an object which can be rendered by the Render API.
+ */
+interface RenderableInterface {
+
+  /**
+   * Returns a render array representation of the object.
+   *
+   * @return mixed[]
+   *   A render array.
+   */
+  public function toRenderable();
+
+}
diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 482c888..0c36f55 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -14,6 +14,7 @@
 
 use Drupal\Component\Utility\SafeMarkup;
 use Drupal\Component\Utility\SafeStringInterface;
+use Drupal\Core\Render\RenderableInterface;
 use Drupal\Core\Render\RendererInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\Theme\ThemeManagerInterface;
@@ -420,6 +421,10 @@ public function escapeFilter(\Twig_Environment $env, $arg, $strategy = 'html', $
       elseif (method_exists($arg, 'toString')) {
         $return = $arg->toString();
       }
+      elseif ($arg instanceof RenderableInterface) {
+        $arg = $arg->toRenderable();
+        return $this->renderer->render($arg);
+      }
       else {
         throw new \Exception(t('Object of type "@class" cannot be printed.', array('@class' => get_class($arg))));
       }
@@ -493,6 +498,10 @@ public function renderVar($arg) {
       if (method_exists($arg, '__toString')) {
         return (string) $arg;
       }
+      elseif ($arg instanceof RenderableInterface) {
+        $arg = $arg->toRenderable();
+        return $this->renderer->render($arg);
+      }
       // You can't throw exceptions in the magic PHP __toString methods, see
       // http://php.net/manual/en/language.oop5.magic.php#object.tostring so
       // we also support a toString method.
diff --git a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
index 5f15073..3069721 100644
--- a/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
+++ b/core/modules/image/src/Plugin/Field/FieldFormatter/ImageFormatter.php
@@ -10,6 +10,7 @@
 use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\FieldDefinitionInterface;
+use Drupal\Core\Link;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Routing\UrlGeneratorInterface;
 use Drupal\Core\Session\AccountInterface;
@@ -40,13 +41,6 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
   protected $currentUser;
 
   /**
-   * The link generator.
-   *
-   * @var \Drupal\Core\Utility\LinkGeneratorInterface
-   */
-  protected $linkGenerator;
-
-  /**
    * The image style entity storage.
    *
    * @var \Drupal\Core\Entity\EntityStorageInterface
@@ -72,13 +66,10 @@ class ImageFormatter extends ImageFormatterBase implements ContainerFactoryPlugi
    *   Any third party settings settings.
    * @param \Drupal\Core\Session\AccountInterface $current_user
    *   The current user.
-   * @param \Drupal\Core\Utility\LinkGeneratorInterface $link_generator
-   *   The link generator service.
    */
-  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, LinkGeneratorInterface $link_generator, EntityStorageInterface $image_style_storage) {
+  public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode, array $third_party_settings, AccountInterface $current_user, EntityStorageInterface $image_style_storage) {
     parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $label, $view_mode, $third_party_settings);
     $this->currentUser = $current_user;
-    $this->linkGenerator = $link_generator;
     $this->imageStyleStorage = $image_style_storage;
   }
 
@@ -95,7 +86,6 @@ public static function create(ContainerInterface $container, array $configuratio
       $configuration['view_mode'],
       $configuration['third_party_settings'],
       $container->get('current_user'),
-      $container->get('link_generator'),
       $container->get('entity.manager')->getStorage('image_style')
     );
   }
@@ -115,17 +105,20 @@ public static function defaultSettings() {
    */
   public function settingsForm(array $form, FormStateInterface $form_state) {
     $image_styles = image_style_options(FALSE);
-    $element['image_style'] = array(
+    $description_link = Link::fromTextAndUrl(
+      $this->t('Configure Image Styles'),
+      Url::fromRoute('entity.image_style.collection')
+    );
+    $element['image_style'] = [
       '#title' => t('Image style'),
       '#type' => 'select',
       '#default_value' => $this->getSetting('image_style'),
       '#empty_option' => t('None (original image)'),
       '#options' => $image_styles,
-      '#description' => array(
-        '#markup' => $this->linkGenerator->generate($this->t('Configure Image Styles'), new Url('entity.image_style.collection')),
-        '#access' => $this->currentUser->hasPermission('administer image styles'),
-      ),
-    );
+      '#description' => $description_link->toRenderable() + [
+        '#access' => $this->currentUser->hasPermission('administer image styles')
+      ],
+    ];
     $link_types = array(
       'content' => t('Content'),
       'file' => t('File'),
diff --git a/core/modules/menu_ui/src/MenuForm.php b/core/modules/menu_ui/src/MenuForm.php
index e008b3b..8b4f6e7 100644
--- a/core/modules/menu_ui/src/MenuForm.php
+++ b/core/modules/menu_ui/src/MenuForm.php
@@ -13,6 +13,7 @@
 use Drupal\Core\Entity\Query\QueryFactory;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Language\LanguageInterface;
+use Drupal\Core\Link;
 use Drupal\Core\Menu\MenuLinkManagerInterface;
 use Drupal\Core\Menu\MenuLinkTreeElement;
 use Drupal\Core\Menu\MenuLinkTreeInterface;
@@ -353,12 +354,12 @@ protected function buildOverviewTreeForm($tree, $delta) {
         $id = 'menu_plugin_id:' . $link->getPluginId();
         $form[$id]['#item'] = $element;
         $form[$id]['#attributes'] = $link->isEnabled() ? array('class' => array('menu-enabled')) : array('class' => array('menu-disabled'));
-        $form[$id]['title']['#markup'] = $this->linkGenerator->generate($link->getTitle(), $link->getUrlObject());
+        $form[$id]['title'] = Link::fromTextAndUrl($link->getTitle(), $link->getUrlObject())->toRenderable();
         if (!$link->isEnabled()) {
-          $form[$id]['title']['#markup'] .= ' (' . $this->t('disabled') . ')';
+          $form[$id]['title']['#suffix'] = ' (' . $this->t('disabled') . ')';
         }
         elseif (($url = $link->getUrlObject()) && $url->isRouted() && $url->getRouteName() == 'user.page') {
-          $form[$id]['title']['#markup'] .= ' (' . $this->t('logged in users only') . ')';
+          $form[$id]['title']['#suffix'] = ' (' . $this->t('logged in users only') . ')';
         }
 
         $form[$id]['enabled'] = array(
diff --git a/core/modules/system/src/Tests/Theme/EngineTwigTest.php b/core/modules/system/src/Tests/Theme/EngineTwigTest.php
index 59af014..283b41d 100644
--- a/core/modules/system/src/Tests/Theme/EngineTwigTest.php
+++ b/core/modules/system/src/Tests/Theme/EngineTwigTest.php
@@ -137,4 +137,12 @@ public function testTwigAttachLibrary() {
     $this->assertRaw('ckeditor.js');
   }
 
+  /**
+   * Tests the rendering of renderables.
+   */
+  public function testRenderable() {
+    $this->drupalGet('/twig-theme-test/renderable');
+    $this->assertRaw('<div>Example markup</div>');
+  }
+
 }
diff --git a/core/modules/system/tests/modules/twig_theme_test/src/ExampleRenderable.php b/core/modules/system/tests/modules/twig_theme_test/src/ExampleRenderable.php
new file mode 100644
index 0000000..fcda370
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_theme_test/src/ExampleRenderable.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\twig_theme_test\ExampleRenderable.
+ */
+
+namespace Drupal\twig_theme_test;
+
+use Drupal\Core\Render\RenderableInterface;
+
+/**
+ * Provides an example implementation of the RenderableInterface.
+ */
+class ExampleRenderable implements RenderableInterface {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function toRenderable() {
+    return [
+      '#markup' => 'Example markup',
+    ];
+  }
+
+}
diff --git a/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php b/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php
index dce85a3..3ca428b 100644
--- a/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php
+++ b/core/modules/system/tests/modules/twig_theme_test/src/TwigThemeTestController.php
@@ -99,4 +99,14 @@ public function registryLoaderRender() {
     return array('#theme' => 'twig_registry_loader_test');
   }
 
+  /**
+   * Controller for testing a renderable inside a template.
+   */
+  public function renderable() {
+    return [
+      '#theme' => 'twig_theme_test_renderable',
+      '#renderable' => new ExampleRenderable()
+    ];
+  }
+
 }
diff --git a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.renderable.html.twig b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.renderable.html.twig
new file mode 100644
index 0000000..29bab78
--- /dev/null
+++ b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.renderable.html.twig
@@ -0,0 +1 @@
+<div>{{ renderable }}</div>
diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module
index 52c0ef4..cba0d5b 100644
--- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module
+++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.module
@@ -62,6 +62,12 @@ function twig_theme_test_theme($existing, $type, $theme, $path) {
     'variables' => array(),
     'template' => 'twig_theme_test.attach_library',
   );
+  $items['twig_theme_test_renderable'] = array(
+    'variables' => array(
+      'renderable' => NULL,
+    ),
+    'template' => 'twig_theme_test.renderable',
+  );
   return $items;
 }
 
diff --git a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml
index 73fcc4a..df665c3 100644
--- a/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml
+++ b/core/modules/system/tests/modules/twig_theme_test/twig_theme_test.routing.yml
@@ -62,3 +62,10 @@ twig_theme_test_registry_loader:
     no_cache: TRUE
   requirements:
     _access: 'TRUE'
+
+twig_theme_test_renderable:
+  path: '/twig-theme-test/renderable'
+  defaults:
+    _controller: '\Drupal\twig_theme_test\TwigThemeTestController::renderable'
+  requirements:
+    _access: 'TRUE'
