diff --git a/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php b/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php
index 0e17c25..f344162 100644
--- a/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php
+++ b/core/lib/Drupal/Core/Entity/Element/EntityAutocomplete.php
@@ -39,6 +39,10 @@ public function getInfo() {
     // This should only be set to FALSE if proper validation by the selection
     // handler is performed at another level on the extracted form values.
     $info['#validate_reference'] = TRUE;
+    // When validation is performed at another level, the caller might need the
+    // submitted value as-is. In this case, the form element will act as a
+    // simple textfield and just return the user input.
+    $info['#process_autocomplete_value'] = TRUE;
     // IMPORTANT! This should only be set to FALSE if the #default_value
     // property is processed at another level (e.g. by a Field API widget) and
     // it's value is properly checked for access.
@@ -128,6 +132,15 @@ public static function processEntityAutocomplete(array &$element, FormStateInter
   public static function validateEntityAutocomplete(array &$element, FormStateInterface $form_state, array &$complete_form) {
     $value = NULL;
     if (!empty($element['#value'])) {
+      $input_values = $element['#tags'] ? Tags::explode($element['#value']) : $element['#value'];
+
+      // If the element is used as a simple textfield with autocomplete support,
+      // no extra processing is required.
+      if (!$element['#process_autocomplete_value']) {
+        $form_state->setValueForElement($element, $input_values);
+        return;
+      }
+
       $options = array(
         'target_type' => $element['#target_type'],
         'handler' => $element['#selection_handler'],
@@ -136,7 +149,7 @@ public static function validateEntityAutocomplete(array &$element, FormStateInte
       $handler = \Drupal::service('plugin.manager.entity_reference_selection')->getInstance($options);
       $autocreate = (bool) $element['#autocreate'];
 
-      foreach (Tags::explode($element['#value']) as $input) {
+      foreach ((array) $input_values as $input) {
         $match = static::extractEntityIdFromAutocompleteInput($input);
         if ($match === NULL) {
           // Try to get a match from the input string when the user didn't use
diff --git a/core/modules/comment/src/CommentForm.php b/core/modules/comment/src/CommentForm.php
index a9d742b..2fbc565 100644
--- a/core/modules/comment/src/CommentForm.php
+++ b/core/modules/comment/src/CommentForm.php
@@ -146,9 +146,15 @@ public function form(array $form, FormStateInterface $form_state) {
       '#size' => 30,
     );
     if ($is_admin) {
+      $form['author']['name']['#type'] = 'entity_autocomplete';
+      $form['author']['name']['#target_type'] = 'user';
+      $form['author']['name']['#selection_settings'] = ['include_anonymous' => FALSE];
+      $form['author']['name']['#process_default_value'] = FALSE;
+      // The user name is validated and processed in static::buildEntity() and
+      // static::validate().
+      $form['author']['name']['#process_autocomplete_value'] = FALSE;
       $form['author']['name']['#title'] = $this->t('Authored by');
       $form['author']['name']['#description'] = $this->t('Leave blank for %anonymous.', array('%anonymous' => $this->config('user.settings')->get('anonymous')));
-      $form['author']['name']['#autocomplete_route_name'] = 'user.autocomplete';
     }
     elseif ($this->currentUser->isAuthenticated()) {
       $form['author']['name']['#type'] = 'item';
@@ -248,9 +254,8 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
     else {
       $comment->setCreatedTime(REQUEST_TIME);
     }
-    $author_name = $form_state->getValue('name');
 
-    if (!$this->currentUser->isAnonymous()) {
+    if ($author_name = $form_state->getValue('name')) {
       // Assign the owner based on the given user name - none means anonymous.
       $accounts = $this->entityManager->getStorage('user')
         ->loadByProperties(array('name' => $author_name));
@@ -258,6 +263,9 @@ public function buildEntity(array $form, FormStateInterface $form_state) {
       $uid = $account ? $account->id() : 0;
       $comment->setOwnerId($uid);
     }
+    else {
+      $comment->setOwnerId(0);
+    }
 
     // If the comment was posted by an anonymous user and no author name was
     // required, use "Anonymous" by default.
diff --git a/core/modules/comment/src/Tests/CommentInterfaceTest.php b/core/modules/comment/src/Tests/CommentInterfaceTest.php
index 98eee30..818a896 100644
--- a/core/modules/comment/src/Tests/CommentInterfaceTest.php
+++ b/core/modules/comment/src/Tests/CommentInterfaceTest.php
@@ -196,4 +196,5 @@ function testCommentInterface() {
     $this->drupalLogin($this->adminUser);
     $this->setCommentForm(FALSE);
   }
+
 }
diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php
index a475332..eab020f 100644
--- a/core/modules/content_translation/src/ContentTranslationHandler.php
+++ b/core/modules/content_translation/src/ContentTranslationHandler.php
@@ -390,19 +390,21 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En
       }
 
       // Default to the anonymous user.
-      $name = '';
+      $uid = 0;
       if ($new_translation) {
-        $name = \Drupal::currentUser()->getUsername();
+        $uid = \Drupal::currentUser()->getAccount()->id();
       }
       elseif (($account = $metadata->getAuthor()) && $account->id()) {
-        $name = $account->getUsername();
+        $uid = $account->id();
       }
-      $form['content_translation']['name'] = array(
-        '#type' => 'textfield',
+      $form['content_translation']['uid'] = array(
+        '#type' => 'entity_autocomplete',
         '#title' => t('Authored by'),
+        '#target_type' => 'user',
+        '#default_value' => User::load($uid),
+        // Validation is done by static::entityFormValidate().
+        '#validate_reference' => FALSE,
         '#maxlength' => 60,
-        '#autocomplete_route_name' => 'user.autocomplete',
-        '#default_value' => $name,
         '#description' => t('Leave blank for %anonymous.', array('%anonymous' => \Drupal::config('user.settings')->get('anonymous'))),
       );
 
@@ -530,12 +532,8 @@ public function entityFormEntityBuild($entity_type, EntityInterface $entity, arr
     $form_langcode = $form_object->getFormLangcode($form_state);
     $values = &$form_state->getValue('content_translation', array());
 
-    if ($values['name'] == \Drupal::config('user.settings')->get('anonymous')) {
-      $values['name'] = '';
-    }
-
     $metadata = $this->manager->getTranslationMetadata($entity);
-    $metadata->setAuthor(!empty($values['name']) && ($account = user_load_by_name($values['name'])) ? $account : User::load(0));
+    $metadata->setAuthor(!empty($values['uid']) ? User::load($values['uid']) : User::load(0));
     $metadata->setPublished(!empty($values['status']));
     $metadata->setCreatedTime(!empty($values['created']) ? strtotime($values['created']) : REQUEST_TIME);
     $metadata->setChangedTime(REQUEST_TIME);
@@ -560,8 +558,8 @@ function entityFormValidate($form, FormStateInterface $form_state) {
     if (!$form_state->isValueEmpty('content_translation')) {
       $translation = $form_state->getValue('content_translation');
       // Validate the "authored by" field.
-      if (!empty($translation['name']) && !($account = user_load_by_name($translation['name']))) {
-        $form_state->setErrorByName('content_translation][name', t('The translation authoring username %name does not exist.', array('%name' => $translation['name'])));
+      if (!empty($translation['uid']) && !($account = User::load($translation['uid']))) {
+        $form_state->setErrorByName('content_translation][uid', t('The translation authoring username %name does not exist.', array('%name' => $account->getUsername())));
       }
       // Validate the "authored on" field.
       if (!empty($translation['created']) && strtotime($translation['created']) === FALSE) {
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationUITest.php b/core/modules/content_translation/src/Tests/ContentTranslationUITest.php
index 2a8d680..9ed362b 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationUITest.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationUITest.php
@@ -219,7 +219,7 @@ protected function doTestAuthoringInfo() {
         'created' => REQUEST_TIME - mt_rand(0, 1000),
       );
       $edit = array(
-        'content_translation[name]' => $user->getUsername(),
+        'content_translation[uid]' => $user->getUsername(),
         'content_translation[created]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d H:i:s O'),
       );
       $url = $entity->urlInfo('edit-form', array('language' => ConfigurableLanguage::load($langcode)));
@@ -237,7 +237,7 @@ protected function doTestAuthoringInfo() {
     $langcode = 'en';
     $edit = array(
       // User names have by default length 8.
-      'content_translation[name]' => $this->randomMachineName(12),
+      'content_translation[uid]' => $this->randomMachineName(12),
       'content_translation[created]' => '19/11/1978',
     );
     $this->drupalPostForm($entity->urlInfo('edit-form'), $edit, $this->getFormSubmitAction($entity, $langcode));
diff --git a/core/modules/entity_reference/config/schema/entity_reference.schema.yml b/core/modules/entity_reference/config/schema/entity_reference.schema.yml
index ec291fa..4574c9e 100644
--- a/core/modules/entity_reference/config/schema/entity_reference.schema.yml
+++ b/core/modules/entity_reference/config/schema/entity_reference.schema.yml
@@ -36,3 +36,6 @@ entity_reference.default.handler_settings:
     auto_create:
       type: boolean
       label: 'Create referenced entities if they don''t already exist'
+    include_anonymous:
+      type: boolean
+      label: 'Include the anonymous user in the matched entities.'
diff --git a/core/modules/node/src/Plugin/Action/AssignOwnerNode.php b/core/modules/node/src/Plugin/Action/AssignOwnerNode.php
index 0d1cc38..44cfeb6 100644
--- a/core/modules/node/src/Plugin/Action/AssignOwnerNode.php
+++ b/core/modules/node/src/Plugin/Action/AssignOwnerNode.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
 use Drupal\Core\Session\AccountInterface;
+use Drupal\user\Entity\User;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -63,8 +64,8 @@ public static function create(ContainerInterface $container, array $configuratio
    * {@inheritdoc}
    */
   public function execute($entity = NULL) {
-    $entity->uid = $this->configuration['owner_uid'];
-    $entity->save();
+    /** @var \Drupal\node\NodeInterface $entity */
+    $entity->setOwnerId($this->configuration['owner_uid'])->save();
   }
 
   /**
@@ -82,32 +83,33 @@ public function defaultConfiguration() {
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
     $description = t('The username of the user to which you would like to assign ownership.');
     $count = $this->connection->query("SELECT COUNT(*) FROM {users}")->fetchField();
-    $owner_name = '';
-    if (is_numeric($this->configuration['owner_uid'])) {
-      $owner_name = $this->connection->query("SELECT name FROM {users_field_data} WHERE uid = :uid AND default_langcode = 1", array(':uid' => $this->configuration['owner_uid']))->fetchField();
-    }
 
     // Use dropdown for fewer than 200 users; textbox for more than that.
     if (intval($count) < 200) {
       $options = array();
       $result = $this->connection->query("SELECT uid, name FROM {users_field_data} WHERE uid > 0 AND default_langcode = 1 ORDER BY name");
       foreach ($result as $data) {
-        $options[$data->name] = $data->name;
+        $options[$data->uid] = $data->name;
       }
-      $form['owner_name'] = array(
+      $form['owner_uid'] = array(
         '#type' => 'select',
         '#title' => t('Username'),
-        '#default_value' => $owner_name,
+        '#default_value' => $this->configuration['owner_uid'],
         '#options' => $options,
         '#description' => $description,
       );
     }
     else {
-      $form['owner_name'] = array(
-        '#type' => 'textfield',
+      $form['owner_uid'] = array(
+        '#type' => 'entity_autocomplete',
         '#title' => t('Username'),
-        '#default_value' => $owner_name,
-        '#autocomplete_route_name' => 'user.autocomplete',
+        '#target_type' => 'user',
+        '#selection_setttings' => array(
+          'include_anonymous' => FALSE,
+        ),
+        '#default_value' => User::load($this->configuration['owner_uid']),
+        // Validation is done in static::validateConfigurationForm().
+        '#validate_reference' => FALSE,
         '#size' => '6',
         '#maxlength' => '60',
         '#description' => $description,
@@ -120,9 +122,9 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
    * {@inheritdoc}
    */
   public function validateConfigurationForm(array &$form, FormStateInterface $form_state) {
-    $exists = (bool) $this->connection->queryRange('SELECT 1 FROM {users_field_data} WHERE name = :name AND default_langcode = 1', 0, 1, array(':name' => $form_state->getValue('owner_name')))->fetchField();
+    $exists = (bool) $this->connection->queryRange('SELECT 1 FROM {users_field_data} WHERE uid = :uid AND default_langcode = 1', 0, 1, array(':name' => $form_state->getValue('owner_uid')))->fetchField();
     if (!$exists) {
-      $form_state->setErrorByName('owner_name', t('Enter a valid username.'));
+      $form_state->setErrorByName('owner_uid', t('Enter a valid username.'));
     }
   }
 
@@ -130,7 +132,7 @@ public function validateConfigurationForm(array &$form, FormStateInterface $form
    * {@inheritdoc}
    */
   public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
-    $this->configuration['owner_uid'] = $this->connection->query('SELECT uid from {users_field_data} WHERE name = :name AND default_langcode = 1', array(':name' => $form_state->getValue('owner_name')))->fetchField();
+    $this->configuration['owner_uid'] = $form_state->getValue('owner_uid');
   }
 
   /**
@@ -139,7 +141,7 @@ public function submitConfigurationForm(array &$form, FormStateInterface $form_s
   public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
     /** @var \Drupal\node\NodeInterface $object */
     $result = $object->access('update', $account, TRUE)
-      ->andIf($object->uid->access('edit', $account, TRUE));
+      ->andIf($object->getOwner()->access('edit', $account, TRUE));
 
     return $return_as_object ? $result : $result->isAllowed();
   }
diff --git a/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php b/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php
index 1fcdb72..85ae606 100644
--- a/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php
+++ b/core/modules/system/src/Tests/Entity/Element/EntityAutocompleteElementFormTest.php
@@ -282,7 +282,7 @@ public function testInvalidEntityAutocompleteElement() {
       ]);
     $form_builder->submitForm($this, $form_state);
 
-    // The input is complete (i.e. contains an entity ID at the ent), no errors
+    // The input is complete (i.e. contains an entity ID at the end), no errors
     // are triggered.
     $this->assertEqual(count($form_state->getErrors()), 0);
   }
diff --git a/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php b/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php
index c125653..b7bf65e 100644
--- a/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php
+++ b/core/modules/system/src/Tests/Entity/EntityReferenceSelection/EntityReferenceSelectionAccessTest.php
@@ -203,6 +203,7 @@ public function testUserHandler() {
       'handler' => 'default',
       'handler_settings' => array(
         'target_bundles' => array(),
+        'include_anonymous' => TRUE,
       ),
     );
 
@@ -320,6 +321,19 @@ public function testUserHandler() {
       ),
     );
     $this->assertReferenceable($selection_options, $referenceable_tests, 'User handler (admin)');
+
+    // Test the 'include_anonymous' option.
+    $selection_options['handler_settings']['include_anonymous'] = FALSE;
+    $referenceable_tests = array(
+      array(
+        'arguments' => array(
+          array('Anonymous', 'CONTAINS'),
+          array('anonymous', 'CONTAINS'),
+        ),
+        'result' => array(),
+      ),
+    );
+    $this->assertReferenceable($selection_options, $referenceable_tests, 'User handler (does not include anonymous)');
   }
 
   /**
diff --git a/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php b/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php
index 788f35a..d8f609a 100644
--- a/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php
+++ b/core/modules/system/tests/modules/theme_test/src/EventSubscriber/ThemeTestSubscriber.php
@@ -71,12 +71,11 @@ public function onRequest(GetResponseEvent $event) {
    */
   public function onView(GetResponseEvent $event) {
     $current_route = $this->currentRouteMatch->getRouteName();
-    $user_autcomplete_route = array(
-      'user.autocomplete',
-      'user.autocomplete_anonymous',
+    $entity_autcomplete_route = array(
+      'system.entity_autocomplete',
     );
 
-    if (in_array($current_route, $user_autcomplete_route)) {
+    if (in_array($current_route, $entity_autcomplete_route)) {
       if ($this->container->initialized('theme.registry')) {
         throw new \Exception('registry initialized');
       }
diff --git a/core/modules/user/src/Controller/UserAutocompleteController.php b/core/modules/user/src/Controller/UserAutocompleteController.php
deleted file mode 100644
index aca4e44..0000000
--- a/core/modules/user/src/Controller/UserAutocompleteController.php
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\Controller\UserAutocompleteController.
- */
-namespace Drupal\user\Controller;
-
-use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpFoundation\Request;
-use Symfony\Component\DependencyInjection\ContainerInterface;
-
-use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
-use Drupal\user\UserAutocomplete;
-
-/**
- * Controller routines for user routes.
- */
-class UserAutocompleteController implements ContainerInjectionInterface {
-
-  /**
-   * The user autocomplete helper class to find matching user names.
-   *
-   * @var \Drupal\user\UserAutocomplete
-   */
-  protected $userAutocomplete;
-
-  /**
-   * Constructs an UserAutocompleteController object.
-   *
-   * @param \Drupal\user\UserAutocomplete $user_autocomplete
-   *   The user autocomplete helper class to find matching user names.
-   */
-  public function __construct(UserAutocomplete $user_autocomplete) {
-    $this->userAutocomplete = $user_autocomplete;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public static function create(ContainerInterface $container) {
-    return new static(
-      $container->get('user.autocomplete')
-    );
-  }
-
-  /**
-   * Returns response for the user autocompletion.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request object containing the search string.
-   * @param bool $include_anonymous
-   *   (optional) TRUE if the name used to indicate anonymous users (e.g.
-   *   "Anonymous") should be autocompleted. Defaults to FALSE.
-   *
-   * @return \Symfony\Component\HttpFoundation\JsonResponse
-   *   A JSON response containing the autocomplete suggestions for existing users.
-   *
-   * @see \Drupal\user\UserAutocomplete::getMatches()
-   */
-  public function autocompleteUser(Request $request, $include_anonymous = FALSE) {
-    $matches = $this->userAutocomplete->getMatches($request->query->get('q'), $include_anonymous);
-
-    return new JsonResponse($matches);
-  }
-
-  /**
-   * Returns response for the user autocompletion with the anonymous user.
-   *
-   * @param \Symfony\Component\HttpFoundation\Request $request
-   *   The current request object containing the search string.
-   *
-   * @return \Symfony\Component\HttpFoundation\JsonResponse
-   *   A JSON response containing the autocomplete suggestions for existing users.
-   *
-   * @see \Drupal\user\UserAutocomplete::autocompleteUser()
-   */
-  public function autocompleteUserAnonymous(Request $request) {
-    return $this->autocompleteUser($request, TRUE);
-  }
-
-}
diff --git a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php
index 8d2e701..164006c 100644
--- a/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php
+++ b/core/modules/user/src/Plugin/EntityReferenceSelection/UserSelection.php
@@ -86,6 +86,13 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       'filter' => array(
         'type' => '_none',
       ),
+      'include_anonymous' => TRUE,
+    );
+
+    $form['include_anonymous'] = array(
+      '#type' => 'checkbox',
+      '#title' => $this->t('Include the anonymous user.'),
+      '#default_value' => $selection_handler_settings['include_anonymous'],
     );
 
     // Add user specific filter options.
@@ -156,6 +163,12 @@ protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS')
    * {@inheritdoc}
    */
   public function entityQueryAlter(SelectInterface $query) {
+    // Bail out early if we do not need to match the Anonymous user.
+    $handler_settings = $this->configuration['handler_settings'];
+    if (isset($handler_settings['include_anonymous']) && !$handler_settings['include_anonymous']) {
+      return;
+    }
+
     if ($this->currentUser->hasPermission('administer users')) {
       // In addition, if the user is administrator, we need to make sure to
       // match the anonymous user, that doesn't actually have a name in the
diff --git a/core/modules/user/src/Plugin/views/filter/Name.php b/core/modules/user/src/Plugin/views/filter/Name.php
index 76e642a..3cf6b79 100644
--- a/core/modules/user/src/Plugin/views/filter/Name.php
+++ b/core/modules/user/src/Plugin/views/filter/Name.php
@@ -8,7 +8,9 @@
 namespace Drupal\user\Plugin\views\filter;
 
 use Drupal\Component\Utility\Tags;
+use Drupal\Core\Entity\Element\EntityAutocomplete;
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\user\Entity\User;
 use Drupal\views\Plugin\views\filter\InOperator;
 
 /**
@@ -23,27 +25,16 @@ class Name extends InOperator {
   protected $alwaysMultiple = TRUE;
 
   protected function valueForm(&$form, FormStateInterface $form_state) {
-    $values = array();
-    if ($this->value) {
-      $result = entity_load_multiple_by_properties('user', array('uid' => $this->value));
-      foreach ($result as $account) {
-        if ($account->id()) {
-          $values[] = $account->getUsername();
-        }
-        else {
-          $values[] = 'Anonymous'; // Intentionally NOT translated.
-        }
-      }
-    }
-
-    sort($values);
-    $default_value = implode(', ', $values);
+    $users = $this->value ? User::loadMultiple($this->value) : array();
+    $default_value = EntityAutocomplete::getEntityLabels($users);
     $form['value'] = array(
-      '#type' => 'textfield',
+      '#type' => 'entity_autocomplete',
       '#title' => $this->t('Usernames'),
       '#description' => $this->t('Enter a comma separated list of user names.'),
+      '#target_type' => 'user',
+      '#tags' => TRUE,
       '#default_value' => $default_value,
-      '#autocomplete_route_name' => 'user.autocomplete_anonymous',
+      '#process_default_value' => FALSE,
     );
 
     $user_input = $form_state->getUserInput();
@@ -54,10 +45,14 @@ protected function valueForm(&$form, FormStateInterface $form_state) {
   }
 
   protected function valueValidate($form, FormStateInterface $form_state) {
-    $values = Tags::explode($form_state->getValue(array('options', 'value')));
-    if ($uids = $this->validate_user_strings($form['value'], $form_state, $values)) {
-      $form_state->setValue(array('options', 'value'), $uids);
+    $uids = [];
+    if ($values = $form_state->getValue(array('options', 'value'))) {
+      foreach ($values as $value) {
+        $uids[] = $value['target_id'];
+      }
+      sort($uids);
     }
+    $form_state->setValue(array('options', 'value'), $uids);
   }
 
   public function acceptExposedInput($input) {
@@ -90,13 +85,12 @@ public function validateExposed(&$form, FormStateInterface $form_state) {
       $input = $this->options['group_info']['group_items'][$input]['value'];
     }
 
-    $values = Tags::explode($input);
-
-    if (!$this->options['is_grouped'] || ($this->options['is_grouped'] && ($input != 'All'))) {
-      $uids = $this->validate_user_strings($form[$identifier], $form_state, $values);
-    }
-    else {
-      $uids = FALSE;
+    $uids = [];
+    $values = $form_state->getValue($identifier);
+    if ($values && (!$this->options['is_grouped'] || ($this->options['is_grouped'] && ($input != 'All')))) {
+      foreach ($values as $value) {
+        $uids[] = $value['target_id'];
+      }
     }
 
     if ($uids) {
@@ -104,43 +98,6 @@ public function validateExposed(&$form, FormStateInterface $form_state) {
     }
   }
 
-  /**
-   * Validate the user string. Since this can come from either the form
-   * or the exposed filter, this is abstracted out a bit so it can
-   * handle the multiple input sources.
-   */
-  function validate_user_strings(&$form, FormStateInterface $form_state, $values) {
-    $uids = array();
-    $placeholders = array();
-    $args = array();
-    foreach ($values as $value) {
-      if (strtolower($value) == 'anonymous') {
-        $uids[] = 0;
-      }
-      else {
-        $missing[strtolower($value)] = TRUE;
-        $args[] = $value;
-        $placeholders[] = "'%s'";
-      }
-    }
-
-    if (!$args) {
-      return $uids;
-    }
-
-    $result = entity_load_multiple_by_properties('user', array('name' => $args));
-    foreach ($result as $account) {
-      unset($missing[strtolower($account->getUsername())]);
-      $uids[] = $account->id();
-    }
-
-    if ($missing) {
-      $form_state->setError($form, $this->formatPlural(count($missing), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', array_keys($missing)))));
-    }
-
-    return $uids;
-  }
-
   protected function valueSubmit($form, FormStateInterface $form_state) {
     // prevent array filter from removing our anonymous user.
   }
diff --git a/core/modules/user/src/Tests/UserAutocompleteTest.php b/core/modules/user/src/Tests/UserAutocompleteTest.php
deleted file mode 100644
index 52fff32..0000000
--- a/core/modules/user/src/Tests/UserAutocompleteTest.php
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\user\Tests\UserAutocompleteTest.
- */
-
-namespace Drupal\user\Tests;
-
-use Drupal\Component\Utility\String;
-use Drupal\Component\Utility\Unicode;
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests user autocompletion functionality.
- *
- * @group user
- */
-class UserAutocompleteTest extends WebTestBase {
-
-  /**
-   * A regular user for testing.
-   *
-   * @var \Drupal\user\UserInterface
-   */
-  protected $unprivilegedUser;
-
-  /**
-   * A user with permission to access user profiles.
-   *
-   * @var \Drupal\user\UserInterface
-   */
-  protected $privilegedUser;
-
-  protected function setUp() {
-    parent::setUp();
-
-    // Set up two users with different permissions to test access.
-    $this->unprivilegedUser = $this->drupalCreateUser();
-    $this->privilegedUser = $this->drupalCreateUser(array('access user profiles'));
-  }
-
-  /**
-   * Tests access to user autocompletion and verify the correct results.
-   */
-  function testUserAutocomplete() {
-    // Check access from unprivileged user, should be denied.
-    $this->drupalLogin($this->unprivilegedUser);
-    $username = $this->unprivilegedUser->getUsername();
-    $this->drupalGet('user/autocomplete', array('query' => array('q' => $username[0])));
-    $this->assertResponse(403, 'Autocompletion access denied to user without permission.');
-
-    // Check access from privileged user.
-    $this->drupalLogout();
-    $this->drupalLogin($this->privilegedUser);
-    $this->drupalGet('user/autocomplete', array('query' => array('q' => $username[0])));
-    $this->assertResponse(200, 'Autocompletion access allowed.');
-
-    // Using first letter of the user's name, make sure the user's full name is
-    // in the results.
-    $this->assertRaw($this->unprivilegedUser->getUsername(), 'User name found in autocompletion results.');
-
-    $anonymous_name = $this->randomString() . '<script>alert();</script>';
-    $this->config('user.settings')->set('anonymous', $anonymous_name)->save();
-    // Test that anonymous username is in the result when requested and escaped
-    // with \Drupal\Component\Utility\String::checkPlain().
-    $users = $this->drupalGetJSON('user/autocomplete/anonymous', array('query' => array('q' => Unicode::substr($anonymous_name, 0, 4))));
-    $this->assertEqual(String::checkPlain($anonymous_name), $users[0]['label'], 'The anonymous name found in autocompletion results.');
-    $users = $this->drupalGetJSON('user/autocomplete', array('query' => array('q' => Unicode::substr($anonymous_name, 0, 4))));
-    $this->assertTrue(empty($users), 'The anonymous name not found in autocompletion results without enabling anonymous username.');
-  }
-}
diff --git a/core/modules/user/src/Tests/Views/HandlerFilterUserNameTest.php b/core/modules/user/src/Tests/Views/HandlerFilterUserNameTest.php
index 0faa52c..00bc8c0 100644
--- a/core/modules/user/src/Tests/Views/HandlerFilterUserNameTest.php
+++ b/core/modules/user/src/Tests/Views/HandlerFilterUserNameTest.php
@@ -102,8 +102,7 @@ public function testAdminUserInterface() {
       'options[value]' => implode(', ', $users)
     );
     $this->drupalPostForm($path, $edit, t('Apply'));
-    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
-    $this->assertText($message);
+    $this->assertRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
 
     // Pass in an invalid username and a valid username.
     $random_name = $this->randomMachineName();
@@ -114,8 +113,7 @@ public function testAdminUserInterface() {
     );
     $users = array($users[0]);
     $this->drupalPostForm($path, $edit, t('Apply'));
-    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
-    $this->assertRaw($message);
+    $this->assertRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
 
     // Pass in just valid usernames.
     $users = $this->names;
@@ -124,8 +122,7 @@ public function testAdminUserInterface() {
       'options[value]' => implode(', ', $users)
     );
     $this->drupalPostForm($path, $edit, t('Apply'));
-    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
-    $this->assertNoRaw($message);
+    $this->assertNoRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
   }
 
   /**
@@ -141,18 +138,16 @@ public function testExposedFilter() {
     $users = array_map('strtolower', $users);
     $options['query']['uid'] = implode(', ', $users);
     $this->drupalGet($path, $options);
-    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
-    $this->assertRaw($message);
+    $this->assertRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
 
     // Pass in an invalid username and a valid username.
     $users = array($this->randomMachineName(), $this->names[0]);
-    $options['query']['uid'] = implode(', ', $users);
     $users = array_map('strtolower', $users);
+    $options['query']['uid'] = implode(', ', $users);
     $users = array($users[0]);
 
     $this->drupalGet($path, $options);
-    $message = \Drupal::translation()->formatPlural(count($users), 'Unable to find user: @users', 'Unable to find users: @users', array('@users' => implode(', ', $users)));
-    $this->assertRaw($message);
+    $this->assertRaw(t('There are no entities matching "%value".', array('%value' => implode(', ', $users))));
 
     // Pass in just valid usernames.
     $users = $this->names;
diff --git a/core/modules/user/src/UserAutocomplete.php b/core/modules/user/src/UserAutocomplete.php
deleted file mode 100644
index d32c166..0000000
--- a/core/modules/user/src/UserAutocomplete.php
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\user\UserAutocomplete.
- */
-
-namespace Drupal\user;
-
-use Drupal\Component\Utility\String;
-use Drupal\Core\Config\ConfigFactoryInterface;
-use Drupal\Core\Entity\EntityManagerInterface;
-use Drupal\Core\Entity\Query\QueryFactory;
-
-/**
- * Defines a helper class to get user autocompletion results.
- */
-class UserAutocomplete {
-
-  /**
-   * The config factory to get the anonymous user name.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected $configFactory;
-
-  /**
-   * The entity query factory service.
-   *
-   * @var \Drupal\Core\Entity\Query\QueryFactory
-   */
-  protected $entityQuery;
-
-  /**
-   * The entity manager service.
-   *
-   * @var \Drupal\Core\Entity\EntityManagerInterface
-   */
-  protected $entityManager;
-
-  /**
-   * Constructs a UserAutocomplete object.
-   *
-   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
-   *   The config factory.
-   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
-   *   The entity manager.
-   * @param \Drupal\Core\Entity\Query\QueryFactory $entity_query
-   *   The entity query factory.
-   */
-  public function __construct(ConfigFactoryInterface $config_factory, EntityManagerInterface $entity_manager, QueryFactory $entity_query) {
-    $this->configFactory = $config_factory;
-    $this->entityQuery = $entity_query;
-    $this->entityManager = $entity_manager;
-  }
-
-  /**
-   * Get matches for the autocompletion of user names.
-   *
-   * @param string $string
-   *   The string to match for usernames.
-   *
-   * @param bool $include_anonymous
-   *   (optional) TRUE if the name used to indicate anonymous users (e.g.
-   *   "Anonymous") should be autocompleted. Defaults to FALSE.
-   *
-   * @return array
-   *   An array containing the matching usernames.
-   */
-  public function getMatches($string, $include_anonymous = FALSE) {
-    $matches = array();
-    if ($string) {
-      if ($include_anonymous) {
-        $anonymous_name = $this->configFactory->get('user.settings')->get('anonymous');
-        // Allow autocompletion for the anonymous user.
-        if (stripos($anonymous_name, $string) !== FALSE) {
-          $matches[] = array('value' => $anonymous_name, 'label' => String::checkPlain($anonymous_name));
-        }
-      }
-      $uids = $this->entityQuery->get('user')
-        ->condition('name', $string, 'STARTS_WITH')
-        ->range(0, 10)
-        ->execute();
-
-      $controller = $this->entityManager->getStorage('user');
-      foreach ($controller->loadMultiple($uids) as $account) {
-        $matches[] = array('value' => $account->getUsername(), 'label' => String::checkPlain($account->getUsername()));
-      }
-    }
-
-    return $matches;
-  }
-
-}
diff --git a/core/modules/user/user.routing.yml b/core/modules/user/user.routing.yml
index 4f6a263..d30770f 100644
--- a/core/modules/user/user.routing.yml
+++ b/core/modules/user/user.routing.yml
@@ -13,20 +13,6 @@ user.logout:
   requirements:
     _user_is_logged_in: 'TRUE'
 
-user.autocomplete:
-  path: '/user/autocomplete'
-  defaults:
-    _controller: '\Drupal\user\Controller\UserAutocompleteController::autocompleteUser'
-  requirements:
-    _permission: 'access user profiles'
-
-user.autocomplete_anonymous:
-  path: '/user/autocomplete/anonymous'
-  defaults:
-    _controller: '\Drupal\user\Controller\UserAutocompleteController::autocompleteUserAnonymous'
-  requirements:
-    _permission: 'access user profiles'
-
 user.admin_index:
   path: '/admin/config/people'
   defaults:
diff --git a/core/modules/user/user.services.yml b/core/modules/user/user.services.yml
index 5bec22c..50405b5 100644
--- a/core/modules/user/user.services.yml
+++ b/core/modules/user/user.services.yml
@@ -34,9 +34,6 @@ services:
     arguments: ['@database']
     tags:
       - { name: backend_overridable }
-  user.autocomplete:
-    class: Drupal\user\UserAutocomplete
-    arguments: ['@config.factory', '@entity.manager', '@entity.query']
   user_maintenance_mode_subscriber:
     class: Drupal\user\EventSubscriber\MaintenanceModeSubscriber
     arguments: ['@maintenance_mode', '@current_user']
