diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index f5812c6..7c3a4c3 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -115,7 +115,7 @@ function datetime_field_info() {
 /**
  * Implements hook_field_settings_form().
  */
-function datetime_field_settings_form($field, $instance, $has_data) {
+function datetime_field_settings_form($field, $instance) {
   $settings = $field['settings'];
 
   $form['datetime_type'] = array(
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 5608b6b..e125a8e 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -143,7 +143,7 @@ function entity_reference_field_validate(EntityInterface $entity = NULL, $field,
 /**
  * Implements hook_field_settings_form().
  */
-function entity_reference_field_settings_form($field, $instance, $has_data) {
+function entity_reference_field_settings_form($field, $instance) {
   // Select the target entity type.
   $entity_type_options = array();
   foreach (entity_get_info() as $entity_type => $entity_info) {
@@ -161,7 +161,7 @@ function entity_reference_field_settings_form($field, $instance, $has_data) {
     '#options' => $entity_type_options,
     '#default_value' => $field['settings']['target_type'],
     '#required' => TRUE,
-    '#disabled' => $has_data,
+    '#disabled' => $field->hasData(),
     '#size' => 1,
   );
 
@@ -173,7 +173,7 @@ function entity_reference_field_settings_form($field, $instance, $has_data) {
  *
  * Reset the instance handler settings, when the target type is changed.
  */
-function entity_reference_field_update_field($field, $prior_field, $has_data) {
+function entity_reference_field_update_field($field, $prior_field) {
   if ($field['type'] != 'entity_reference') {
     // Not an entity reference field.
     return;
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 75a99df..4b5c565 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -541,11 +541,9 @@ function hook_field_update(\Drupal\Core\Entity\EntityInterface $entity, $field,
  *   The updated field structure to be saved.
  * @param $prior_field
  *   The previously-saved field structure.
- * @param $has_data
- *   TRUE if the field has data in storage currently.
  */
-function hook_field_storage_update_field($field, $prior_field, $has_data) {
-  if (!$has_data) {
+function hook_field_storage_update_field($field, $prior_field) {
+  if (!$field->hasData()) {
     // There is no data. Re-create the tables completely.
     $prior_schema = _field_sql_storage_schema($prior_field);
     foreach ($prior_schema as $name => $table) {
@@ -1863,15 +1861,13 @@ function hook_field_create_instance($instance) {
  *   The field as it will be post-update.
  * @param $prior_field
  *   The field as it is pre-update.
- * @param $has_data
- *   Whether any data already exists for this field.
  */
-function hook_field_update_forbid($field, $prior_field, $has_data) {
+function hook_field_update_forbid($field, $prior_field) {
   // A 'list' field stores integer keys mapped to display values. If
   // the new field will have fewer values, and any data exists for the
   // abandoned keys, the field will have no way to display them. So,
   // forbid such an update.
-  if ($has_data && count($field['settings']['allowed_values']) < count($prior_field['settings']['allowed_values'])) {
+  if ($field->hasData() && count($field['settings']['allowed_values']) < count($prior_field['settings']['allowed_values'])) {
     // Identify the keys that will be lost.
     $lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($prior_field['settings']['allowed_values']));
     // If any data exist for those keys, forbid the update.
@@ -1897,10 +1893,8 @@ function hook_field_update_forbid($field, $prior_field, $has_data) {
  *   The field as it is post-update.
  * @param $prior_field
  *   The field as it was pre-update.
- * @param $has_data
- *   Whether any data already exists for this field.
  */
-function hook_field_update_field($field, $prior_field, $has_data) {
+function hook_field_update_field($field, $prior_field) {
   // Reset the static value that keeps track of allowed values for list fields.
   drupal_static_reset('list_allowed_values');
 }
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 798d604..41605e0 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -884,43 +884,6 @@ function field_get_items(EntityInterface $entity, $field_name, $langcode = NULL)
 }
 
 /**
- * Determines whether a field has any data.
- *
- * @param $field
- *   A field structure.
- *
- * @return
- *   TRUE if the field has data for any entity; FALSE otherwise.
- */
-function field_has_data($field) {
-  $columns = array_keys($field['columns']);
-  $factory = Drupal::service('entity.query');
-  foreach ($field['bundles'] as $entity_type => $bundle) {
-    // Entity Query throws an exception if there is no base table.
-    $entity_info = entity_get_info($entity_type);
-    if (!isset($entity_info['base_table'])) {
-      continue;
-    }
-    $query = $factory->get($entity_type);
-    $group = $query->orConditionGroup();
-    foreach ($columns as $column) {
-      $group->exists($field['field_name'] . '.' . $column);
-    }
-    $result = $query
-      ->condition($group)
-      ->count()
-      ->accessCheck(FALSE)
-      ->range(0, 1)
-      ->execute();
-    if ($result) {
-      return TRUE;
-    }
-  }
-
-  return FALSE;
-}
-
-/**
  * Determines whether the user has access to a given field.
  *
  * @param string $op
diff --git a/core/modules/field/lib/Drupal/field/FieldUpdateForbiddenException.php b/core/modules/field/lib/Drupal/field/FieldUpdateForbiddenException.php
index 6bf914f..a63132a 100644
--- a/core/modules/field/lib/Drupal/field/FieldUpdateForbiddenException.php
+++ b/core/modules/field/lib/Drupal/field/FieldUpdateForbiddenException.php
@@ -1,8 +1,8 @@
 <?php
 
-/*
+/**
  * @file
- * Definition of Drupal\field\FieldUpdateForbiddenException.
+ * Contains \Drupal\field\FieldUpdateForbiddenException.
  */
 
 namespace Drupal\field;
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
index 872a8d0..cf4e470 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/Field.php
@@ -420,17 +420,15 @@ protected function saveUpdated() {
     // objects.
     $this->settings += $original->settings;
 
-    $has_data = field_has_data($this);
-
     // See if any module forbids the update by throwing an exception. This
     // invokes hook_field_update_forbid().
-    $module_handler->invokeAll('field_update_forbid', array($this, $original, $has_data));
+    $module_handler->invokeAll('field_update_forbid', array($this, $original));
 
     // Tell the storage engine to update the field by invoking the
     // hook_field_storage_update_field(). The storage engine can reject the
     // definition update as invalid by raising an exception, which stops
     // execution before the definition is written to config.
-    $module_handler->invoke($this->storage['module'], 'field_storage_update_field', array($this, $original, $has_data));
+    $module_handler->invoke($this->storage['module'], 'field_storage_update_field', array($this, $original));
 
     // Save the configuration.
     $result = parent::save();
@@ -438,7 +436,7 @@ protected function saveUpdated() {
 
     // Invoke hook_field_update_field() after the cache is cleared for API
     // consistency.
-    $module_handler->invokeAll('field_update_field', array($this, $original, $has_data));
+    $module_handler->invokeAll('field_update_field', array($this, $original));
 
     return $result;
   }
@@ -633,4 +631,38 @@ public static function getReservedColumns() {
     return array('deleted');
   }
 
+  /**
+   * Determines whether a field has any data.
+   *
+   * @return
+   *   TRUE if the field has data for any entity; FALSE otherwise.
+   */
+  public function hasData() {
+    $storage_details = $this->getSchema();
+    $columns = array_keys($storage_details['columns']);
+    $factory = \Drupal::service('entity.query');
+    foreach ($this->getBundles() as $entity_type => $bundle) {
+      // Entity Query throws an exception if there is no base table.
+      $entity_info = \Drupal::entityManager()->getDefinition($entity_type);
+      if (!isset($entity_info['base_table'])) {
+        continue;
+      }
+      $query = $factory->get($entity_type);
+      $group = $query->orConditionGroup();
+      foreach ($columns as $column) {
+        $group->exists($this->id() . '.' . $column);
+      }
+      $result = $query
+        ->condition($group)
+        ->count()
+        ->accessCheck(FALSE)
+        ->range(0, 1)
+        ->execute();
+      if ($result) {
+        return TRUE;
+      }
+    }
+
+    return FALSE;
+  }
 }
diff --git a/core/modules/field/tests/modules/field_test/field_test.field.inc b/core/modules/field/tests/modules/field_test/field_test.field.inc
index d2f4a94..01b08c8 100644
--- a/core/modules/field/tests/modules/field_test/field_test.field.inc
+++ b/core/modules/field/tests/modules/field_test/field_test.field.inc
@@ -63,7 +63,7 @@ function field_test_field_widget_info_alter(&$info) {
 /**
  * Implements hook_field_update_forbid().
  */
-function field_test_field_update_forbid($field, $prior_field, $has_data) {
+function field_test_field_update_forbid($field, $prior_field) {
   if ($field['type'] == 'test_field' && $field['settings']['unchangeable'] != $prior_field['settings']['unchangeable']) {
     throw new FieldException("field_test 'unchangeable' setting cannot be changed'");
   }
@@ -144,7 +144,7 @@ function field_test_field_is_empty($item, $field) {
 /**
  * Implements hook_field_settings_form().
  */
-function field_test_field_settings_form($field, $instance, $has_data) {
+function field_test_field_settings_form($field, $instance) {
   $settings = $field['settings'];
 
   $form['test_field_setting'] = array(
diff --git a/core/modules/field_sql_storage/field_sql_storage.module b/core/modules/field_sql_storage/field_sql_storage.module
index dcbe476..3ccac54 100644
--- a/core/modules/field_sql_storage/field_sql_storage.module
+++ b/core/modules/field_sql_storage/field_sql_storage.module
@@ -266,8 +266,8 @@ function field_sql_storage_field_create_field($field) {
  * Forbids any field update that changes column definitions if there is any
  * data.
  */
-function field_sql_storage_field_update_forbid($field, $prior_field, $has_data) {
-  if ($has_data && $field['columns'] != $prior_field['columns']) {
+function field_sql_storage_field_update_forbid($field, $prior_field) {
+  if ($field->hasData() && $field['columns'] != $prior_field['columns']) {
     throw new FieldUpdateForbiddenException("field_sql_storage cannot change the schema for an existing field with data.");
   }
 }
@@ -275,8 +275,8 @@ function field_sql_storage_field_update_forbid($field, $prior_field, $has_data)
 /**
  * Implements hook_field_storage_update_field().
  */
-function field_sql_storage_field_storage_update_field($field, $prior_field, $has_data) {
-  if (! $has_data) {
+function field_sql_storage_field_storage_update_field($field, $prior_field) {
+  if (!$field->hasData()) {
     // There is no data. Re-create the tables completely.
 
     if (Database::getConnection()->supportsTransactionalDDL()) {
diff --git a/core/modules/field_ui/field_ui.api.php b/core/modules/field_ui/field_ui.api.php
index 81a5f3b..b3bf03e 100644
--- a/core/modules/field_ui/field_ui.api.php
+++ b/core/modules/field_ui/field_ui.api.php
@@ -29,13 +29,11 @@
  *   The field structure being configured.
  * @param $instance
  *   The instance structure being configured.
- * @param $has_data
- *   TRUE if the field already has data, FALSE if not.
  *
  * @return
  *   The form definition for the field settings.
  */
-function hook_field_settings_form($field, $instance, $has_data) {
+function hook_field_settings_form($field, $instance) {
   $settings = $field['settings'];
   $form['max_length'] = array(
     '#type' => 'number',
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
index 556a73d..c2f0a45 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldEditForm.php
@@ -82,8 +82,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
 
     // See if data already exists for this field.
     // If so, prevent changes to the field settings.
-    $has_data = field_has_data($field);
-    if ($has_data) {
+    if ($field->hasData()) {
       $form['field']['#prefix'] = '<div class="messages messages--error">' . t('There is data for this field in the database. The field settings can no longer be changed.') . '</div>' . $form['field']['#prefix'];
     }
 
@@ -135,7 +134,7 @@ public function buildForm(array $form, array &$form_state, FieldInstanceInterfac
     $form['field']['settings'] = array(
       '#weight' => 10,
     );
-    $additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_settings_form', array($field, $this->instance, $has_data));
+    $additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_settings_form', array($field, $this->instance));
     if (is_array($additions)) {
       $form['field']['settings'] += $additions;
     }
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index cb76631..6aadd75 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -37,7 +37,7 @@ function file_field_info() {
 /**
  * Implements hook_field_settings_form().
  */
-function file_field_settings_form($field, $instance, $has_data) {
+function file_field_settings_form($field, $instance) {
   $defaults = field_info_field_settings($field['type']);
   $settings = array_merge($defaults, $field['settings']);
 
@@ -71,7 +71,7 @@ function file_field_settings_form($field, $instance, $has_data) {
     '#options' => $scheme_options,
     '#default_value' => $settings['uri_scheme'],
     '#description' => t('Select where the final files should be stored. Private file storage has significantly more overhead than public files, but allows restricted access to files within this field.'),
-    '#disabled' => $has_data,
+    '#disabled' => $field->hasData(),
   );
 
   return $form;
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index e8dc3d4..bdcb5e9 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -364,7 +364,7 @@ function image_field_delete_field($field) {
 /**
  * Implements hook_field_update_field().
  */
-function image_field_update_field($field, $prior_field, $has_data) {
+function image_field_update_field($field, $prior_field) {
   if ($field['type'] != 'image') {
     return;
   }
diff --git a/core/modules/number/number.module b/core/modules/number/number.module
index 4615519..afb7fa1 100644
--- a/core/modules/number/number.module
+++ b/core/modules/number/number.module
@@ -56,7 +56,7 @@ function number_field_info() {
 /**
  * Implements hook_field_settings_form().
  */
-function number_field_settings_form($field, $instance, $has_data) {
+function number_field_settings_form($field, $instance) {
   $settings = $field['settings'];
   $form = array();
 
@@ -67,7 +67,7 @@ function number_field_settings_form($field, $instance, $has_data) {
       '#options' => drupal_map_assoc(range(10, 32)),
       '#default_value' => $settings['precision'],
       '#description' => t('The total number of digits to store in the database, including those to the right of the decimal.'),
-      '#disabled' => $has_data,
+      '#disabled' => $field->hasData(),
     );
     $form['scale'] = array(
       '#type' => 'select',
@@ -75,7 +75,7 @@ function number_field_settings_form($field, $instance, $has_data) {
       '#options' => drupal_map_assoc(range(0, 10)),
       '#default_value' => $settings['scale'],
       '#description' => t('The number of digits to the right of the decimal.'),
-      '#disabled' => $has_data,
+      '#disabled' => $field->hasData(),
     );
   }
 
diff --git a/core/modules/options/options.module b/core/modules/options/options.module
index 0d8ec00..f1ea565 100644
--- a/core/modules/options/options.module
+++ b/core/modules/options/options.module
@@ -66,7 +66,7 @@ function options_field_info() {
 /**
  * Implements hook_field_settings_form().
  */
-function options_field_settings_form($field, $instance, $has_data) {
+function options_field_settings_form($field, $instance) {
   $settings = $field['settings'];
 
   switch ($field['type']) {
@@ -79,7 +79,7 @@ function options_field_settings_form($field, $instance, $has_data) {
         '#default_value' => options_allowed_values_string($settings['allowed_values']),
         '#rows' => 10,
         '#element_validate' => array('options_field_settings_form_validate_allowed_values'),
-        '#field_has_data' => $has_data,
+        '#field_has_data' => $field->hasData(),
         '#field' => $field,
         '#field_type' => $field['type'],
         '#access' => empty($settings['allowed_values_function']),
@@ -215,7 +215,7 @@ function options_field_settings_form_value_boolean_allowed_values($element, $inp
 /**
  * Implements hook_field_update_field().
  */
-function options_field_update_field($field, $prior_field, $has_data) {
+function options_field_update_field($field, $prior_field) {
   drupal_static_reset('options_allowed_values');
 }
 
@@ -360,8 +360,8 @@ function options_allowed_values_string($values) {
 /**
  * Implements hook_field_update_forbid().
  */
-function options_field_update_forbid($field, $prior_field, $has_data) {
-  if ($field['module'] == 'options' && $has_data) {
+function options_field_update_forbid($field, $prior_field) {
+  if ($field['module'] == 'options' && $field->hasData()) {
     // Forbid any update that removes allowed values with actual data.
     $lost_keys = array_diff(array_keys($prior_field['settings']['allowed_values']), array_keys($field['settings']['allowed_values']));
     if (_options_values_in_use($field, $lost_keys)) {
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 6ed67a1..7169238 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -1055,7 +1055,7 @@ function taxonomy_autocomplete_validate($element, &$form_state) {
 /**
  * Implements hook_field_settings_form().
  */
-function taxonomy_field_settings_form($field, $instance, $has_data) {
+function taxonomy_field_settings_form($field, $instance) {
   // Get proper values for 'allowed_values_function', which is a core setting.
   $vocabularies = taxonomy_vocabulary_load_multiple();
   $options = array();
@@ -1074,7 +1074,7 @@ function taxonomy_field_settings_form($field, $instance, $has_data) {
       '#options' => $options,
       '#required' => TRUE,
       '#description' => t('The vocabulary which supplies the options for this field.'),
-      '#disabled' => $has_data,
+      '#disabled' => $field->hasData(),
     );
     $form['allowed_values'][$delta]['parent'] = array(
       '#type' => 'value',
diff --git a/core/modules/text/text.module b/core/modules/text/text.module
index 4fe2115..2cd5dcf 100644
--- a/core/modules/text/text.module
+++ b/core/modules/text/text.module
@@ -84,7 +84,7 @@ function text_field_info() {
 /**
  * Implements hook_field_settings_form().
  */
-function text_field_settings_form($field, $instance, $has_data) {
+function text_field_settings_form($field, $instance) {
   $settings = $field['settings'];
 
   $form = array();
@@ -99,7 +99,7 @@ function text_field_settings_form($field, $instance, $has_data) {
       '#min' => 1,
       // @todo: If $has_data, add a validate handler that only allows
       // max_length to increase.
-      '#disabled' => $has_data,
+      '#disabled' => $field->hasData(),
     );
   }
 
diff --git a/core/modules/translation_entity/translation_entity.admin.inc b/core/modules/translation_entity/translation_entity.admin.inc
index dd7874c..7b25917 100644
--- a/core/modules/translation_entity/translation_entity.admin.inc
+++ b/core/modules/translation_entity/translation_entity.admin.inc
@@ -346,7 +346,7 @@ function _translation_entity_update_field_translatability($settings) {
       $field_operations = array(
         array('translation_entity_translatable_switch', array($translatable, $field_name)),
       );
-      if (field_has_data($field)) {
+      if ($field->hasData()) {
         $field_operations[] = array('translation_entity_translatable_batch', array($translatable, $field_name));
         $field_operations = $translatable ? $field_operations : array_reverse($field_operations);
       }
diff --git a/core/modules/translation_entity/translation_entity.module b/core/modules/translation_entity/translation_entity.module
index 6f6c740..9f78d89 100644
--- a/core/modules/translation_entity/translation_entity.module
+++ b/core/modules/translation_entity/translation_entity.module
@@ -810,7 +810,7 @@ function translation_entity_form_field_ui_field_edit_form_alter(array &$form, ar
   $translatable = $field['translatable'];
   $label = t('Field translation');
 
-  if (field_has_data($field)) {
+  if ($field->hasData()) {
     $form['field']['translatable'] = array(
       '#type' => 'item',
       '#title' => $label,
