diff --git a/core/lib/Drupal/Core/Template/TwigExtension.php b/core/lib/Drupal/Core/Template/TwigExtension.php
index 62ad45d377e45a7faa6f7f8d1b0ea01ccd34a47b..9f259598cbe2ae7389d2258d923bb744063e3f82 100644
--- a/core/lib/Drupal/Core/Template/TwigExtension.php
+++ b/core/lib/Drupal/Core/Template/TwigExtension.php
@@ -280,6 +280,10 @@ public function getLink($text, $url, $attributes = []) {
     if (!$url instanceof Url) {
       $url = Url::fromUri($url);
     }
+    // The twig extension should not modify the original URL object, this
+    // ensures consistent rendering.
+    // @see https://www.drupal.org/node/2842399
+    $url = clone $url;
     if ($attributes) {
       if ($attributes instanceof Attribute) {
         $attributes = $attributes->toArray();
diff --git a/core/lib/Drupal/Core/Utility/LinkGenerator.php b/core/lib/Drupal/Core/Utility/LinkGenerator.php
index 0ec5280db30661b38b1dfec40c5c9151b554d203..1dad742a822066d6fd5e6f557f867f7284b031c8 100644
--- a/core/lib/Drupal/Core/Utility/LinkGenerator.php
+++ b/core/lib/Drupal/Core/Utility/LinkGenerator.php
@@ -76,6 +76,11 @@ public function generateFromLink(Link $link) {
    * @see system_page_attachments()
    */
   public function generate($text, Url $url) {
+    // The link generator should not modify the original URL object, this
+    // ensures consistent rendering.
+    // @see https://www.drupal.org/node/2842399
+    $url = clone $url;
+
     // Performance: avoid Url::toString() needing to retrieve the URL generator
     // service from the container.
     $url->setUrlGenerator($this->urlGenerator);
diff --git a/core/modules/system/src/Tests/Theme/EngineTwigTest.php b/core/modules/system/src/Tests/Theme/EngineTwigTest.php
index 51d092d44b114918b3b31071b6aec2bd2c5bdd6a..58661d185f84aeba727c2d10987626d369e49cdf 100644
--- a/core/modules/system/src/Tests/Theme/EngineTwigTest.php
+++ b/core/modules/system/src/Tests/Theme/EngineTwigTest.php
@@ -86,6 +86,7 @@ public function testTwigLinkGenerator() {
       'link via the linkgenerator: ' . $link_generator->generate('register', new Url('user.register', [], ['attributes' => ['class' => ['llama', 'kitten', 'panda']]])),
       'link via the linkgenerator: ' . $link_generator->generate(Markup::create('<span>register</span>'), new Url('user.register', [], ['absolute' => TRUE])),
       'link via the linkgenerator: <a href="' . $generated_url . '"><span>register</span><svg></svg></a>',
+      'link via the linkgenerator: ' . $link_generator->generate('register', new Url('user.register', [], ['attributes' => ['foo' => 'bar']])) . ' ' . $link_generator->generate('register', new Url('user.register', [], ['attributes' => ['foo' => 'bar']])),
     ];
 
     // Verify that link() has the ability to bubble cacheability metadata:
diff --git a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig
index a836aec93c615721479a97ce6e3f95ba825a4a3c..1b20b46e0e4fca4baa8f68ad5792372f31482fe6 100644
--- a/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig
+++ b/core/modules/system/tests/modules/twig_theme_test/templates/twig_theme_test.link_generator.html.twig
@@ -7,3 +7,4 @@
 <div>link via the linkgenerator: {{ link(title, test_url) }}</div>
 {% set title %}<span>register</span><svg></svg>{% endset %}
 <div>link via the linkgenerator: {{ link(title, test_url) }}</div>
+<div>link via the linkgenerator: {{ link('register', test_url_attribute) }} {{ link('register', test_url_attribute) }}</div>
diff --git a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
index f4dc2dfa8e74abb5f944d27394b722308a392073..c3af2db09dda97215b3a00423636c878349e4e6f 100644
--- a/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
+++ b/core/tests/Drupal/Tests/Core/Utility/LinkGeneratorTest.php
@@ -537,6 +537,25 @@ public function testGenerateWithAlterHook() {
     $this->assertEquals($expected_link_markup, (string) $this->linkGenerator->generate('Test', $url)->getGeneratedLink());
   }
 
+  /**
+   * Tests whether rendering the same link twice works.
+   *
+   * This is a regression test for https://www.drupal.org/node/2842399.
+   */
+  public function testGenerateTwice() {
+    $this->urlGenerator->expects($this->any())
+      ->method('generateFromRoute')
+      ->will($this->returnValue((new GeneratedUrl())->setGeneratedUrl('/')));
+
+    $url = Url::fromRoute('<front>', [], ['attributes' => ['class' => ['foo', 'bar']]]);
+    $url->setUrlGenerator($this->urlGenerator);
+
+    $link = Link::fromTextAndUrl('text', $url);
+    $link->setLinkGenerator($this->linkGenerator);
+    $output = $link->toString() . $link->toString();
+    $this->assertEquals('<a href="/" class="foo bar">text</a><a href="/" class="foo bar">text</a>', $output);
+  }
+
   /**
    * Checks that a link with certain properties exists in a given HTML snippet.
    *