diff --git a/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php b/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php
index 8a95237..2101150 100644
--- a/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php
+++ b/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php
@@ -107,13 +107,7 @@ public static function validateEntityAutocomplete(&$element, FormStateInterface
       foreach (Tags::explode($element['#value']) as $input) {
         // Take "label (entity id)', match the ID from parenthesis when it's a
         // number.
-        if (preg_match("/.+\((\d+)\)/", $input, $matches)) {
-          $match = $matches[1];
-        }
-        // Match the ID when it's a string (e.g. for config entity types).
-        elseif (preg_match("/.+\(([\w.]+)\)/", $input, $matches)) {
-          $match = $matches[1];
-        }
+        if (($match = static::extractEntityIdFormAutocompletionResult($input)) && $match !== NULL);
         else {
           // Try to get a match from the input string when the user didn't use
           // the autocomplete but filled in a value manually.
@@ -146,6 +140,27 @@ public static function validateEntityAutocomplete(&$element, FormStateInterface
   }
 
   /**
+   * Extracts the entity ID from the autocompletion result.
+   *
+   * @param string $input
+   *   The input coming from the autocompletion result.
+   *
+   * @return mixed|null
+   *   NULL if no entity could be extracted, otherwise the entity ID.
+   */
+  public static function extractEntityIdFormAutocompletionResult($input) {
+    $match = NULL;
+    if (preg_match("/.+\((\d+)\)/", $input, $matches)) {
+      $match = $matches[1];
+    }
+    // Match the ID when it's a string (e.g. for config entity types).
+    elseif (preg_match("/.+\(([\w.]+)\)/", $input, $matches)) {
+      $match = $matches[1];
+    }
+    return $match;
+  }
+
+  /**
    * Creates a new entity from a label entered in the autocomplete input.
    *
    * @param string $entity_type_id
diff --git a/core/lib/Drupal/Core/Path/PathValidator.php b/core/lib/Drupal/Core/Path/PathValidator.php
index 51cdc2f..fcf0968 100644
--- a/core/lib/Drupal/Core/Path/PathValidator.php
+++ b/core/lib/Drupal/Core/Path/PathValidator.php
@@ -109,6 +109,9 @@ protected function getUrl($path, $access_check) {
     if ($parsed_url['path'] == '<front>') {
       return new Url('<front>', [], $options);
     }
+    elseif ($parsed_url['path'] == '<none>') {
+      return new Url('<none>', [], $options);
+    }
     elseif (UrlHelper::isExternal($path) && UrlHelper::isValid($path)) {
       if (empty($parsed_url['path'])) {
         return FALSE;
diff --git a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
index 0606f42..f6acbbb 100644
--- a/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
+++ b/core/modules/link/src/Plugin/Field/FieldWidget/LinkWidget.php
@@ -9,6 +9,7 @@
 
 use Drupal\Component\Utility\Unicode;
 use Drupal\Component\Utility\UrlHelper;
+use Drupal\Core\Entity\Element\EntityAutocomplete;
 use Drupal\Core\Field\FieldItemListInterface;
 use Drupal\Core\Field\WidgetBase;
 use Drupal\Core\Form\FormStateInterface;
@@ -44,15 +45,29 @@ public static function defaultSettings() {
   /**
    * Gets the URI without the 'user-path:' scheme, for display while editing.
    *
+   * This method is the inverse of ::getUserEnteredStringAsUri().
+   *
    * @param string $uri
    *   The URI to get the displayable string for.
    *
    * @return string
+   *
+   * @see getUserEnteredStringAsUri
    */
   protected static function getUriAsDisplayableString($uri) {
     $scheme = parse_url($uri, PHP_URL_SCHEME);
+    $uri = str_replace('<none>', '', $uri);
+    $uri = str_replace('<front>', '/', $uri);
+
     if ($scheme === 'user-path') {
-      $uri_reference = explode(':', $uri, 2)[1];
+      $uri_reference = ltrim(explode(':', $uri, 2)[1], '/');
+      if (!in_array($uri_reference[0], ['?', '#', '/'])) {
+        $uri_reference = '/' . $uri_reference;
+      }
+    }
+    elseif ($scheme === 'entity') {
+      list($entity_type, $entity_id) = explode('/', substr($uri, 7), 2);
+      $uri_reference = \Drupal::entityManager()->getStorage($entity_type)->load($entity_id)->label() . ' (' . $entity_id . ')';
     }
     else {
       $uri_reference = $uri;
@@ -65,18 +80,33 @@ protected static function getUriAsDisplayableString($uri) {
    *
    * Schemeless URIs are treated as 'user-path:' URIs.
    *
+   * This method is the inverse of ::getUriAsDisplayableString().
+   *
    * @param string $string
    *   The user-entered string.
    *
    * @return string
-   *   The URI, if a non-empty $string was passed.
+   *   The URI, if a non-empty $uri was passed.
+   *
+   * @see getUriAsDisplayableString
    */
   protected static function getUserEnteredStringAsUri($string) {
+    $entity_id = EntityAutocomplete::extractEntityIdFormAutocompletionResult($string);
+    if ($entity_id !== NULL) {
+      $string = 'entity:node/' . $entity_id;
+    }
+
     if (!empty($string)) {
       // Users can enter relative URLs, but we need a valid URI, so add an
       // explicit scheme when necessary.
       if (parse_url($string, PHP_URL_SCHEME) === NULL) {
-        return 'user-path:' . $string;
+        if (parse_url($string, PHP_URL_PATH) === NULL) {
+          $string = '<none>' . $string;
+        }
+        if (parse_url($string, PHP_URL_PATH) === '/') {
+          $string = '<front>' . ltrim($string, '/');
+        }
+        $string = 'user-path:' . $string;
       }
     }
     return $string;
@@ -87,6 +117,15 @@ protected static function getUserEnteredStringAsUri($string) {
    */
   public static function validateUriElement($element, FormStateInterface $form_state, $form) {
     $uri = static::getUserEnteredStringAsUri($element['#value']);
+    $form_state->setValueForElement($element, $uri);
+
+    // Figure out the user entered value after user-path. This might contain a
+    // fragment so we cannot use parse_url($string, PHP_URL_PATH), so we strip
+    // out the 10 chars of user-path:.
+    if (parse_url($uri, PHP_URL_SCHEME) === 'user-path' && !in_array(substr($uri, 10)[0], ['#', '/', '?', '<'], TRUE)) {
+      //
+      $form_state->setError($element, t('Manually entered paths should start with /, # or ?'));
+    }
 
     // If the URI is empty or not well-formed, the link field type's validation
     // constraint will detect it.
@@ -131,18 +170,20 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen
     // If the field is configured to support internal links, it cannot use the
     // 'url' form element and we have to do the validation ourselves.
     if ($this->supportsInternalLinks()) {
-      $element['uri']['#type'] = 'textfield';
+      $element['uri']['#type'] = 'entity_autocomplete';
+      // @todo This should be a setting?
+      $element['uri']['#target_type'] = 'node';
     }
 
     // If the field is configured to allow only internal links, add a useful
     // element prefix.
     if (!$this->supportsExternalLinks()) {
-      $element['uri']['#field_prefix'] = \Drupal::url('<front>', array(), array('absolute' => TRUE));
+      $element['uri']['#field_prefix'] = rtrim(\Drupal::url('<front>', array(), array('absolute' => TRUE)), '/');
     }
     // If the field is configured to allow both internal and external links,
     // show a useful description.
     elseif ($this->supportsExternalLinks() && $this->supportsInternalLinks()) {
-      $element['uri']['#description'] = $this->t('This can be an internal Drupal path such as %add-node or an external URL such as %drupal. Enter %front to link to the front page.', array('%front' => '<front>', '%add-node' => 'node/add', '%drupal' => 'http://drupal.org'));
+      $element['uri']['#description'] = $this->t('This can be an internal Drupal path such as %add-node or an external URL such as %drupal. Enter %front to link to the front page.', array('%front' => '<front>', '%add-node' => '/node/add', '%drupal' => 'http://drupal.org'));
     }
 
     $element['title'] = array(
diff --git a/core/modules/link/src/Tests/LinkFieldTest.php b/core/modules/link/src/Tests/LinkFieldTest.php
index 05a427e..7fed262 100644
--- a/core/modules/link/src/Tests/LinkFieldTest.php
+++ b/core/modules/link/src/Tests/LinkFieldTest.php
@@ -98,9 +98,11 @@ function testURLValidation() {
       'http://www.example.com/',
     );
     $valid_internal_entries = array(
-      'entity_test/add',
-      'a/path/alias',
+      '/entity_test/add',
+      '/a/path/alias',
       'entity:user/1',
+      '#example',
+      '?example=llama',
     );
 
     // Define some invalid URLs.
@@ -113,7 +115,10 @@ function testURLValidation() {
       'http://',
     );
     $invalid_internal_entries = array(
-      'non/existing/path',
+      // No existing.
+      '/non/existing/path',
+      // Missing start with /
+      'no-slash-start',
     );
 
     // Test external and internal URLs for 'link_type' = LinkItemInterface::LINK_GENERIC.
diff --git a/core/modules/system/system.routing.yml b/core/modules/system/system.routing.yml
index 7c87bb9..fecfd249 100644
--- a/core/modules/system/system.routing.yml
+++ b/core/modules/system/system.routing.yml
@@ -382,7 +382,8 @@ system.theme_settings_theme:
   path: ''
   options:
     _only_fragment: TRUE
-
+  requirements:
+    _access: 'TRUE'
 
 '<current>':
   path: '<current>'
