diff --git a/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php b/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php
new file mode 100644
index 0000000..56e23ff
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/Field/FieldDefinitionInterface.php
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\Core\Entity\Field\FieldDefinitionInterface.
+ */
+
+namespace Drupal\Core\Entity\Field;
+
+/**
+ * @todo Document
+ */
+interface FieldDefinitionInterface {
+
+  public function getFieldName();
+  public function getFieldType();
+  public function getFieldSettings();
+  public function getFieldSetting($setting_name);
+  public function getFieldPropertyNames();
+  public function isFieldTranslatable();
+  public function getFieldLabel();
+  public function getFieldDescription();
+  public function getFieldCardinality();
+  public function isFieldRequired();
+
+}
diff --git a/core/modules/datetime/datetime.module b/core/modules/datetime/datetime.module
index b545c36..5ad7fa4 100644
--- a/core/modules/datetime/datetime.module
+++ b/core/modules/datetime/datetime.module
@@ -82,7 +82,7 @@ function datetime_theme() {
 /**
  * Implements hook_field_is_empty().
  */
-function datetime_field_is_empty($item, $field) {
+function datetime_field_is_empty($item, $field_type) {
   if (empty($item['value'])) {
     return TRUE;
   }
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
index d5610f3..f2eff9f 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimeDefaultFormatter.php
@@ -53,7 +53,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
 
         // The formatted output will be in local time.
         $date->setTimeZone(timezone_open(drupal_get_user_timezone()));
-        if ($this->field['settings']['datetime_type'] == 'date') {
+        if ($this->getFieldSetting('datetime_type') == 'date') {
           // A date without time will pick up the current time, use the default.
           datetime_date_default_time($date);
         }
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
index 45a85a2..e385c69 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/formatter/DatetimePlainFormatter.php
@@ -28,7 +28,7 @@
 class DateTimePlainFormatter extends FormatterBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Formatter\FormatterInterface::viewElements().
+   * {@inheritdoc}
    */
   public function viewElements(EntityInterface $entity, $langcode, array $items) {
 
@@ -43,7 +43,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
         $date = $item['date'];
         $date->setTimeZone(timezone_open(drupal_get_user_timezone()));
         $format = DATETIME_DATETIME_STORAGE_FORMAT;
-        if ($this->field['settings']['datetime_type'] == 'date') {
+        if ($this->getFieldSetting('datetime_type') == 'date') {
           // A date without time will pick up the current time, use the default.
           datetime_date_default_time($date);
           $format = DATETIME_DATE_STORAGE_FORMAT;
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
index f0d60fe..610f6fd 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDatelistWidget.php
@@ -11,8 +11,9 @@
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\field\FieldInstanceInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
 use Drupal\datetime\DateHelper;
 
@@ -38,10 +39,14 @@ class DateTimeDatelistWidget extends WidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) {
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
     // Identify the function used to set the default value.
-    $instance['default_value_function'] = $this->defaultValueFunction();
-    parent::__construct($plugin_id, $plugin_definition, $instance, $settings);
+    // @todo Make this work for both configurable and nonconfigurable fields:
+    //   https://drupal.org/node/1989468.
+    if ($field_definition instanceof FieldInstanceInterface) {
+      $field_definition->default_value_function = $this->defaultValueFunction();
+    }
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings);
   }
 
   /**
@@ -55,13 +60,9 @@ public function defaultValueFunction() {
   }
 
   /**
-   * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-
-    $field = $this->field;
-    $instance = $this->instance;
-
     $date_order = $this->getSetting('date_order');
     $time_type = $this->getSetting('time_type');
     $increment = $this->getSetting('increment');
@@ -78,7 +79,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element['#element_validate'][] = 'datetime_datelist_widget_validate';
 
     // Identify the type of date and time elements to use.
-    switch ($field['settings']['datetime_type']) {
+    switch ($this->getFieldSetting('datetime_type')) {
       case 'date':
         $storage_format = DATETIME_DATE_STORAGE_FORMAT;
         $type_type = 'none';
@@ -126,7 +127,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     );
 
     // Set the storage and widget options so the validation can use them. The
-    // validator will not have access to field or instance settings.
+    // validator will not have access to the field definition.
     $element['value']['#date_storage_format'] = $storage_format;
 
     if (!empty($items[$delta]['date'])) {
@@ -134,7 +135,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       // The date was created and verified during field_load(), so it is safe to
       // use without further inspection.
       $date->setTimezone( new \DateTimeZone($element['value']['#date_timezone']));
-      if ($field['settings']['datetime_type'] == 'date') {
+      if ($this->getFieldSetting('datetime_type') == 'date') {
         // A date without time will pick up the current time, use the default
         // time.
         datetime_date_default_time($date);
@@ -145,22 +146,11 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   *
-   *
-   * @param array $form
-   *   The form definition as an array.
-   * @param array $form_state
-   *   The current state of the form as an array.
-   *
-   * @return array
-   *
+   * {@inheritdoc}
    */
   function settingsForm(array $form, array &$form_state) {
     $element = parent::settingsForm($form, $form_state);
 
-    $field = $this->field;
-    $instance = $this->instance;
-
     $element['date_order'] = array(
       '#type' => 'select',
       '#title' => t('Date part order'),
@@ -168,7 +158,7 @@ function settingsForm(array $form, array &$form_state) {
       '#options' => array('MDY' => t('Month/Day/Year'), 'DMY' => t('Day/Month/Year'), 'YMD' => t('Year/Month/Day')),
     );
 
-    if ($field['settings']['datetime_type'] == 'datetime') {
+    if ($this->getFieldSetting('datetime_type') == 'datetime') {
       $element['time_type'] = array(
         '#type' => 'select',
         '#title' => t('Time type'),
diff --git a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
index f0c45c0..79f12bc 100644
--- a/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
+++ b/core/modules/datetime/lib/Drupal/datetime/Plugin/field/widget/DatetimeDefaultWidget.php
@@ -11,8 +11,9 @@
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 use Drupal\Component\Plugin\Discovery\DiscoveryInterface;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\field\FieldInstanceInterface;
 use Drupal\Core\Datetime\DrupalDateTime;
 
 /**
@@ -32,10 +33,14 @@ class DateTimeDefaultWidget extends WidgetBase {
   /**
    * {@inheritdoc}
    */
-  public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) {
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
     // Identify the function used to set the default value.
-    $instance['default_value_function'] = $this->defaultValueFunction();
-    parent::__construct($plugin_id, $plugin_definition, $instance, $settings);
+    // @todo Make this work for both configurable and nonconfigurable fields:
+    //   https://drupal.org/node/1989468.
+    if ($field_definition instanceof FieldInstanceInterface) {
+      $field_definition->default_value_function = $this->defaultValueFunction();
+    }
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings);
   }
 
   /**
@@ -49,13 +54,9 @@ public function defaultValueFunction() {
   }
 
   /**
-   * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
-   *
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-
-    $field = $this->field;
-    $instance = $this->instance;
     $format_type = datetime_default_format_type();
 
     // We are nesting some sub-elements inside the parent, so we need a wrapper.
@@ -69,7 +70,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element['#element_validate'][] = 'datetime_datetime_widget_validate';
 
     // Identify the type of date and time elements to use.
-    switch ($field['settings']['datetime_type']) {
+    switch ($this->getFieldSetting('datetime_type')) {
       case 'date':
         $date_type = 'date';
         $time_type = 'none';
@@ -104,7 +105,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     );
 
     // Set the storage and widget options so the validation can use them. The
-    // validator will not have access to field or instance settings.
+    // validator will not have access to the field definition.
     $element['value']['#date_element_format'] = $element_format;
     $element['value']['#date_storage_format'] = $storage_format;
 
@@ -113,7 +114,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       // The date was created and verified during field_load(), so it is safe to
       // use without further inspection.
       $date->setTimezone(new \DateTimeZone($element['value']['#date_timezone']));
-      if ($field['settings']['datetime_type'] == 'date') {
+      if ($this->getFieldSetting('datetime_type') == 'date') {
         // A date without time will pick up the current time, use the default
         // time.
         datetime_date_default_time($date);
diff --git a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
index f7f0c06..e139d0e 100644
--- a/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
+++ b/core/modules/edit/lib/Drupal/edit/Access/EditEntityFieldAccessCheck.php
@@ -41,7 +41,7 @@ public function access(Route $route, Request $request) {
    * Implements EntityFieldAccessCheckInterface::accessEditEntityField().
    */
   public function accessEditEntityField(EntityInterface $entity, $field_name) {
-    return $entity->access('update') && field_access('edit', $field_name, $entity->entityType(), $entity);
+    return $entity->access('update') && ($field = field_info_field($field_name)) && field_access('edit', $field, $entity->entityType(), $entity);
   }
 
   /**
diff --git a/core/modules/email/email.module b/core/modules/email/email.module
index 73e427e..28b9b21 100644
--- a/core/modules/email/email.module
+++ b/core/modules/email/email.module
@@ -45,7 +45,7 @@ function email_field_info_alter(&$info) {
 /**
  * Implements hook_field_is_empty().
  */
-function email_field_is_empty($item, $field) {
+function email_field_is_empty($item, $field_type) {
   return !isset($item['value']) || $item['value'] === '';
 }
 
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
index 6f4f20e..f8c3f5b 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php
@@ -54,7 +54,7 @@ public function getFormatter($field_name) {
     if ($configuration = $this->getComponent($field_name)) {
       $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle);
       $formatter = $this->pluginManager->getInstance(array(
-        'instance' => $instance,
+        'field_definition' => $instance,
         'view_mode' => $this->originalMode,
         // No need to prepare, defaults have been merged in setComponent().
         'prepare' => FALSE,
diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
index 9f6425b..8c72986 100644
--- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
+++ b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityFormDisplay.php
@@ -54,7 +54,7 @@ public function getWidget($field_name) {
     if ($configuration = $this->getComponent($field_name)) {
       $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle);
       $widget = $this->pluginManager->getInstance(array(
-        'instance' => $instance,
+        'field_definition' => $instance,
         'form_mode' => $this->originalMode,
         // No need to prepare, defaults have been merged in setComponent().
         'prepare' => FALSE,
diff --git a/core/modules/entity_reference/entity_reference.module b/core/modules/entity_reference/entity_reference.module
index 97e9db0..3841a70 100644
--- a/core/modules/entity_reference/entity_reference.module
+++ b/core/modules/entity_reference/entity_reference.module
@@ -8,6 +8,7 @@
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Database\Query\AlterableInterface;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 
 /**
  * Implements hook_field_info().
@@ -80,10 +81,9 @@ function entity_reference_field_widget_info_alter(&$info) {
  *
  * @return \Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface
  */
-function entity_reference_get_selection_handler($field, $instance, EntityInterface $entity = NULL) {
+function entity_reference_get_selection_handler(FieldDefinitionInterface $field_definition, EntityInterface $entity = NULL) {
   $options = array(
-    'field' => $field,
-    'instance' => $instance,
+    'field_definition' => $field_definition,
     'entity' => $entity,
   );
   return Drupal::service('plugin.manager.entity_reference.selection')->getInstance($options);
@@ -92,7 +92,7 @@ function entity_reference_get_selection_handler($field, $instance, EntityInterfa
 /**
  * Implements hook_field_is_empty().
  */
-function entity_reference_field_is_empty($item, $field) {
+function entity_reference_field_is_empty($item, $field_type) {
   if (!empty($item['target_id']) && $item['target_id'] == 'auto_create') {
     // Allow auto-create entities.
     return FALSE;
@@ -149,7 +149,7 @@ function entity_reference_field_validate(EntityInterface $entity = NULL, $field,
   }
 
   if ($ids) {
-    $valid_ids = entity_reference_get_selection_handler($field, $instance, $entity)->validateReferencableEntities(array_keys($ids));
+    $valid_ids = entity_reference_get_selection_handler($instance, $entity)->validateReferencableEntities(array_keys($ids));
 
     $invalid_entities = array_diff_key($ids, array_flip($valid_ids));
     if ($invalid_entities) {
@@ -290,7 +290,7 @@ function entity_reference_field_instance_settings_form($field, $instance, $form_
     '#attributes' => array('class' => array('entity_reference-settings')),
   );
 
-  $handler = entity_reference_get_selection_handler($field, $instance);
+  $handler = entity_reference_get_selection_handler($instance);
   $form['handler']['handler_settings'] += $handler->settingsForm($field, $instance);
 
   return $form;
@@ -386,13 +386,13 @@ function entity_reference_settings_ajax_submit($form, &$form_state) {
 /**
  * Implements hook_options_list().
  */
-function entity_reference_options_list($field, $instance, $entity_type = NULL, $entity = NULL) {
-  if (!$options = entity_reference_get_selection_handler($field, $instance, $entity)->getReferencableEntities()) {
+function entity_reference_options_list(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
+  if (!$options = entity_reference_get_selection_handler($field_definition, $entity)->getReferencableEntities()) {
     return array();
   }
 
   // Rebuild the array by changing the bundle key into the bundle label.
-  $target_type = $field['settings']['target_type'];
+  $target_type = $field_definition->getFieldSetting('target_type');
   $bundles = entity_get_bundles($target_type);
 
   $return = array();
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
index 6168bea..6a42b57 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/EntityReferenceAutocomplete.php
@@ -71,7 +71,7 @@ public function getMatches($field, $instance, $entity_type, $entity_id = '', $pr
         throw new AccessDeniedHttpException();
       }
     }
-    $handler = entity_reference_get_selection_handler($field, $instance, $entity);
+    $handler = entity_reference_get_selection_handler($instance, $entity);
 
     if (isset($string)) {
       // Get an array of matching entities.
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php
index 9e191bf..55dfe97 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Derivative/SelectionBase.php
@@ -46,7 +46,7 @@ public function getDerivativeDefinitions(array $base_plugin_definition) {
     foreach (entity_get_info() as $entity_type => $info) {
       if (!in_array($entity_type, $supported_entities)) {
         $this->derivatives[$entity_type] = $base_plugin_definition;
-        $this->derivatives[$entity_type]['label'] = t('@enitty_type selection', array('@entity_type' => $info['label']));
+        $this->derivatives[$entity_type]['label'] = t('@entity_type selection', array('@entity_type' => $info['label']));
       }
     }
     return $this->derivatives;
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/Selection/SelectionBroken.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/Selection/SelectionBroken.php
index 31c1cb1..d8a73b9 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/Selection/SelectionBroken.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/Selection/SelectionBroken.php
@@ -15,14 +15,6 @@
 class SelectionBroken implements SelectionInterface {
 
   /**
-   * Constructs a SelectionBroken object.
-   */
-  public function __construct($field, $instance = NULL) {
-    $this->field = $field;
-    $this->instance = $instance;
-  }
-
-  /**
    * Implements SelectionInterface::settingsForm().
    */
   public static function settingsForm(&$field, &$instance) {
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/SelectionPluginManager.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/SelectionPluginManager.php
index f178242..d51544d 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/SelectionPluginManager.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/Type/SelectionPluginManager.php
@@ -42,7 +42,7 @@ public function createInstance($plugin_id, array $configuration = array()) {
       return parent::createInstance($plugin_id, $configuration);
     }
     catch (PluginException $e) {
-      return new SelectionBroken($configuration['field'], $configuration['instance']);
+      return new SelectionBroken($configuration['field_definition']);
     }
   }
 
@@ -50,8 +50,8 @@ public function createInstance($plugin_id, array $configuration = array()) {
    * Overrides \Drupal\Component\Plugin\PluginManagerBase::getInstance().
    */
   public function getInstance(array $options) {
-    $selection_handler = $options['instance']['settings']['handler'];
-    $target_entity_type = $options['field']['settings']['target_type'];
+    $selection_handler = $options['field_definition']->getFieldSetting('handler');
+    $target_entity_type = $options['field_definition']->getFieldSetting('target_type');
 
     // Get all available selection plugins for this entity type.
     $selection_handler_groups = $this->getSelectionGroups($target_entity_type);
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php
index ab60905..97aeb6e 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/entity_reference/selection/SelectionBase.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Database\Query\AlterableInterface;
 use Drupal\Core\Database\Query\SelectInterface;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\Component\Utility\NestedArray;
 use Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface;
 
@@ -30,18 +31,11 @@
 class SelectionBase implements SelectionInterface {
 
   /**
-   * The field array.
+   * The field definition.
    *
-   * @var array
+   * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface
    */
-  protected $field;
-
-  /**
-   * The instance array.
-   *
-   * @var array
-   */
-  protected $instance;
+  protected $fieldDefinition;
 
   /**
    * The entity object, or NULL
@@ -53,9 +47,8 @@ class SelectionBase implements SelectionInterface {
   /**
    * Constructs a SelectionBase object.
    */
-  public function __construct($field, $instance, EntityInterface $entity = NULL) {
-    $this->field = $field;
-    $this->instance = $instance;
+  public function __construct(FieldDefinitionInterface $field_definition, EntityInterface $entity = NULL) {
+    $this->fieldDefinition = $field_definition;
     $this->entity = $entity;
   }
 
@@ -165,7 +158,7 @@ public static function settingsForm(&$field, &$instance) {
    * Implements SelectionInterface::getReferencableEntities().
    */
   public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
-    $target_type = $this->field['settings']['target_type'];
+    $target_type = $this->fieldDefinition->getFieldSetting('target_type');
 
     $query = $this->buildEntityQuery($match, $match_operator);
     if ($limit > 0) {
@@ -204,7 +197,7 @@ public function countReferencableEntities($match = NULL, $match_operator = 'CONT
   public function validateReferencableEntities(array $ids) {
     $result = array();
     if ($ids) {
-      $target_type = $this->field['settings']['target_type'];
+      $target_type = $this->fieldDefinition->getFieldSetting('target_type');
       $entity_info = entity_get_info($target_type);
       $query = $this->buildEntityQuery();
       $result = $query
@@ -264,7 +257,7 @@ public function validateAutocompleteInput($input, &$element, &$form_state, $form
    *   it.
    */
   public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
-    $target_type = $this->field['settings']['target_type'];
+    $target_type = $this->fieldDefinition->getFieldSetting('target_type');
     $entity_info = entity_get_info($target_type);
 
     $query = \Drupal::entityQuery($target_type);
@@ -277,17 +270,18 @@ public function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
     }
 
     // Add entity-access tag.
-    $query->addTag($this->field['settings']['target_type'] . '_access');
+    $query->addTag($this->fieldDefinition->getFieldSetting('target_type') . '_access');
 
     // Add the Selection handler for
     // entity_reference_query_entity_reference_alter().
     $query->addTag('entity_reference');
-    $query->addMetaData('field', $this->field);
+    $query->addMetaData('field_definition', $this->fieldDefinition);
     $query->addMetaData('entity_reference_selection_handler', $this);
 
     // Add the sort option.
-    if (!empty($this->instance['settings']['handler_settings']['sort'])) {
-      $sort_settings = $this->instance['settings']['handler_settings']['sort'];
+    $handler_settings = $this->fieldDefinition->getFieldSetting('handler_settings');
+    if (!empty($handler_settings['sort'])) {
+      $sort_settings = $handler_settings['sort'];
       if ($sort_settings['field'] != '_none') {
         $query->sort($sort_settings['field'], $sort_settings['direction']);
       }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php
index 647de08..e54bf32 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/formatter/EntityReferenceEntityFormatter.php
@@ -36,7 +36,7 @@ class EntityReferenceEntityFormatter extends EntityReferenceFormatterBase {
    * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
-    $view_modes = entity_get_view_modes($this->field['settings']['target_type']);
+    $view_modes = entity_get_view_modes($this->getFieldSetting('target_type'));
     $options = array();
     foreach ($view_modes as $view_mode => $view_mode_settings) {
       $options[$view_mode] = $view_mode_settings['label'];
@@ -65,7 +65,7 @@ public function settingsForm(array $form, array &$form_state) {
   public function settingsSummary() {
     $summary = array();
 
-    $view_modes = entity_get_view_modes($this->field['settings']['target_type']);
+    $view_modes = entity_get_view_modes($this->getFieldSetting('target_type'));
     $view_mode = $this->getSetting('view_mode');
     $summary[] = t('Rendered as @mode', array('@mode' => isset($view_modes[$view_mode]['label']) ? $view_modes[$view_mode]['label'] : $view_mode));
     $summary[] = $this->getSetting('links') ? t('Display links') : t('Do not display links');
@@ -83,7 +83,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
     $view_mode = $this->getSetting('view_mode');
     $links = $this->getSetting('links');
 
-    $target_type = $this->field['settings']['target_type'];
+    $target_type = $this->getFieldSetting('target_type');
 
     $elements = array();
 
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php
index a88f2ea..a7e0fba 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteTagsWidget.php
@@ -34,14 +34,14 @@
 class AutocompleteTagsWidget extends AutocompleteWidgetBase {
 
   /**
-   * Overrides \Drupal\entity_reference\Plugin\field\widget\AutocompleteWidgetBase::elementValidate()
+   * {@inheritdoc}
    */
   public function elementValidate($element, &$form_state, $form) {
     $value = array();
     // If a value was entered into the autocomplete.
-    $handler = entity_reference_get_selection_handler($this->field, $this->instance);
-    $bundles = entity_get_bundles($this->field['settings']['target_type']);
-    $auto_create = isset($this->instance['settings']['handler_settings']['auto_create']) ? $this->instance['settings']['handler_settings']['auto_create'] : FALSE;
+    $handler = entity_reference_get_selection_handler($this->fieldDefinition);
+    $bundles = entity_get_bundles($this->getFieldSetting('target_type'));
+    $auto_create = $this->getSelectionHandlerSetting('auto_create');
 
     if (!empty($element['#value'])) {
       $entities = drupal_explode_tags($element['#value']);
@@ -62,7 +62,7 @@ public function elementValidate($element, &$form_state, $form) {
         if ($match) {
           $value[] = array('target_id' => $match);
         }
-        elseif ($auto_create && (count($this->instance['settings']['handler_settings']['target_bundles']) == 1 || count($bundles) == 1)) {
+        elseif ($auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1 || count($bundles) == 1)) {
           // Auto-create item. see entity_reference_field_presave().
           $value[] = array('target_id' => 'auto_create', 'label' => $entity);
         }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php
index 57c4b7b..98fc52a 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidget.php
@@ -38,7 +38,7 @@
 class AutocompleteWidget extends AutocompleteWidgetBase {
 
   /**
-   * Overrides \Drupal\entity_reference\Plugin\field\widget\AutocompleteWidgetBase::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     // We let the Field API handles multiple values for us, only take care of
@@ -54,10 +54,10 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Overrides \Drupal\entity_reference\Plugin\field\widget\AutocompleteWidgetBase::elementValidate()
+   * {@inheritdoc}
    */
   public function elementValidate($element, &$form_state, $form) {
-    $auto_create = isset($this->instance['settings']['handler_settings']['auto_create']) ? $this->instance['settings']['handler_settings']['auto_create'] : FALSE;
+    $auto_create = $this->getSelectionHandlerSetting('auto_create');
 
     // If a value was entered into the autocomplete.
     $value = '';
@@ -69,11 +69,11 @@ public function elementValidate($element, &$form_state, $form) {
       else {
         // Try to get a match from the input string when the user didn't use the
         // autocomplete but filled in a value manually.
-        $handler = entity_reference_get_selection_handler($this->field, $this->instance);
+        $handler = entity_reference_get_selection_handler($this->fieldDefinition);
         $value = $handler->validateAutocompleteInput($element['#value'], $element, $form_state, $form, !$auto_create);
       }
 
-      if (!$value && $auto_create && (count($this->instance['settings']['handler_settings']['target_bundles']) == 1)) {
+      if (!$value && $auto_create && (count($this->getSelectionHandlerSetting('target_bundles')) == 1)) {
         // Auto-create item. see entity_reference_field_presave().
         $value = array(
           'target_id' => 'auto_create',
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
index 6a8df6f..3f91372 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Plugin/field/widget/AutocompleteWidgetBase.php
@@ -17,7 +17,7 @@
 abstract class AutocompleteWidgetBase extends WidgetBase {
 
   /**
-   * Overrides \Drupal\field\Plugin\Type\Widget\WidgetBase::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['match_operator'] = array(
@@ -50,16 +50,14 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-    $instance = $this->instance;
-    $field = $this->field;
-    $entity = isset($element['#entity']) ? $element['#entity'] : NULL;
+    $entity = $element['#entity'];
 
     // Prepare the autocomplete path.
     $autocomplete_path = $this->getSetting('autocomplete_path');
-    $autocomplete_path .= '/' . $field['field_name'] . '/' . $instance['entity_type'] . '/' . $instance['bundle'] . '/';
+    $autocomplete_path .= '/' . $this->fieldDefinition->getFieldName() . '/' . $entity->entityType() . '/' . $entity->bundle() . '/';
 
     // Use <NULL> as a placeholder in the URL when we don't have an entity.
     // Most web servers collapse two consecutive slashes.
@@ -83,7 +81,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Overrides \Drupal\field\Plugin\Type\Widget\WidgetBase::errorElement().
+   * {@inheritdoc}
    */
   public function errorElement(array $element, array $error, array $form, array &$form_state) {
     return $element['target_id'];
@@ -107,7 +105,7 @@ protected function getLabels(array $items) {
     }
 
     // Load those entities and loop through them to extract their labels.
-    $entities = entity_load_multiple($this->field['settings']['target_type'], $entity_ids);
+    $entities = entity_load_multiple($this->getFieldSetting('target_type'), $entity_ids);
 
     foreach ($entities as $entity_id => $entity_item) {
       $label = $entity_item->label();
@@ -120,4 +118,19 @@ protected function getLabels(array $items) {
     }
     return $entity_labels;
   }
+
+  /**
+   * Returns the value of a setting for the entity reference selection handler.
+   *
+   * @param string $setting_name
+   *   The setting name.
+   *
+   * @return mixed
+   *   The setting value.
+   */
+  protected function getSelectionHandlerSetting($setting_name) {
+    $settings = $this->getFieldSetting('handler_settings');
+    return isset($settings[$setting_name]) ? $settings[$setting_name] : NULL;
+  }
+
 }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
index 9ab172b..8106bb9 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionAccessTest.php
@@ -7,6 +7,7 @@
 
 namespace Drupal\entity_reference\Tests;
 
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\Core\Language\Language;
 use Drupal\simpletest\WebTestBase;
 
@@ -32,8 +33,8 @@ function setUp() {
     $this->drupalCreateContentType(array('type' => 'article', 'name' => 'Article'));
   }
 
-  protected function assertReferencable($field, $instance, $tests, $handler_name) {
-    $handler = entity_reference_get_selection_handler($field, $instance);
+  protected function assertReferencable(FieldDefinitionInterface $field_definition, $tests, $handler_name) {
+    $handler = entity_reference_get_selection_handler($field_definition);
 
     foreach ($tests as $test) {
       foreach ($test['arguments'] as $arguments) {
@@ -58,8 +59,8 @@ protected function assertReferencable($field, $instance, $tests, $handler_name)
    * Test the node-specific overrides of the entity handler.
    */
   public function testNodeHandler() {
-    // Build a fake field instance.
-    $field = array(
+    // Create a field and instance.
+    $field = entity_create('field_entity', array(
       'translatable' => FALSE,
       'entity_types' => array(),
       'settings' => array(
@@ -68,15 +69,20 @@ public function testNodeHandler() {
       'field_name' => 'test_field',
       'type' => 'entity_reference',
       'cardinality' => '1',
-    );
-    $instance = array(
+    ));
+    $field->save();
+    $instance = entity_create('field_instance', array(
+      'field_name' => 'test_field',
+      'entity_type' => 'test_entity',
+      'bundle' => 'test_bundle',
       'settings' => array(
         'handler' => 'default',
         'handler_settings' => array(
           'target_bundles' => array(),
         ),
       ),
-    );
+    ));
+    $instance->save();
 
     // Build a set of test data.
     // Titles contain HTML-special characters to test escaping.
@@ -160,7 +166,7 @@ public function testNodeHandler() {
         'result' => array(),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'Node handler');
+    $this->assertReferencable($instance, $referencable_tests, 'Node handler');
 
     // Test as an admin.
     $admin_user = $this->drupalCreateUser(array('access content', 'bypass node access'));
@@ -189,15 +195,15 @@ public function testNodeHandler() {
         ),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'Node handler (admin)');
+    $this->assertReferencable($instance, $referencable_tests, 'Node handler (admin)');
   }
 
   /**
    * Test the user-specific overrides of the entity handler.
    */
   public function testUserHandler() {
-    // Build a fake field instance.
-    $field = array(
+    // Create a field and instance.
+    $field = entity_create('field_entity', array(
       'translatable' => FALSE,
       'entity_types' => array(),
       'settings' => array(
@@ -206,15 +212,20 @@ public function testUserHandler() {
       'field_name' => 'test_field',
       'type' => 'entity_reference',
       'cardinality' => '1',
-    );
-    $instance = array(
+    ));
+    $field->save();
+    $instance = entity_create('field_instance', array(
+      'field_name' => 'test_field',
+      'entity_type' => 'test_entity',
+      'bundle' => 'test_bundle',
       'settings' => array(
         'handler' => 'default',
         'handler_settings' => array(
           'target_bundles' => array(),
         ),
       ),
-    );
+    ));
+    $instance->save();
 
     // Build a set of test data.
     $user_values = array(
@@ -290,7 +301,7 @@ public function testUserHandler() {
         'result' => array(),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'User handler');
+    $this->assertReferencable($instance, $referencable_tests, 'User handler');
 
     $GLOBALS['user'] = $users['admin'];
     $referencable_tests = array(
@@ -329,15 +340,15 @@ public function testUserHandler() {
         ),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'User handler (admin)');
+    $this->assertReferencable($instance, $referencable_tests, 'User handler (admin)');
   }
 
   /**
    * Test the comment-specific overrides of the entity handler.
    */
   public function testCommentHandler() {
-    // Build a fake field instance.
-    $field = array(
+    // Create a field and instance.
+    $field = entity_create('field_entity', array(
       'translatable' => FALSE,
       'entity_types' => array(),
       'settings' => array(
@@ -346,15 +357,20 @@ public function testCommentHandler() {
       'field_name' => 'test_field',
       'type' => 'entity_reference',
       'cardinality' => '1',
-    );
-    $instance = array(
+    ));
+    $field->save();
+    $instance = entity_create('field_instance', array(
+      'field_name' => 'test_field',
+      'entity_type' => 'test_entity',
+      'bundle' => 'test_bundle',
       'settings' => array(
         'handler' => 'default',
         'handler_settings' => array(
           'target_bundles' => array(),
         ),
       ),
-    );
+    ));
+    $instance->save();
 
     // Build a set of test data.
     $node_values = array(
@@ -454,7 +470,7 @@ public function testCommentHandler() {
         'result' => array(),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'Comment handler');
+    $this->assertReferencable($instance, $referencable_tests, 'Comment handler');
 
     // Test as a comment admin.
     $admin_user = $this->drupalCreateUser(array('access content', 'access comments', 'administer comments'));
@@ -472,7 +488,7 @@ public function testCommentHandler() {
         ),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'Comment handler (comment admin)');
+    $this->assertReferencable($instance, $referencable_tests, 'Comment handler (comment admin)');
 
     // Test as a node and comment admin.
     $admin_user = $this->drupalCreateUser(array('access content', 'access comments', 'administer comments', 'bypass node access'));
@@ -491,6 +507,6 @@ public function testCommentHandler() {
         ),
       ),
     );
-    $this->assertReferencable($field, $instance, $referencable_tests, 'Comment handler (comment + node admin)');
+    $this->assertReferencable($instance, $referencable_tests, 'Comment handler (comment + node admin)');
   }
 }
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
index d3245e0..9fdb2d4 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/EntityReferenceSelectionSortTest.php
@@ -54,8 +54,8 @@ public function testSort() {
     field_create_instance($instance_info);
 
 
-    // Build a fake field instance.
-    $field = array(
+    // Create a field and instance.
+    $field = entity_create('field_entity', array(
       'translatable' => FALSE,
       'entity_types' => array(),
       'settings' => array(
@@ -64,9 +64,12 @@ public function testSort() {
       'field_name' => 'test_field',
       'type' => 'entity_reference',
       'cardinality' => 1,
-    );
-
-    $instance = array(
+    ));
+    $field->save();
+    $instance = entity_create('field_instance', array(
+      'field_name' => 'test_field',
+      'entity_type' => 'test_entity',
+      'bundle' => 'test_bundle',
       'settings' => array(
         'handler' => 'default',
         'handler_settings' => array(
@@ -78,7 +81,8 @@ public function testSort() {
           ),
         ),
       ),
-    );
+    ));
+    $instance->save();
 
     // Build a set of test data.
     $node_values = array(
@@ -119,7 +123,7 @@ public function testSort() {
     $normal_user = $this->drupalCreateUser(array('access content'));
     $GLOBALS['user'] = $normal_user;
 
-    $handler = entity_reference_get_selection_handler($field, $instance);
+    $handler = entity_reference_get_selection_handler($instance);
 
     // Not only assert the result, but make sure the keys are sorted as
     // expected.
@@ -135,7 +139,7 @@ public function testSort() {
       'field' => 'nid',
       'direction' => 'ASC',
     );
-    $handler = entity_reference_get_selection_handler($field, $instance);
+    $handler = entity_reference_get_selection_handler($instance);
     $result = $handler->getReferencableEntities();
     $expected_result = array(
       $nodes['published1']->nid => $node_labels['published1'],
diff --git a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php
index 6998209..0bfdae3 100644
--- a/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php
+++ b/core/modules/entity_reference/lib/Drupal/entity_reference/Tests/Views/SelectionTest.php
@@ -39,8 +39,8 @@ public function testSelectionHandler() {
       $nodes[$node->type][$node->nid] = $node->label();
     }
 
-    // Build a fake field instance.
-    $field = array(
+    // Create a field and instance.
+    $field = entity_create('field_entity', array(
       'translatable' => FALSE,
       'entity_types' => array(),
       'settings' => array(
@@ -49,8 +49,12 @@ public function testSelectionHandler() {
       'field_name' => 'test_field',
       'type' => 'entity_reference',
       'cardinality' => '1',
-    );
-    $instance = array(
+    ));
+    $field->save();
+    $instance = entity_create('field_instance', array(
+      'field_name' => 'test_field',
+      'entity_type' => 'test_entity',
+      'bundle' => 'test_bundle',
       'settings' => array(
         'handler' => 'views',
         'handler_settings' => array(
@@ -62,10 +66,11 @@ public function testSelectionHandler() {
           ),
         ),
       ),
-    );
+    ));
+    $instance->save();
 
     // Get values from selection handler.
-    $handler = entity_reference_get_selection_handler($field, $instance);
+    $handler = entity_reference_get_selection_handler($instance);
     $result = $handler->getReferencableEntities();
 
     $success = FALSE;
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index 75a99df..9aaf7bc 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -654,14 +654,14 @@ function hook_field_prepare_translation(\Drupal\Core\Entity\EntityInterface $ent
  *
  * @param $item
  *   An item that may or may not be empty.
- * @param $field
- *   The field to which $item belongs.
+ * @param $field_type
+ *   The field type to which $item belongs.
  *
  * @return
- *   TRUE if $field's type considers $item not to contain any data; FALSE
+ *   TRUE if the field type considers $item not to contain any data; FALSE
  *   otherwise.
  */
-function hook_field_is_empty($item, $field) {
+function hook_field_is_empty($item, $field_type) {
   if (empty($item['value']) && (string) $item['value'] !== '0') {
     return TRUE;
   }
@@ -724,19 +724,19 @@ function hook_field_widget_info_alter(array &$info) {
  * @param $form_state
  *   An associative array containing the current state of the form.
  * @param $context
- *   An associative array containing the following key-value pairs, matching the
- *   arguments received by hook_field_widget_form():
+ *   An associative array containing the following key-value pairs:
  *   - form: The form structure to which widgets are being attached. This may be
  *     a full form structure, or a sub-element of a larger form.
- *   - field: The field structure.
- *   - instance: The field instance structure.
+ *   - widget: The widget plugin instance.
+ *   - field_definition: The field definition.
+ *   - entity: The entity.
  *   - langcode: The language associated with $items.
  *   - items: Array of default values for this field.
  *   - delta: The order of this item in the array of subelements (0, 1, 2, etc).
  *   - default: A boolean indicating whether the form is being shown as a dummy
  *     form to set default values.
  *
- * @see hook_field_widget_form()
+ * @see \Drupal\field\Plugin\Type\Widget\WidgetBase::formSingleElement()
  * @see hook_field_widget_WIDGET_TYPE_form_alter()
  */
 function hook_field_widget_form_alter(&$element, &$form_state, $context) {
@@ -759,20 +759,10 @@ function hook_field_widget_form_alter(&$element, &$form_state, $context) {
  * @param $form_state
  *   An associative array containing the current state of the form.
  * @param $context
- *   An associative array containing the following key-value pairs, matching the
- *   arguments received by hook_field_widget_form():
- *   - "form": The form structure where widgets are being attached to. This
- *     might be a full form structure, or a sub-element of a larger form.
- *   - "field": The field structure.
- *   - "instance": The field instance structure.
- *   - "langcode": The language associated with $items.
- *   - "items": Array of default values for this field.
- *   - "delta": The order of this item in the array of subelements (0, 1, 2,
- *     etc).
- *   - default: A boolean indicating whether the form is being shown as a dummy
- *     form to set default values.
+ *   An associative array. See hook_field_widget_form_alter() for the structure
+ *   and content of the array.
  *
- * @see hook_field_widget_form()
+ * @see \Drupal\field\Plugin\Type\Widget\WidgetBase::formSingleElement()
  * @see hook_field_widget_form_alter()
  */
 function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $context) {
@@ -2076,7 +2066,7 @@ function hook_field_storage_purge(\Drupal\Core\Entity\EntityInterface $entity, $
  *
  * @param $op
  *   The operation to be performed. Possible values: 'edit', 'view'.
- * @param $field
+ * @param \Drupal\field\FieldInterface $field
  *   The field on which the operation is to be performed.
  * @param $entity_type
  *   The type of $entity; for example, 'node' or 'user'.
@@ -2088,7 +2078,7 @@ function hook_field_storage_purge(\Drupal\Core\Entity\EntityInterface $entity, $
  * @return
  *   TRUE if the operation is allowed, and FALSE if the operation is denied.
  */
-function hook_field_access($op, $field, $entity_type, $entity, $account) {
+function hook_field_access($op, \Drupal\field\FieldInterface $field, $entity_type, $entity, $account) {
   if ($field['field_name'] == 'field_of_interest' && $op == 'edit') {
     return user_access('edit field of interest', $account);
   }
diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc
index baa7ff4..6a6faa3 100644
--- a/core/modules/field/field.attach.inc
+++ b/core/modules/field/field.attach.inc
@@ -779,7 +779,6 @@ function _field_invoke_widget_target($form_display) {
  *         '#default_value' => The field value for delta 0,
  *         '#required' => Whether the widget should be marked required,
  *         '#delta' => 0,
- *         '#columns' => The array of field columns,
  *         // The remaining elements in the sub-array depend on the widget.
  *         '#type' => The type of the widget,
  *         ...
@@ -791,7 +790,6 @@ function _field_invoke_widget_target($form_display) {
  *       // Only for multiple widgets:
  *       '#entity_type' => The name of the entity type,
  *       '#bundle' => $instance['bundle'],
- *       '#columns'  => array_keys($field['columns']),
  *       // The remaining elements in the sub-array depend on the widget.
  *       '#type' => The type of the widget,
  *       ...
diff --git a/core/modules/field/field.default.inc b/core/modules/field/field.default.inc
index ab6b10e..cc6a393 100644
--- a/core/modules/field/field.default.inc
+++ b/core/modules/field/field.default.inc
@@ -42,7 +42,7 @@
  */
 function field_default_validate(EntityInterface $entity, $field, $instance, $langcode, $items, &$errors) {
   // Filter out empty values.
-  $items = _field_filter_items($field, $items);
+  $items = _field_filter_items($field['type'], $items);
 
   // Check that the number of values doesn't exceed the field cardinality.
   // For form submitted values, this can only happen with 'multiple value'
diff --git a/core/modules/field/field.form.inc b/core/modules/field/field.form.inc
index 203a112..198aa47 100644
--- a/core/modules/field/field.form.inc
+++ b/core/modules/field/field.form.inc
@@ -152,14 +152,9 @@ function field_add_more_js($form, $form_state) {
 
   // Go one level up in the form, to the widgets container.
   $element = NestedArray::getValue($form, array_slice($button['#array_parents'], 0, -1));
-  $field_name = $element['#field_name'];
-  $langcode = $element['#language'];
-  $parents = $element['#field_parents'];
 
-  $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
-
-  $field = $field_state['field'];
-  if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
+  // Ensure the widget allows adding additional items.
+  if ($element['#cardinality'] != FIELD_CARDINALITY_UNLIMITED) {
     return;
   }
 
@@ -185,8 +180,6 @@ function field_add_more_js($form, $form_state) {
  *
  * @return
  *   An array with the following key/data pairs:
- *   - field: The field definition array.
- *   - instance: The field instance definition array.
  *   - items_count: The number of widgets to display for the field.
  *   - array_parents: The location of the field's widgets within the $form
  *     structure. This entry is populated at '#after_build' time.
@@ -256,52 +249,3 @@ function _field_form_state_parents($parents, $field_name, $langcode) {
   return $form_state_parents;
 }
 
-/**
- * Retrieves the field definition for a widget's helper callbacks.
- *
- * Widget helper element callbacks (such as #process, #element_validate,
- * #value_callback, ...) should use field_widget_field() and
- * field_widget_instance() instead of field_info_field() and
- * field_info_instance() when they need to access field or instance properties.
- * See hook_field_widget_form() for more details.
- *
- * @param $element
- *   The structured array for the widget.
- * @param $form_state
- *   The form state.
- *
- * @return
- *   The $field definition array for the current widget.
- *
- * @see field_widget_instance()
- * @see hook_field_widget_form()
- */
-function field_widget_field($element, $form_state) {
-  $field_state = field_form_get_state($element['#field_parents'], $element['#field_name'], $element['#language'], $form_state);
-  return $field_state['field'];
-}
-
-/**
- * Retrieves the instance definition array for a widget's helper callbacks.
- *
- * Widgets helper element callbacks (such as #process, #element_validate,
- * #value_callback, ...) should use field_widget_field() and
- * field_widget_instance() instead of field_info_field() and
- * field_info_instance() when they need to access field or instance properties.
- * See hook_field_widget_form() for more details.
- *
- * @param $element
- *   The structured array for the widget.
- * @param $form_state
- *   The form state.
- *
- * @return
- *   The $instance definition array for the current widget.
- *
- * @see field_widget_field()
- * @see hook_field_widget_form()
- */
-function field_widget_instance($element, $form_state) {
-  $field_state = field_form_get_state($element['#field_parents'], $element['#field_name'], $element['#language'], $form_state);
-  return $field_state['instance'];
-}
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index f69649d..b6b1b0a 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -39,6 +39,8 @@ function field_info_cache_clear() {
 
   _field_info_collate_types_reset();
   Field::fieldInfo()->flush();
+
+  Drupal::moduleHandler()->invokeAll('field_info_cache_clear');
 }
 
 /**
diff --git a/core/modules/field/field.module b/core/modules/field/field.module
index 798d604..7ff93f3 100644
--- a/core/modules/field/field.module
+++ b/core/modules/field/field.module
@@ -7,6 +7,7 @@
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Language\Language;
 use Drupal\Core\Template\Attribute;
+use Drupal\field\FieldInterface;
 
 /*
  * Load all public Field API functions. Drupal currently has no
@@ -501,8 +502,8 @@ function field_get_default_value(EntityInterface $entity, $field, $instance, $la
 /**
  * Filters out empty field values.
  *
- * @param $field
- *   The field definition.
+ * @param $field_type
+ *   The field type.
  * @param $items
  *   The field values to filter.
  *
@@ -510,11 +511,12 @@ function field_get_default_value(EntityInterface $entity, $field, $instance, $la
  *   The array of items without empty field values. The function also renumbers
  *   the array keys to ensure sequential deltas.
  */
-function _field_filter_items($field, $items) {
-  $function = $field['module'] . '_field_is_empty';
+function _field_filter_items($field_type, $items) {
+  $field_type_info = field_info_field_types($field_type);
+  $function = $field_type_info['module'] . '_field_is_empty';
   foreach ((array) $items as $delta => $item) {
     // Explicitly break if the function is undefined.
-    if ($function($item, $field)) {
+    if ($function($item, $field_type)) {
       unset($items[$delta]);
     }
   }
@@ -808,7 +810,7 @@ function field_view_field(EntityInterface $entity, $field_name, $display_options
     $formatter_manager = drupal_container()->get('plugin.manager.field.formatter');
     $display_options = $formatter_manager->prepareConfiguration($field['type'], $display_options);
     $formatter = $formatter_manager->getInstance(array(
-      'instance' => $instance,
+      'field_definition' => $instance,
       'view_mode' => $view_mode,
       'prepare' => FALSE,
       'configuration' => $display_options,
@@ -927,9 +929,8 @@ function field_has_data($field) {
  *   The operation to be performed. Possible values:
  *   - edit
  *   - view
- * @param array $field
- *   The full field structure array for the field on which the operation is to
- *   be performed. See field_info_field().
+ * @param \Drupal\field\FieldInterface $field
+ *   The field on which the operation is to be performed.
  * @param $entity_type
  *   The type of $entity; for example, 'node' or 'user'.
  * @param $entity
@@ -940,7 +941,7 @@ function field_has_data($field) {
  * @return
  *   TRUE if the operation is allowed; FALSE if the operation is denied.
  */
-function field_access($op, $field, $entity_type, $entity = NULL, $account = NULL) {
+function field_access($op, FieldInterface $field, $entity_type, $entity = NULL, $account = NULL) {
   global $user;
 
   if (!isset($account)) {
diff --git a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
index c6b8ad6..d2a0b85 100644
--- a/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInstanceInterface.php
@@ -8,11 +8,12 @@
 namespace Drupal\field;
 
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 
 /**
  * Provides an interface defining a field instance entity.
  */
-interface FieldInstanceInterface extends ConfigEntityInterface, \ArrayAccess, \Serializable {
+interface FieldInstanceInterface extends ConfigEntityInterface, FieldDefinitionInterface, \ArrayAccess, \Serializable {
 
   /**
    * Returns the field entity for this instance.
diff --git a/core/modules/field/lib/Drupal/field/FieldInterface.php b/core/modules/field/lib/Drupal/field/FieldInterface.php
index 32673ff..83b3de7 100644
--- a/core/modules/field/lib/Drupal/field/FieldInterface.php
+++ b/core/modules/field/lib/Drupal/field/FieldInterface.php
@@ -8,11 +8,12 @@
 namespace Drupal\field;
 
 use Drupal\Core\Config\Entity\ConfigEntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 
 /**
  * Provides an interface defining a field entity.
  */
-interface FieldInterface extends ConfigEntityInterface, \ArrayAccess, \Serializable {
+interface FieldInterface extends ConfigEntityInterface, FieldDefinitionInterface, \ArrayAccess, \Serializable {
 
   /**
    * Returns the field schema.
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 c2fb4e0..b8eae4c 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
@@ -210,6 +210,15 @@ class Field extends ConfigEntityBase implements FieldInterface {
   protected $storageDetails;
 
   /**
+   * The merged settings of the field and a default instance.
+   *
+   * Set by the getFieldSettings() method.
+   *
+   * @var array
+   */
+  protected $mergedSettings;
+
+  /**
    * Constructs a Field object.
    *
    * @param array $values
@@ -512,6 +521,84 @@ public function getBundles() {
   /**
    * {@inheritdoc}
    */
+  public function getFieldName() {
+    return $this->id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldType() {
+    return $this->type;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldSettings() {
+    if (!isset($this->mergedSettings)) {
+      $field_type_info = field_info_field_types($this->type);
+      $this->mergedSettings = $field_type_info['instance_settings'] + $this->settings + $field_type_info['settings'];
+    }
+    return $this->mergedSettings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldSetting($setting_name) {
+    if (!isset($this->mergedSettings)) {
+      $this->getFieldSettings();
+    }
+    return $this->mergedSettings[$setting_name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldPropertyNames() {
+    $schema = $this->getSchema();
+    return array_keys($schema['columns']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isFieldTranslatable() {
+    return $this->translatable;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldLabel() {
+    return $this->label();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldDescription() {
+    return '';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldCardinality() {
+    return $this->cardinality;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isFieldRequired() {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function offsetExists($offset) {
     return isset($this->{$offset}) || in_array($offset, array('columns', 'foreign keys', 'bundles', 'storage_details'));
   }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
index 11c185a..ae68750 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Core/Entity/FieldInstance.php
@@ -201,6 +201,15 @@ class FieldInstance extends ConfigEntityBase implements FieldInstanceInterface {
   protected $bundle_rename_allowed = FALSE;
 
   /**
+   * The merged settings of the instance and field.
+   *
+   * Set by the getFieldSettings() method.
+   *
+   * @var array
+   */
+  protected $mergedSettings;
+
+  /**
    * Constructs a FieldInstance object.
    *
    * @param array $values
@@ -441,6 +450,84 @@ public function getField() {
   /**
    * {@inheritdoc}
    */
+  public function getFieldName() {
+    return $this->field->id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldType() {
+    return $this->field->type;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldSettings() {
+    if (!isset($this->mergedSettings)) {
+      $field_type_info = field_info_field_types($this->field->type);
+      $this->mergedSettings = $this->settings + $field_type_info['instance_settings'] + $this->field->settings + $field_type_info['settings'];
+    }
+    return $this->mergedSettings;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldSetting($setting_name) {
+    if (!isset($this->mergedSettings)) {
+      $this->getFieldSettings();
+    }
+    return $this->mergedSettings[$setting_name];
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldPropertyNames() {
+    $schema = $this->field->getSchema();
+    return array_keys($schema['columns']);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isFieldTranslatable() {
+    return $this->field->translatable;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldLabel() {
+    return $this->label();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldDescription() {
+    return $this->description;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFieldCardinality() {
+    return $this->field->cardinality;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isFieldRequired() {
+    return $this->required;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
   public function allowBundleRename() {
     $this->bundle_rename_allowed = TRUE;
   }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php
index 6b316ae..fa780a5 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterBase.php
@@ -2,14 +2,15 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\Type\Formatter\FormatterBase.
+ * Contains \Drupal\field\Plugin\Type\Formatter\FormatterBase.
  */
 
 namespace Drupal\field\Plugin\Type\Formatter;
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\field\FieldInstanceInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
 
 /**
  * Base class for 'Field formatter' plugin implementations.
@@ -19,16 +20,9 @@
   /**
    * The field definition.
    *
-   * @var array
-   */
-  protected $field;
-
-  /**
-   * The field instance definition.
-   *
-   * @var \Drupal\field\Plugin\Core\Entity\FieldInstance
+   * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface
    */
-  protected $instance;
+  protected $fieldDefinition;
 
   /**
    * The formatter settings.
@@ -58,8 +52,8 @@
    *   The plugin_id for the formatter.
    * @param array $plugin_definition
    *   The plugin implementation definition.
-   * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
-   *   The field instance to which the formatter is associated.
+   * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the formatter is associated.
    * @param array $settings
    *   The formatter settings.
    * @param string $label
@@ -67,11 +61,10 @@
    * @param string $view_mode
    *   The view mode.
    */
-  public function __construct($plugin_id, array $plugin_definition, $instance, array $settings, $label, $view_mode) {
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, $label, $view_mode) {
     parent::__construct(array(), $plugin_id, $plugin_definition);
 
-    $this->instance = $instance;
-    $this->field = field_info_field($instance['field_name']);
+    $this->fieldDefinition = $field_definition;
     $this->settings = $settings;
     $this->label = $label;
     $this->viewMode = $view_mode;
@@ -81,24 +74,22 @@ public function __construct($plugin_id, array $plugin_definition, $instance, arr
    * {@inheritdoc}
    */
   public function view(EntityInterface $entity, $langcode, array $items) {
-    $field = $this->field;
-    $instance = $this->instance;
-
     $addition = array();
 
     $elements = $this->viewElements($entity, $langcode, $items);
     if ($elements) {
       $entity_type = $entity->entityType();
+      $field_name = $this->fieldDefinition->getFieldName();
       $info = array(
         '#theme' => 'field',
-        '#title' => $instance['label'],
-        '#access' => field_access('view', $field, $entity->entityType(), $entity),
+        '#title' => $this->fieldDefinition->getFieldLabel(),
+        '#access' => $this->checkFieldAccess('view', $entity),
         '#label_display' => $this->label,
         '#view_mode' => $this->viewMode,
         '#language' => $langcode,
-        '#field_name' => $field['field_name'],
-        '#field_type' => $field['type'],
-        '#field_translatable' => $field['translatable'],
+        '#field_name' => $field_name,
+        '#field_type' => $this->fieldDefinition->getFieldType(),
+        '#field_translatable' => $this->fieldDefinition->isFieldTranslatable(),
         '#entity_type' => $entity_type,
         '#bundle' => $entity->bundle(),
         '#object' => $entity,
@@ -106,7 +97,7 @@ public function view(EntityInterface $entity, $langcode, array $items) {
         '#formatter' => $this->getPluginId(),
       );
 
-      $addition[$field['field_name']] = array_merge($info, $elements);
+      $addition[$field_name] = array_merge($info, $elements);
     }
 
     return $addition;
@@ -131,4 +122,43 @@ public function settingsSummary() {
    */
   public function prepareView(array $entities, $langcode, array &$items) { }
 
+  /**
+   * Returns whether the currently logged in user has access to the field.
+   *
+   * @todo Remove this once Field API access is unified with entity field
+   *   access: http://drupal.org/node/1994140.
+   */
+  protected function checkFieldAccess($op, $entity) {
+    if ($this->fieldDefinition instanceof FieldInstanceInterface) {
+      $field = $this->fieldDefinition->getField();
+      return field_access($op, $field, $entity->entityType(), $entity);
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Returns the array of field settings.
+   *
+   * @return array
+   *   The array of settings.
+   */
+  protected function getFieldSettings() {
+    return $this->fieldDefinition->getFieldSettings();
+  }
+
+  /**
+   * Returns the value of a field setting.
+   *
+   * @param string $setting_name
+   *   The setting name.
+   *
+   * @return mixed
+   *   The setting value.
+   */
+  protected function getFieldSetting($setting_name) {
+    return $this->fieldDefinition->getFieldSetting($setting_name);
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterFactory.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterFactory.php
index 0df5b97..1e41001 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterFactory.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterFactory.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\Type\Formatter\FormatterFactory.
+ * Contains \Drupal\field\Plugin\Type\Formatter\FormatterFactory.
  */
 
 namespace Drupal\field\Plugin\Type\Formatter;
@@ -15,11 +15,11 @@
 class FormatterFactory extends DefaultFactory {
 
   /**
-   * Overrides Drupal\Component\Plugin\Factory\DefaultFactory::createInstance().
+   * {@inheritdoc}
    */
   public function createInstance($plugin_id, array $configuration) {
     $plugin_definition = $this->discovery->getDefinition($plugin_id);
     $plugin_class = static::getPluginClass($plugin_id, $plugin_definition);
-    return new $plugin_class($plugin_id, $plugin_definition, $configuration['instance'], $configuration['settings'], $configuration['label'], $configuration['view_mode']);
+    return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['label'], $configuration['view_mode']);
   }
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
index ab5f207..0b04387 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php
@@ -55,7 +55,7 @@ public function __construct(\Traversable $namespaces) {
    *
    * @param array $options
    *   An array with the following key/value pairs:
-   *   - instance: (FieldInstance) The field instance.
+   *   - field_definition: (FieldDefinitionInterface) The field definition.
    *   - view_mode: (string) The view mode.
    *   - prepare: (bool, optional) Whether default values should get merged in
    *     the 'configuration' array. Defaults to TRUE.
@@ -77,12 +77,12 @@ public function __construct(\Traversable $namespaces) {
    */
   public function getInstance(array $options) {
     $configuration = $options['configuration'];
-    $instance = $options['instance'];
-    $field = field_info_field($instance['field_name']);
+    $field_definition = $options['field_definition'];
+    $field_type = $field_definition->getFieldType();
 
     // Fill in default configuration if needed.
     if (!isset($options['prepare']) || $options['prepare'] == TRUE) {
-      $configuration = $this->prepareConfiguration($field['type'], $configuration);
+      $configuration = $this->prepareConfiguration($field_type, $configuration);
     }
 
     $plugin_id = $configuration['type'];
@@ -91,14 +91,14 @@ public function getInstance(array $options) {
     // - $type_info doesn't exist (the widget type is unknown),
     // - the field type is not allowed for the widget.
     $definition = $this->getDefinition($configuration['type']);
-    if (!isset($definition['class']) || !in_array($field['type'], $definition['field_types'])) {
+    if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
       // Grab the default widget for the field type.
-      $field_type_definition = field_info_field_types($field['type']);
+      $field_type_definition = field_info_field_types($field_type);
       $plugin_id = $field_type_definition['default_formatter'];
     }
 
     $configuration += array(
-      'instance' => $instance,
+      'field_definition' => $field_definition,
       'view_mode' => $options['view_mode'],
     );
     return $this->createInstance($plugin_id, $configuration);
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
index 8806cb5..5cf902b 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetBase.php
@@ -2,15 +2,16 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\Type\Widget\WidgetBase.
+ * Contains \Drupal\field\Plugin\Type\Widget\WidgetBase.
  */
 
 namespace Drupal\field\Plugin\Type\Widget;
 
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
+use Drupal\field\FieldInstanceInterface;
 use Drupal\field\Plugin\PluginSettingsBase;
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
 
 /**
  * Base class for 'Field widget' plugin implementations.
@@ -20,16 +21,9 @@
   /**
    * The field definition.
    *
-   * @var array
+   * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface
    */
-  protected $field;
-
-  /**
-   * The field instance definition.
-   *
-   * @var \Drupal\field\Plugin\Core\Entity\FieldInstance
-   */
-  protected $instance;
+  protected $fieldDefinition;
 
   /**
    * The widget settings.
@@ -45,26 +39,23 @@
    *   The plugin_id for the widget.
    * @param array $plugin_definition
    *   The plugin implementation definition.
-   * @param \Drupal\field\Plugin\Core\Entity\FieldInstance $instance
-   *   The field instance to which the widget is associated.
+   * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
+   *   The definition of the field to which the widget is associated.
    * @param array $settings
    *   The widget settings.
    */
-  public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) {
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
     parent::__construct(array(), $plugin_id, $plugin_definition);
 
-    $this->instance = $instance;
-    $this->field = field_info_field($instance['field_name']);
+    $this->fieldDefinition = $field_definition;
     $this->settings = $settings;
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::form().
+   * {@inheritdoc}
    */
   public function form(EntityInterface $entity, $langcode, array $items, array &$form, array &$form_state, $get_delta = NULL) {
-    $field = $this->field;
-    $instance = $this->instance;
-    $field_name = $field['field_name'];
+    $field_name = $this->fieldDefinition->getFieldName();
 
     $parents = $form['#parents'];
 
@@ -75,11 +66,9 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
     // Store field information in $form_state.
     if (!field_form_get_state($parents, $field_name, $langcode, $form_state)) {
       $field_state = array(
-          'field' => $field,
-          'instance' => $instance,
-          'items_count' => count($items),
-          'array_parents' => array(),
-          'errors' => array(),
+        'items_count' => count($items),
+        'array_parents' => array(),
+        'errors' => array(),
       );
       field_form_set_state($parents, $field_name, $langcode, $form_state, $field_state);
     }
@@ -94,8 +83,8 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
     if (isset($get_delta) || $definition['multiple_values']) {
       $delta = isset($get_delta) ? $get_delta : 0;
       $element = array(
-        '#title' => check_plain($instance['label']),
-        '#description' => field_filter_xss(\Drupal::token()->replace($instance['description'])),
+        '#title' => check_plain($this->fieldDefinition->getFieldLabel()),
+        '#description' => field_filter_xss(\Drupal::token()->replace($this->fieldDefinition->getFieldDescription())),
       );
       $element = $this->formSingleElement($entity, $items, $delta, $langcode, $element, $form, $form_state);
 
@@ -125,7 +114,7 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
       '#type' => 'container',
       '#attributes' => array(
         'class' => array(
-          'field-type-' . drupal_html_class($field['type']),
+          'field-type-' . drupal_html_class($this->fieldDefinition->getFieldType()),
           'field-name-' . drupal_html_class($field_name),
           'field-widget-' . drupal_html_class($this->getPluginId()),
         ),
@@ -146,7 +135,7 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
       // when $langcode is unknown.
       '#language' => $langcode,
       $langcode => $elements,
-      '#access' => field_access('edit', $field, $entity->entityType(), $entity),
+      '#access' => $this->checkFieldAccess('edit', $entity),
     );
 
     return $addition;
@@ -161,14 +150,12 @@ public function form(EntityInterface $entity, $langcode, array $items, array &$f
    * - table display and drag-n-drop value reordering
    */
   protected function formMultipleElements(EntityInterface $entity, array $items, $langcode, array &$form, array &$form_state) {
-    $field = $this->field;
-    $instance = $this->instance;
-    $field_name = $field['field_name'];
-
+    $field_name = $this->fieldDefinition->getFieldName();
+    $cardinality = $this->fieldDefinition->getFieldCardinality();
     $parents = $form['#parents'];
 
     // Determine the number of widgets to display.
-    switch ($field['cardinality']) {
+    switch ($cardinality) {
       case FIELD_CARDINALITY_UNLIMITED:
         $field_state = field_form_get_state($parents, $field_name, $langcode, $form_state);
         $max = $field_state['items_count'];
@@ -176,16 +163,16 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
         break;
 
       default:
-        $max = $field['cardinality'] - 1;
-        $is_multiple = ($field['cardinality'] > 1);
+        $max = $cardinality - 1;
+        $is_multiple = ($cardinality > 1);
         break;
     }
 
     $id_prefix = implode('-', array_merge($parents, array($field_name)));
     $wrapper_id = drupal_html_id($id_prefix . '-add-more-wrapper');
 
-    $title = check_plain($instance['label']);
-    $description = field_filter_xss(\Drupal::token()->replace($instance['description']));
+    $title = check_plain($this->fieldDefinition->getFieldLabel());
+    $description = field_filter_xss(\Drupal::token()->replace($this->fieldDefinition->getFieldDescription()));
 
     $elements = array();
 
@@ -221,9 +208,9 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
     if ($elements) {
       $elements += array(
         '#theme' => 'field_multiple_value_form',
-        '#field_name' => $field['field_name'],
-        '#cardinality' => $field['cardinality'],
-        '#required' => $instance['required'],
+        '#field_name' => $field_name,
+        '#cardinality' => $cardinality,
+        '#required' => $this->fieldDefinition->isFieldRequired(),
         '#title' => $title,
         '#description' => $description,
         '#prefix' => '<div id="' . $wrapper_id . '">',
@@ -232,7 +219,7 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
       );
 
       // Add 'add more' button, if not working with a programmed form.
-      if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
+      if ($cardinality == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
         $elements['add_more'] = array(
           '#type' => 'submit',
           '#name' => strtr($id_prefix, '-', '_') . '_add_more',
@@ -256,19 +243,15 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
    * Generates the form element for a single copy of the widget.
    */
   protected function formSingleElement(EntityInterface $entity, array $items, $delta, $langcode, array $element, array &$form, array &$form_state) {
-    $instance = $this->instance;
-    $field = $this->field;
-
     $element += array(
       '#entity_type' => $entity->entityType(),
       '#bundle' => $entity->bundle(),
       '#entity' => $entity,
-      '#field_name' => $field['field_name'],
+      '#field_name' => $this->fieldDefinition->getFieldName(),
       '#language' => $langcode,
       '#field_parents' => $form['#parents'],
-      '#columns' => array_keys($field['columns']),
       // Only the first widget should be required.
-      '#required' => $delta == 0 && $instance['required'],
+      '#required' => $delta == 0 && $this->fieldDefinition->isFieldRequired(),
       '#delta' => $delta,
       '#weight' => $delta,
     );
@@ -279,8 +262,9 @@ protected function formSingleElement(EntityInterface $entity, array $items, $del
       // Allow modules to alter the field widget form element.
       $context = array(
         'form' => $form,
-        'field' => $field,
-        'instance' => $instance,
+        'widget' => $this,
+        'field_definition' => $this->fieldDefinition,
+        'entity' => $entity,
         'langcode' => $langcode,
         'items' => $items,
         'delta' => $delta,
@@ -293,10 +277,10 @@ protected function formSingleElement(EntityInterface $entity, array $items, $del
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::extractFormValues().
+   * {@inheritdoc}
    */
   public function extractFormValues(EntityInterface $entity, $langcode, array &$items, array $form, array &$form_state) {
-    $field_name = $this->field['field_name'];
+    $field_name = $this->fieldDefinition->getFieldName();
 
     // Extract the values from $form_state['values'].
     $path = array_merge($form['#parents'], array($field_name, $langcode));
@@ -331,7 +315,7 @@ public function extractFormValues(EntityInterface $entity, $langcode, array &$it
       $this->sortItems($items);
 
       // Remove empty values.
-      $items = _field_filter_items($this->field, $items);
+      $items = _field_filter_items($this->fieldDefinition->getFieldType(), $items);
 
       // Put delta mapping in $form_state, so that flagErrors() can use it.
       $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state);
@@ -344,10 +328,10 @@ public function extractFormValues(EntityInterface $entity, $langcode, array &$it
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::flagErrors().
+   * {@inheritdoc}
    */
   public function flagErrors(EntityInterface $entity, $langcode, array $items, array $form, array &$form_state) {
-    $field_name = $this->field['field_name'];
+    $field_name = $this->fieldDefinition->getFieldName();
 
     $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state);
 
@@ -410,7 +394,8 @@ public function massageFormValues(array $values, array $form, array &$form_state
    *   The field values.
    */
   protected function sortItems(array &$items) {
-    $is_multiple = ($this->field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) || ($this->field['cardinality'] > 1);
+    $cardinality = $this->fieldDefinition->getFieldCardinality();
+    $is_multiple = ($cardinality == FIELD_CARDINALITY_UNLIMITED) || ($cardinality > 1);
     if ($is_multiple && isset($items[0]['_weight'])) {
       usort($items, function ($a, $b) {
         $a_weight = (is_array($a) ? $a['_weight'] : 0);
@@ -426,4 +411,43 @@ protected function sortItems(array &$items) {
     }
   }
 
+  /**
+   * Returns whether the currently logged in user has access to the field.
+   *
+   * @todo Remove this once Field API access is unified with entity field
+   *   access: http://drupal.org/node/1994140.
+   */
+  protected function checkFieldAccess($op, $entity) {
+    if ($this->fieldDefinition instanceof FieldInstanceInterface) {
+      $field = $this->fieldDefinition->getField();
+      return field_access($op, $field, $entity->entityType(), $entity);
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  /**
+   * Returns the array of field settings.
+   *
+   * @return array
+   *   The array of settings.
+   */
+  protected function getFieldSettings() {
+    return $this->fieldDefinition->getFieldSettings();
+  }
+
+  /**
+   * Returns the value of a field setting.
+   *
+   * @param string $setting_name
+   *   The setting name.
+   *
+   * @return mixed
+   *   The setting value.
+   */
+  protected function getFieldSetting($setting_name) {
+    return $this->fieldDefinition->getFieldSetting($setting_name);
+  }
+
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php
index 9b14e85..4b7cb6b 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetFactory.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\field\Plugin\WidgetFactory.
+ * Contains \Drupal\field\Plugin\WidgetFactory.
  */
 
 namespace Drupal\field\Plugin\Type\Widget;
@@ -15,11 +15,11 @@
 class WidgetFactory extends DefaultFactory {
 
   /**
-   * Overrides Drupal\Component\Plugin\Factory\DefaultFactory::createInstance().
+   * {@inheritdoc}
    */
   public function createInstance($plugin_id, array $configuration) {
     $plugin_definition = $this->discovery->getDefinition($plugin_id);
     $plugin_class = static::getPluginClass($plugin_id, $plugin_definition);
-    return new $plugin_class($plugin_id, $plugin_definition, $configuration['instance'], $configuration['settings']);
+    return new $plugin_class($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings']);
   }
 }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
index eb82844..e00005b 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetInterface.php
@@ -48,26 +48,18 @@ public function settingsForm(array $form, array &$form_state);
    * each form element. If there are multiple values for this field, the
    * formElement() method will be called as many times as needed.
    *
-   * Note that, depending on the context in which the widget is being included
-   * (regular entity form, field configuration form, advanced search form...),
-   * the values for $field and $instance might be different from the "official"
-   * definitions returned by field_info_field() and field_info_instance().
-   * Examples: mono-value widget even if the field is multi-valued, non-required
-   * widget even if the field is 'required'...
-   *
-   * Therefore, the FAPI element callbacks (such as #process, #element_validate,
-   * #value_callback...) used by the widget cannot use the field_info_field()
-   * or field_info_instance() functions to retrieve the $field or $instance
-   * definitions they should operate on. The field_widget_field() and
-   * field_widget_instance() functions should be used instead to fetch the
-   * current working definitions from $form_state, where Field API stores them.
-   *
-   * Alternatively, hook_field_widget_form() can extract the needed specific
-   * properties from $field and $instance and set them as ad-hoc
-   * $element['#custom'] properties, for later use by its element callbacks.
-   *
    * Other modules may alter the form element provided by this function using
-   * hook_field_widget_form_alter().
+   * hook_field_widget_form_alter() or
+   * hook_field_widget_WIDGET_TYPE_form_alter().
+   *
+   * The FAPI element callbacks (such as #process, #element_validate,
+   * #value_callback...) used by the widget do not have access to the original
+   * $field_definition passed to the widget's constructor. Therefore, if any
+   * information is needed from that definition by those callbacks, the widget
+   * implementing this method, or a hook_field_widget[_WIDGET_TYPE]_form_alter()
+   * implementation, must extract the needed properties from the field
+   * definition and set them as ad-hoc $element['#custom'] properties, for later
+   * use by its element callbacks.
    *
    * @param array $items
    *   Array of default values for this field.
@@ -86,7 +78,6 @@ public function settingsForm(array $form, array &$form_state);
    *       $form_state['values'], and is used to access processing information
    *       for the field through the field_form_get_state() and
    *       field_form_set_state() functions.
-   *   - #columns: A list of field storage columns of the field.
    *   - #title: The sanitized element label for the field instance, ready for
    *     output.
    *   - #description: The sanitized element description for the field instance,
@@ -107,8 +98,6 @@ public function settingsForm(array $form, array &$form_state);
    * @return array
    *   The form elements for a single widget for this field.
    *
-   * @see field_widget_field()
-   * @see field_widget_instance()
    * @see hook_field_widget_form_alter()
    * @see hook_field_widget_WIDGET_TYPE_form_alter()
    */
diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
index f5807be..eb9cc87 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Widget/WidgetPluginManager.php
@@ -56,7 +56,7 @@ public function __construct(\Traversable $namespaces) {
    *
    * @param array $options
    *   An array with the following key/value pairs:
-   *   - instance: (FieldInstance) The field instance.
+   *   - field_definition: (FieldDefinitionInterface) The field definition.
    *   - form_mode: (string) The form mode.
    *   - prepare: (bool, optional) Whether default values should get merged in
    *     the 'configuration' array. Defaults to TRUE.
@@ -75,12 +75,12 @@ public function __construct(\Traversable $namespaces) {
    */
   public function getInstance(array $options) {
     $configuration = $options['configuration'];
-    $instance = $options['instance'];
-    $field = field_info_field($instance['field_name']);
+    $field_definition = $options['field_definition'];
+    $field_type = $field_definition->getFieldType();
 
     // Fill in default configuration if needed.
     if (!isset($options['prepare']) || $options['prepare'] == TRUE) {
-      $configuration = $this->prepareConfiguration($field['type'], $configuration);
+      $configuration = $this->prepareConfiguration($field_type, $configuration);
     }
 
     $plugin_id = $configuration['type'];
@@ -89,14 +89,14 @@ public function getInstance(array $options) {
     // - $type_info doesn't exist (the widget type is unknown),
     // - the field type is not allowed for the widget.
     $definition = $this->getDefinition($configuration['type']);
-    if (!isset($definition['class']) || !in_array($field['type'], $definition['field_types'])) {
+    if (!isset($definition['class']) || !in_array($field_type, $definition['field_types'])) {
       // Grab the default widget for the field type.
-      $field_type_definition = field_info_field_types($field['type']);
+      $field_type_definition = field_info_field_types($field_type);
       $plugin_id = $field_type_definition['default_widget'];
     }
 
     $configuration += array(
-      'instance' => $instance,
+      'field_definition' => $field_definition,
     );
     return $this->createInstance($plugin_id, $configuration);
   }
diff --git a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
index 77927e7..b3a1d0f 100644
--- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
+++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php
@@ -32,12 +32,11 @@ class Field extends FieldPluginBase {
   public $items = array();
 
   /**
-   * Store the field information.
+   * The field information as returned by field_info_field().
    *
-   * @var array
+   * @var \Drupal\field\FieldInterface
    */
-  public $field_info = array();
-
+  public $field_info;
 
   /**
    * Does the field supports multiple field values.
@@ -61,13 +60,6 @@ class Field extends FieldPluginBase {
   public $base_table;
 
   /**
-   * Store the field instance.
-   *
-   * @var array
-   */
-  public $instance;
-
-  /**
    * An array of formatter options.
    *
    * @var array
@@ -393,11 +385,8 @@ public function buildOptionsForm(&$form, &$form_state) {
 
     $settings = $this->options['settings'] + field_info_formatter_settings($format);
 
-    // Provide an instance array for hook_field_formatter_settings_form().
-    $this->instance = $this->fakeFieldInstance($format, $settings);
-
     $options = array(
-      'instance' => $this->instance,
+      'field_definition' => $field,
       'configuration' => array(
         'type' => $format,
         'settings' => $settings,
@@ -416,42 +405,6 @@ public function buildOptionsForm(&$form, &$form_state) {
   }
 
   /**
-   * Provides a fake field instance.
-   *
-   * @param string $formatter
-   *   The machine name of the formatter to use.
-   * @param array $formatter_settings
-   *   An associative array of settings for the formatter.
-   *
-   * @return array
-   *   An associative array of instance date for the fake field.
-   *
-   * @see field_info_instance()
-   */
-  function fakeFieldInstance($formatter, $formatter_settings) {
-    $field_name = $this->definition['field_name'];
-    $field = field_read_field($field_name);
-
-    $field_type = field_info_field_types($field['type']);
-
-    return array(
-      // Build a fake entity type and bundle.
-      'field_name' => $field_name,
-      'entity_type' => 'views_fake',
-      'bundle' => 'views_fake',
-
-      // Use the default field settings.
-      'settings' => field_info_instance_settings($field['type']),
-
-      // Set the other fields to their default values.
-      'required' => FALSE,
-      'label' => $field_name,
-      'description' => '',
-      'deleted' => FALSE,
-    );
-  }
-
-  /**
    * Provide options for multiple value fields.
    */
   function multiple_options_form(&$form, &$form_state) {
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..23ae814 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
@@ -7,6 +7,7 @@
 
 use Drupal\Core\Entity\EntityInterface;
 use Drupal\field\FieldException;
+use Drupal\field\FieldInterface;
 
 /**
  * Implements hook_field_info().
@@ -137,7 +138,7 @@ function field_test_field_validate(EntityInterface $entity = NULL, $field, $inst
 /**
  * Implements hook_field_is_empty().
  */
-function field_test_field_is_empty($item, $field) {
+function field_test_field_is_empty($item, $field_type) {
   return empty($item['value']);
 }
 
@@ -197,7 +198,7 @@ function field_test_default_value(EntityInterface $entity, $field, $instance) {
 /**
  * Implements hook_field_access().
  */
-function field_test_field_access($op, $field, $entity_type, $entity, $account) {
+function field_test_field_access($op, FieldInterface $field, $entity_type, $entity, $account) {
   if ($field['field_name'] == "field_no_{$op}_access") {
     return FALSE;
   }
diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module
index c2070f2..5c28609 100644
--- a/core/modules/field/tests/modules/field_test/field_test.module
+++ b/core/modules/field/tests/modules/field_test/field_test.module
@@ -203,15 +203,13 @@ function field_test_field_attach_view_alter(&$output, $context) {
  * Implements hook_field_widget_form_alter().
  */
 function field_test_field_widget_form_alter(&$element, &$form_state, $context) {
-  $instance = $context['instance'];
-  $entity_form_display = entity_get_form_display($instance['entity_type'], $instance['bundle'], 'default');
-  switch ($context['field']['field_name']) {
+  switch ($context['field_definition']->getFieldName()) {
     case 'alter_test_text':
-      drupal_set_message('Field size: ' . $entity_form_display->getWidget($context['field']['field_name'])->getSetting('size'));
+      drupal_set_message('Field size: ' . $context['widget']->getSetting('size'));
       break;
 
     case 'alter_test_options':
-      drupal_set_message('Widget type: ' . $entity_form_display->getWidget($context['field']['field_name'])->getPluginId());
+      drupal_set_message('Widget type: ' . $context['widget']->getPluginId());
       break;
   }
   // Set a message if this is for the form displayed to set default value for
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
index aea8b85..e77dfee 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php
@@ -210,7 +210,7 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
       // Get the corresponding formatter object.
       if ($display_options && $display_options['type'] != 'hidden') {
         $formatter = $this->formatterManager->getInstance(array(
-          'instance' => $instance,
+          'field_definition' => $instance,
           'view_mode' => $this->mode,
           'configuration' => $display_options
         ));
diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
index 408b778..393997a 100644
--- a/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
+++ b/core/modules/field_ui/lib/Drupal/field_ui/Form/FieldInstanceEditForm.php
@@ -136,6 +136,7 @@ public function validateForm(array &$form, array &$form_state) {
     $field_name = $this->instance['field_name'];
     $entity = $form['#entity'];
     $entity_form_display = $form['#entity_form_display'];
+    $field = $this->instance->getField();
 
     if (isset($form['instance']['default_value_widget'])) {
       $element = $form['instance']['default_value_widget'];
@@ -144,9 +145,8 @@ public function validateForm(array &$form, array &$form_state) {
       $items = array();
       $entity_form_display->getWidget($this->instance->getField()->id)->extractFormValues($entity, Language::LANGCODE_NOT_SPECIFIED, $items, $element, $form_state);
 
-      // Grab the field definition from $form_state.
+      // Get the field state.
       $field_state = field_form_get_state($element['#parents'], $field_name, Language::LANGCODE_NOT_SPECIFIED, $form_state);
-      $field = $field_state['field'];
 
       // Validate the value.
       $errors = array();
diff --git a/core/modules/file/file.field.inc b/core/modules/file/file.field.inc
index d8da611..746778f 100644
--- a/core/modules/file/file.field.inc
+++ b/core/modules/file/file.field.inc
@@ -292,7 +292,7 @@ function file_field_delete_revision(EntityInterface $entity, $field, $instance,
 /**
  * Implements hook_field_is_empty().
  */
-function file_field_is_empty($item, $field) {
+function file_field_is_empty($item, $field_type) {
   return empty($item['fid']);
 }
 
@@ -317,18 +317,18 @@ function file_field_displayed($item, $field) {
 /**
  * Retrieves the upload validators for a file field.
  *
- * @param $field
- *   A field array.
+ * @param array $field_settings
+ *   The field settings.
  *
  * @return
  *   An array suitable for passing to file_save_upload() or the file field
  *   element's '#upload_validators' property.
  */
-function file_field_widget_upload_validators($field, $instance) {
+function file_field_widget_upload_validators(array $field_settings) {
   // Cap the upload size according to the PHP limit.
   $max_filesize = parse_size(file_upload_max_size());
-  if (!empty($instance['settings']['max_filesize']) && parse_size($instance['settings']['max_filesize']) < $max_filesize) {
-    $max_filesize = parse_size($instance['settings']['max_filesize']);
+  if (!empty($field_settings['max_filesize']) && parse_size($field_settings['max_filesize']) < $max_filesize) {
+    $max_filesize = parse_size($field_settings['max_filesize']);
   }
 
   $validators = array();
@@ -337,20 +337,18 @@ function file_field_widget_upload_validators($field, $instance) {
   $validators['file_validate_size'] = array($max_filesize);
 
   // Add the extension check if necessary.
-  if (!empty($instance['settings']['file_extensions'])) {
-    $validators['file_validate_extensions'] = array($instance['settings']['file_extensions']);
+  if (!empty($field_settings['file_extensions'])) {
+    $validators['file_validate_extensions'] = array($field_settings['file_extensions']);
   }
 
   return $validators;
 }
 
 /**
- * Determines the URI for a file field instance.
+ * Determines the URI for a file field.
  *
- * @param $field
- *   A field array.
- * @param $instance
- *   A field instance array.
+ * @param array $field_settings
+ *   The field settings.
  * @param $data
  *   An array of token objects to pass to
  *   \Drupal\Core\Utility\Token::replace().
@@ -360,13 +358,13 @@ function file_field_widget_upload_validators($field, $instance) {
  *
  * @see \Drupal\Core\Utility\Token::replace()
  */
-function file_field_widget_uri($field, $instance, $data = array()) {
-  $destination = trim($instance['settings']['file_directory'], '/');
+function file_field_widget_uri(array $field_settings, $data = array()) {
+  $destination = trim($field_settings['file_directory'], '/');
 
   // Replace tokens.
   $destination = Drupal::token()->replace($destination, $data);
 
-  return $field['settings']['uri_scheme'] . '://' . $destination;
+  return $field_settings['uri_scheme'] . '://' . $destination;
 }
 
 /**
@@ -378,9 +376,8 @@ function file_field_widget_value($element, $input = FALSE, $form_state) {
   if ($input) {
     // Checkboxes lose their value when empty.
     // If the display field is present make sure its unchecked value is saved.
-    $field = field_widget_field($element, $form_state);
     if (empty($input['display'])) {
-      $input['display'] = $field['settings']['display_field'] ? 0 : 1;
+      $input['display'] = $element['#display_field'] ? 0 : 1;
     }
   }
 
@@ -449,17 +446,14 @@ function file_field_widget_process($element, &$form_state, $form) {
   $item = $element['#value'];
   $item['fids'] = $element['fids']['#value'];
 
-  $field = field_widget_field($element, $form_state);
-  $instance = field_widget_instance($element, $form_state);
-
   $element['#theme'] = 'file_widget';
 
   // Add the display field if enabled.
-  if (!empty($field['settings']['display_field']) && $item['fids']) {
+  if ($element['#display_field'] && $item['fids']) {
     $element['display'] = array(
       '#type' => empty($item['fids']) ? 'hidden' : 'checkbox',
       '#title' => t('Include file in display'),
-      '#value' => isset($item['display']) ? $item['display'] : $field['settings']['display_default'],
+      '#value' => isset($item['display']) ? $item['display'] : $element['#display_default'],
       '#attributes' => array('class' => array('file-display')),
     );
   }
@@ -471,7 +465,7 @@ function file_field_widget_process($element, &$form_state, $form) {
   }
 
   // Add the description field if enabled.
-  if (!empty($instance['settings']['description_field']) && $item['fids']) {
+  if ($element['#description_field'] && $item['fids']) {
     $config = config('file.settings');
     $element['description'] = array(
       '#type' => $config->get('description.type'),
@@ -484,7 +478,7 @@ function file_field_widget_process($element, &$form_state, $form) {
 
   // Adjust the Ajax settings so that on upload and remove of any individual
   // file, the entire group of file fields is updated together.
-  if ($field['cardinality'] != 1) {
+  if ($element['#cardinality'] != 1) {
     $parents = array_slice($element['#array_parents'], 0, -1);
     $new_path = 'file/ajax/' . implode('/', $parents) . '/' . $form['form_build_id']['#value'];
     $field_element = NestedArray::getValue($form, $parents);
diff --git a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
index 4eebf6c..4603288 100644
--- a/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
+++ b/core/modules/file/lib/Drupal/file/Plugin/field/widget/FileWidget.php
@@ -31,7 +31,7 @@
 class FileWidget extends WidgetBase {
 
   /**
-   * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['progress_indicator'] = array(
@@ -50,14 +50,12 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Overrides \Drupal\field\Plugin\Type\Widget\WidgetBase::formMultipleElements().
+   * {@inheritdoc}
    *
    * Special handling for draggable multiple widgets and 'add more' button.
    */
   protected function formMultipleElements(EntityInterface $entity, array $items, $langcode, array &$form, array &$form_state) {
-    $field = $this->field;
-    $instance = $this->instance;
-    $field_name = $field['field_name'];
+    $field_name = $this->fieldDefinition->getFieldName();
 
     $parents = $form['#parents'];
 
@@ -70,23 +68,24 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
     }
 
     // Determine the number of widgets to display.
-    switch ($field['cardinality']) {
+    $cardinality = $this->fieldDefinition->getFieldCardinality();
+    switch ($cardinality) {
       case FIELD_CARDINALITY_UNLIMITED:
         $max = count($items);
         $is_multiple = TRUE;
         break;
 
       default:
-        $max = $field['cardinality'] - 1;
-        $is_multiple = ($field['cardinality'] > 1);
+        $max = $cardinality - 1;
+        $is_multiple = ($cardinality > 1);
         break;
     }
 
     $id_prefix = implode('-', array_merge($parents, array($field_name)));
     $wrapper_id = drupal_html_id($id_prefix . '-add-more-wrapper');
 
-    $title = check_plain($instance['label']);
-    $description = field_filter_xss($instance['description']);
+    $title = check_plain($this->fieldDefinition->getFieldLabel());
+    $description = field_filter_xss($this->fieldDefinition->getFieldDescription());
 
     $elements = array();
 
@@ -120,8 +119,8 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
       }
     }
 
-    $empty_single_allowed = ($this->field['cardinality'] == 1 && $delta == 0);
-    $empty_multiple_allowed = ($this->field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta < $this->field['cardinality']) && empty($form_state['programmed']);
+    $empty_single_allowed = ($cardinality == 1 && $delta == 0);
+    $empty_multiple_allowed = ($cardinality == FIELD_CARDINALITY_UNLIMITED || $delta < $cardinality) && empty($form_state['programmed']);
 
     // Add one more empty row for new uploads except when this is a programmed
     // multiple form as it is not necessary.
@@ -150,25 +149,39 @@ protected function formMultipleElements(EntityInterface $entity, array $items, $
       $elements['#description'] = $description;
       $elements['#field_name'] = $element['#field_name'];
       $elements['#language'] = $element['#language'];
-      $elements['#display_field'] = !empty($this->field['settings']['display_field']);
+      $elements['#display_field'] = (bool) $this->getFieldSetting('display_field');
 
       // Add some properties that will eventually be added to the file upload
       // field. These are added here so that they may be referenced easily
       // through a hook_form_alter().
       $elements['#file_upload_title'] = t('Add a new file');
-      $elements['#file_upload_description'] = theme('file_upload_help', array('description' => '', 'upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $this->field['cardinality']));
+      $elements['#file_upload_description'] = theme('file_upload_help', array('description' => '', 'upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $cardinality));
     }
 
     return $elements;
   }
 
   /**
-   * Implements \Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
+    $field_settings = $this->getFieldSettings();
+
+    // The field settings include defaults for the field type. However, this
+    // widget is a base class for other widgets (e.g., ImageWidget) that may act
+    // on field types without these expected settings.
+    // @todo Add support for merging settings of base types to implementations
+    //   of FieldDefinitionInterface::getFieldSettings().
+    $field_settings += array(
+      'display_default' => NULL,
+      'display_field' => NULL,
+      'description_field' => NULL,
+    );
+
+    $cardinality = $this->fieldDefinition->getFieldCardinality();
     $defaults = array(
       'fids' => array(),
-      'display' => !empty($this->field['settings']['display_default']),
+      'display' => (bool) $field_settings['display_default'],
       'description' => '',
     );
 
@@ -177,13 +190,19 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element_info = element_info('managed_file');
     $element += array(
       '#type' => 'managed_file',
-      '#upload_location' => file_field_widget_uri($this->field, $this->instance),
-      '#upload_validators' => file_field_widget_upload_validators($this->field, $this->instance),
+      '#upload_location' => file_field_widget_uri($field_settings),
+      '#upload_validators' => file_field_widget_upload_validators($field_settings),
       '#value_callback' => 'file_field_widget_value',
       '#process' => array_merge($element_info['#process'], array('file_field_widget_process')),
       '#progress_indicator' => $this->getSetting('progress_indicator'),
       // Allows this field to return an array instead of a single value.
       '#extended' => TRUE,
+      // Add properties needed by file_field_widget_value() and
+      // file_field_widget_process().
+      '#display_field' => (bool) $field_settings['display_field'],
+      '#display_default' => $field_settings['display_default'],
+      '#description_field' => $field_settings['description_field'],
+      '#cardinality' => $cardinality,
     );
 
     $element['#weight'] = $delta;
@@ -197,7 +216,6 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
 
     $default_fids = $element['#extended'] ? $element['#default_value']['fids'] : $element['#default_value'];
     if (empty($default_fids)) {
-      $cardinality = isset($this->field['cardinality']) ? $this->field['cardinality'] : 1;
       $element['#description'] = theme('file_upload_help', array('description' => $element['#description'], 'upload_validators' => $element['#upload_validators'], 'cardinality' => $cardinality));
       $element['#multiple'] = $cardinality != 1 ? TRUE : FALSE;
       if ($cardinality != 1 && $cardinality != -1) {
@@ -209,7 +227,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::massageFormValues().
+   * {@inheritdoc}
    */
   public function massageFormValues(array $values, array $form, array &$form_state) {
     // Since file upload widget now supports uploads of more than one file at a
diff --git a/core/modules/image/image.field.inc b/core/modules/image/image.field.inc
index 705bcf3..524005b 100644
--- a/core/modules/image/image.field.inc
+++ b/core/modules/image/image.field.inc
@@ -302,8 +302,8 @@ function image_field_delete_revision(EntityInterface $entity, $field, $instance,
 /**
  * Implements hook_field_is_empty().
  */
-function image_field_is_empty($item, $field) {
-  return file_field_is_empty($item, $field);
+function image_field_is_empty($item, $field_type) {
+  return file_field_is_empty($item, $field_type);
 }
 
 /**
@@ -360,10 +360,6 @@ function image_field_widget_process($element, &$form_state, $form) {
     );
   }
 
-  // Get field settings.
-  $instance = field_widget_instance($element, $form_state);
-  $settings = $instance['settings'];
-
   // Add the additional alt and title fields.
   $element['alt'] = array(
     '#title' => t('Alternate text'),
@@ -374,7 +370,7 @@ function image_field_widget_process($element, &$form_state, $form) {
     '#maxlength' => 512,
     '#weight' => -2,
     '#access' => (bool) $item['fids'] && $element['#alt_field'],
-    '#element_validate' => $settings['alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
+    '#element_validate' => $element['#alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
   );
   $element['title'] = array(
     '#type' => 'textfield',
@@ -384,7 +380,7 @@ function image_field_widget_process($element, &$form_state, $form) {
     '#maxlength' => 1024,
     '#weight' => -1,
     '#access' => (bool) $item['fids'] && $element['#title_field'],
-    '#element_validate' => $settings['alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
+    '#element_validate' => $element['#alt_field_required'] == 1 ? array('_image_field_required_fields_validate') : array(),
   );
 
   return $element;
diff --git a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
index 8062ff6..3ad6e0f 100644
--- a/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
+++ b/core/modules/image/lib/Drupal/image/Plugin/field/widget/ImageWidget.php
@@ -52,37 +52,38 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Overrides \Drupal\file\Plugin\field\widget\FileWidget::formMultipleElements().
+   * {@inheritdoc}
    *
    * Special handling for draggable multiple widgets and 'add more' button.
    */
   protected function formMultipleElements(EntityInterface $entity, array $items, $langcode, array &$form, array &$form_state) {
     $elements = parent::formMultipleElements($entity, $items, $langcode, $form, $form_state);
 
-    if ($this->field['cardinality'] == 1) {
+    $cardinality = $this->fieldDefinition->getFieldCardinality();
+    if ($cardinality == 1) {
       // If there's only one field, return it as delta 0.
       if (empty($elements[0]['#default_value']['fids'])) {
-        $elements[0]['#description'] = theme('file_upload_help', array('description' => $this->instance['description'], 'upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $this->field['cardinality']));
+        $elements[0]['#description'] = theme('file_upload_help', array('description' => $this->fieldDefinition->getFieldDescription(), 'upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $cardinality));
       }
     }
     else {
-      $elements['#file_upload_description'] = theme('file_upload_help', array('upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $this->field['cardinality']));
+      $elements['#file_upload_description'] = theme('file_upload_help', array('upload_validators' => $elements[0]['#upload_validators'], 'cardinality' => $cardinality));
     }
 
     return $elements;
   }
 
   /**
-   * Overrides \Drupal\file\Plugin\field\widget\FileWidget::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
-    $settings = $this->instance['settings'];
+    $field_settings = $this->getFieldSettings();
 
     // Add upload resolution validation.
-    if ($settings['max_resolution'] || $settings['min_resolution']) {
-      $element['#upload_validators']['file_validate_image_resolution'] = array($settings['max_resolution'], $settings['min_resolution']);
+    if ($field_settings['max_resolution'] || $field_settings['min_resolution']) {
+      $element['#upload_validators']['file_validate_image_resolution'] = array($field_settings['max_resolution'], $field_settings['min_resolution']);
     }
 
     // If not using custom extension validation, ensure this is an image.
@@ -95,8 +96,9 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element['#process'][] = 'image_field_widget_process';
     // Add properties needed by image_field_widget_process().
     $element['#preview_image_style'] = $this->getSetting('preview_image_style');
-    $element['#title_field'] = $settings['title_field'];
-    $element['#alt_field'] = $settings['alt_field'];
+    $element['#title_field'] = $field_settings['title_field'];
+    $element['#alt_field'] = $field_settings['alt_field'];
+    $element['#alt_field_required'] = $field_settings['alt_field_required'];
 
     return $element;
   }
diff --git a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
index 0784cae..f960613 100644
--- a/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
+++ b/core/modules/link/lib/Drupal/link/Plugin/field/widget/LinkWidget.php
@@ -33,8 +33,6 @@ class LinkWidget extends WidgetBase {
    * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-    $instance = $this->instance;
-
     $element['url'] = array(
       '#type' => 'url',
       '#title' => t('URL'),
@@ -49,13 +47,13 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       '#placeholder' => $this->getSetting('placeholder_title'),
       '#default_value' => isset($items[$delta]['title']) ? $items[$delta]['title'] : NULL,
       '#maxlength' => 255,
-      '#access' => $instance['settings']['title'] != DRUPAL_DISABLED,
+      '#access' => $this->getFieldSetting('title') != DRUPAL_DISABLED,
     );
     // Post-process the title field to make it conditionally required if URL is
     // non-empty. Omit the validation on the field edit form, since the field
     // settings cannot be saved otherwise.
     $is_field_edit_form = ($element['#entity'] === NULL);
-    if (!$is_field_edit_form && $instance['settings']['title'] == DRUPAL_REQUIRED) {
+    if (!$is_field_edit_form && $this->getFieldSetting('title') == DRUPAL_REQUIRED) {
       $element['#element_validate'] = array(array($this, 'validateTitle'));
     }
 
@@ -70,7 +68,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
 
     // If cardinality is 1, ensure a label is output for the field by wrapping it
     // in a details element.
-    if ($this->field['cardinality'] == 1) {
+    if ($this->fieldDefinition->getFieldCardinality() == 1) {
       $element += array(
         '#type' => 'fieldset',
       );
diff --git a/core/modules/link/link.module b/core/modules/link/link.module
index 16091f1..bfd6ebf 100644
--- a/core/modules/link/link.module
+++ b/core/modules/link/link.module
@@ -75,7 +75,7 @@ function link_field_load($entity_type, $entities, $field, $instances, $langcode,
 /**
  * Implements hook_field_is_empty().
  */
-function link_field_is_empty($item, $field) {
+function link_field_is_empty($item, $field_type) {
   return !isset($item['url']) || $item['url'] === '';
 }
 
diff --git a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
index 37c857f..0e2a65a 100644
--- a/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
+++ b/core/modules/number/lib/Drupal/number/Plugin/field/widget/NumberWidget.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\number\Plugin\field\widget\NumberWidget.
+ * Contains \Drupal\number\Plugin\field\widget\NumberWidget.
  */
 
 namespace Drupal\number\Plugin\field\widget;
@@ -31,7 +31,7 @@
 class NumberWidget extends WidgetBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['placeholder'] = array(
@@ -44,13 +44,11 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-    $field = $this->field;
-    $instance = $this->instance;
-
     $value = isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL;
+    $field_settings = $this->getFieldSettings();
 
     $element += array(
       '#type' => 'number',
@@ -59,9 +57,9 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     );
 
     // Set the step for floating point and decimal numbers.
-    switch ($field['type']) {
+    switch ($this->fieldDefinition->getFieldType()) {
       case 'number_decimal':
-        $element['#step'] = pow(0.1, $field['settings']['scale']);
+        $element['#step'] = pow(0.1, $field_settings['scale']);
         break;
 
       case 'number_float':
@@ -70,20 +68,20 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     }
 
     // Set minimum and maximum.
-    if (is_numeric($instance['settings']['min'])) {
-      $element['#min'] = $instance['settings']['min'];
+    if (is_numeric($field_settings['min'])) {
+      $element['#min'] = $field_settings['min'];
     }
-    if (is_numeric($instance['settings']['max'])) {
-      $element['#max'] = $instance['settings']['max'];
+    if (is_numeric($field_settings['max'])) {
+      $element['#max'] = $field_settings['max'];
     }
 
     // Add prefix and suffix.
-    if (!empty($instance['settings']['prefix'])) {
-      $prefixes = explode('|', $instance['settings']['prefix']);
+    if ($field_settings['prefix']) {
+      $prefixes = explode('|', $field_settings['prefix']);
       $element['#field_prefix'] = field_filter_xss(array_pop($prefixes));
     }
-    if (!empty($instance['settings']['suffix'])) {
-      $suffixes = explode('|', $instance['settings']['suffix']);
+    if ($field_settings('suffix')) {
+      $suffixes = explode('|', $field_settings['suffix']);
       $element['#field_suffix'] = field_filter_xss(array_pop($suffixes));
     }
 
@@ -91,7 +89,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::errorElement().
+   * {@inheritdoc}
    */
   public function errorElement(array $element, array $error, array $form, array &$form_state) {
     return $element['value'];
diff --git a/core/modules/number/number.module b/core/modules/number/number.module
index 4615519..7610639 100644
--- a/core/modules/number/number.module
+++ b/core/modules/number/number.module
@@ -164,7 +164,7 @@ function number_field_presave(EntityInterface $entity, $field, $instance, $langc
 /**
  * Implements hook_field_is_empty().
  */
-function number_field_is_empty($item, $field) {
+function number_field_is_empty($item, $field_type) {
   if (empty($item['value']) && (string) $item['value'] !== '0') {
     return TRUE;
   }
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
index 01b4efb..3b9c57c 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/formatter/OptionsDefaultFormatter.php
@@ -35,7 +35,7 @@ class OptionsDefaultFormatter extends FormatterBase {
   public function viewElements(EntityInterface $entity, $langcode, array $items) {
     $elements = array();
 
-    $allowed_values = options_allowed_values($this->field, $this->instance, $entity);
+    $allowed_values = options_allowed_values($this->fieldDefinition, $entity);
 
     foreach ($items as $delta => $item) {
       if (isset($allowed_values[$item['value']])) {
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
index 7e6b4a5..fd0d230 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OnOffWidget.php
@@ -57,7 +57,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
 
     // Override the title from the incoming $element.
     if ($this->getSetting('display_label')) {
-      $element['#title'] = $this->instance['label'];
+      $element['#title'] = $this->fieldDefinition->getFieldLabel();
     }
     else {
       $element['#title'] = isset($options[1]) ? $options[1] : '';
diff --git a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php
index 6986231..f6801c0 100644
--- a/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php
+++ b/core/modules/options/lib/Drupal/options/Plugin/field/widget/OptionsWidgetBase.php
@@ -7,7 +7,7 @@
 
 namespace Drupal\options\Plugin\field\widget;
 
-use Drupal\field\Plugin\Core\Entity\FieldInstance;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\field\Plugin\Type\Widget\WidgetBase;
 
 /**
@@ -36,12 +36,10 @@
   /**
    * {@inheritdoc}
    */
-  public function __construct($plugin_id, array $plugin_definition, FieldInstance $instance, array $settings) {
-    parent::__construct($plugin_id, $plugin_definition, $instance, $settings);
-
-    // Reset internal pointer since we're dealing with objects now.
-    reset($this->field['columns']);
-    $this->column = key($this->field['columns']);
+  public function __construct($plugin_id, array $plugin_definition, FieldDefinitionInterface $field_definition, array $settings) {
+    parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings);
+    $property_names = $this->fieldDefinition->getFieldPropertyNames();
+    $this->column = $property_names[0];
   }
 
   /**
@@ -52,7 +50,8 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     // element.
     $this->entity = $element['#entity'];
     $this->required = $element['#required'];
-    $this->multiple = ($this->field['cardinality'] == FIELD_CARDINALITY_UNLIMITED) || ($this->field['cardinality'] > 1);
+    $cardinality = $this->fieldDefinition->getFieldCardinality();
+    $this->multiple = ($cardinality == FIELD_CARDINALITY_UNLIMITED) || ($cardinality > 1);
     $this->has_value = isset($items[0][$this->column]);
 
     // Add our custom validator.
@@ -115,7 +114,9 @@ protected function getOptions() {
       $module_handler = \Drupal::moduleHandler();
 
       // Get the list of options from the field type module, and sanitize them.
-      $options = (array) $module_handler->invoke($this->field['module'], 'options_list', array($this->field, $this->instance, $this->entity));
+      $field_type_info = field_info_field_types($this->fieldDefinition->getFieldType());
+      $module = $field_type_info['module'];
+      $options = (array) $module_handler->invoke($module, 'options_list', array($this->fieldDefinition, $this->entity));
 
       // Add an empty option if the widget needs one.
       if ($empty_option = $this->getEmptyOption()) {
@@ -133,8 +134,7 @@ protected function getOptions() {
       }
 
       $context = array(
-        'field' => $this->field,
-        'instance' => $this->instance,
+        'fieldDefinition' => $this->fieldDefinition,
         'entity' => $this->entity,
       );
       $module_handler->alter('options_list', $options, $context);
diff --git a/core/modules/options/options.api.php b/core/modules/options/options.api.php
index a026898..5e8c694 100644
--- a/core/modules/options/options.api.php
+++ b/core/modules/options/options.api.php
@@ -13,12 +13,8 @@
  * implement this hook to specify the list of options to display in the
  * widgets.
  *
- * @param $field
+ * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
  *   The field definition.
- * @param $instance
- *   The instance definition. It is recommended to only use instance level
- *   properties to filter out values from a list defined by field level
- *   properties.
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity object the field is attached to.
  *
@@ -31,7 +27,7 @@
  *   widget. The HTML tags defined in _field_filter_xss_allowed_tags() are
  *   allowed, other tags will be filtered.
  */
-function hook_options_list($field, $instance, $entity) {
+function hook_options_list(\Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition, \Drupal\Core\Entity\EntityInterface $entity) {
   // Sample structure.
   $options = array(
     0 => t('Zero'),
@@ -57,7 +53,7 @@ function hook_options_list($field, $instance, $entity) {
   // In actual implementations, the array of options will most probably depend
   // on properties of the field. Example from taxonomy.module:
   $options = array();
-  foreach ($field['settings']['allowed_values'] as $tree) {
+  foreach ($field_definition->getFieldSetting('allowed_values') as $tree) {
     $terms = taxonomy_get_tree($tree['vid'], $tree['parent'], NULL, TRUE);
     if ($terms) {
       foreach ($terms as $term) {
@@ -81,10 +77,8 @@ function hook_options_list($field, $instance, $entity) {
  *
  * @param array $context
  *   An associative array containing:
- *   - field: The field definition (\Drupal\field\Plugin\Core\Entity\Field).
- *   - instance: The instance definition. It is recommended to only use instance
- *     level properties to filter out values from a list defined by field level
- *     properties (Drupal\field\Plugin\Core\Entity\FieldInstance).
+ *   - field_definition: The field definition
+ *     (\Drupal\Core\Entity\Field\FieldDefinitionInterface).
  *   - entity: The entity object the field is attached to
  *     (\Drupal\Core\Entity\EntityInterface).
  *
diff --git a/core/modules/options/options.module b/core/modules/options/options.module
index 0d8ec00..010e255 100644
--- a/core/modules/options/options.module
+++ b/core/modules/options/options.module
@@ -7,6 +7,7 @@
 
 use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\field\FieldUpdateForbiddenException;
 use Drupal\options\Plugin\field\widget\OptionsWidgetBase;
 
@@ -220,47 +221,53 @@ function options_field_update_field($field, $prior_field, $has_data) {
 }
 
 /**
+ * Implements hook_field_delete_field().
+ */
+function options_field_delete_field($field) {
+  drupal_static_reset('options_allowed_values');
+}
+
+/**
  * Returns the array of allowed values for a list field.
  *
  * The strings are not safe for output. Keys and values of the array should be
  * sanitized through field_filter_xss() before being displayed.
  *
- * @param $field
+ * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
  *   The field definition.
- * @param $instance
- *   (optional) A field instance array. Defaults to NULL.
  * @param \Drupal\Core\Entity\EntityInterface $entity
- *   (optional) The entity object. Defaults to NULL.
+ *   The entity object.
  *
  * @return
  *   The array of allowed values. Keys of the array are the raw stored values
  *   (number or text), values of the array are the display labels.
  */
-function options_allowed_values($field, $instance = NULL, EntityInterface $entity = NULL) {
+function options_allowed_values(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
   $allowed_values = &drupal_static(__FUNCTION__, array());
 
-  if (!isset($allowed_values[$field['uuid']])) {
-    $function = $field['settings']['allowed_values_function'];
+  $cache_id = implode(':', array($entity->entityType(), $entity->bundle(), $field_definition->getFieldName()));
+  if (!isset($allowed_values[$cache_id])) {
+    $function = $field_definition->getFieldSetting('allowed_values_function');
     // If $cacheable is FALSE, then the allowed values are not statically
     // cached. See options_test_dynamic_values_callback() for an example of
     // generating dynamic and uncached values.
     $cacheable = TRUE;
     if (!empty($function)) {
-      $values = $function($field, $instance, $entity, $cacheable);
+      $values = $function($field_definition, $entity, $cacheable);
     }
     else {
-      $values = $field['settings']['allowed_values'];
+      $values = $field_definition->getFieldSetting('allowed_values');
     }
 
     if ($cacheable) {
-      $allowed_values[$field['uuid']] = $values;
+      $allowed_values[$cache_id] = $values;
     }
     else {
       return $values;
     }
   }
 
-  return $allowed_values[$field['uuid']];
+  return $allowed_values[$cache_id];
 }
 
 /**
@@ -400,7 +407,16 @@ function _options_values_in_use($field, $values) {
  * - 'list_illegal_value': The value is not part of the list of allowed values.
  */
 function options_field_validate(EntityInterface $entity = NULL, $field, $instance, $langcode, $items, &$errors) {
-  $allowed_values = options_allowed_values($field, $instance, $entity);
+  // When configuring a field instance, the default value is validated without
+  // an entity, but options_allowed_values() and the callback it invokes
+  // require an entity, because the result can depend on entity type, bundle,
+  // and other entity data.
+  if (!isset($entity)) {
+    $ids = (object) array('entity_type' => $instance->entity_type, 'bundle' => $instance->bundle, 'entity_id' => NULL);
+    $entity = _field_create_entity_from_ids($ids);
+  }
+
+  $allowed_values = options_allowed_values($instance, $entity);
   foreach ($items as $delta => $item) {
     if (!empty($item['value'])) {
       if (!empty($allowed_values) && !isset($allowed_values[$item['value']])) {
@@ -416,7 +432,7 @@ function options_field_validate(EntityInterface $entity = NULL, $field, $instanc
 /**
  * Implements hook_field_is_empty().
  */
-function options_field_is_empty($item, $field) {
+function options_field_is_empty($item, $field_type) {
   if (empty($item['value']) && (string) $item['value'] !== '0') {
     return TRUE;
   }
@@ -426,7 +442,7 @@ function options_field_is_empty($item, $field) {
 /**
  * Implements hook_options_list().
  */
-function options_options_list($field, $instance, $entity) {
-  return options_allowed_values($field, $instance, $entity);
+function options_options_list(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
+  return options_allowed_values($field_definition, $entity);
 }
 
diff --git a/core/modules/options/tests/options_test.module b/core/modules/options/tests/options_test.module
index 4ece85c..9346cf0 100644
--- a/core/modules/options/tests/options_test.module
+++ b/core/modules/options/tests/options_test.module
@@ -6,11 +6,12 @@
  */
 
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 
 /**
  * Allowed values callback.
  */
-function options_test_allowed_values_callback($field, $instance, $entity) {
+function options_test_allowed_values_callback(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
   $values = array(
     'Group 1' => array(
       0 => 'Zero',
@@ -27,7 +28,7 @@ function options_test_allowed_values_callback($field, $instance, $entity) {
 /**
  * An entity-bound allowed values callback.
  */
-function options_test_dynamic_values_callback($field, $instance, EntityInterface $entity, &$cacheable) {
+function options_test_dynamic_values_callback(FieldDefinitionInterface $field_definition, EntityInterface $entity, &$cacheable) {
   $cacheable = FALSE;
   // We need the values of the entity as keys.
   $uri = $entity->uri();
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
index 01a01fa..c0ef1f6 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Plugin/field/widget/TaxonomyAutocompleteWidget.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\taxonomy\Plugin\field\widget\TaxonomyAutocompleteWidget.
+ * Contains \Drupal\taxonomy\Plugin\field\widget\TaxonomyAutocompleteWidget.
  */
 
 namespace Drupal\taxonomy\Plugin\field\widget;
@@ -32,7 +32,7 @@
 class TaxonomyAutocompleteWidget extends WidgetBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['placeholder'] = array(
@@ -45,11 +45,9 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
-    $field = $this->field;
-
     $tags = array();
     foreach ($items as $item) {
       $tags[$item['tid']] = isset($item['taxonomy_term']) ? $item['taxonomy_term'] : taxonomy_term_load($item['tid']);
@@ -57,7 +55,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
     $element += array(
       '#type' => 'textfield',
       '#default_value' => taxonomy_implode_tags($tags),
-      '#autocomplete_path' => $this->getSetting('autocomplete_path') . '/' . $field['field_name'],
+      '#autocomplete_path' => $this->getSetting('autocomplete_path') . '/' . $this->fieldDefinition->getFieldName(),
       '#size' => $this->getSetting('size'),
       '#placeholder' => $this->getSetting('placeholder'),
       '#maxlength' => 1024,
@@ -68,16 +66,15 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::massageFormValues()
+   * {@inheritdoc}
    */
   public function massageFormValues(array $values, array $form, array &$form_state) {
     // Autocomplete widgets do not send their tids in the form, so we must detect
     // them here and process them independently.
     $items = array();
-    $field = $this->field;
 
     // Collect candidate vocabularies.
-    foreach ($field['settings']['allowed_values'] as $tree) {
+    foreach ($this->getFieldSetting('allowed_values') as $tree) {
       if ($vocabulary = entity_load('taxonomy_vocabulary', $tree['vocabulary'])) {
         $vocabularies[$vocabulary->id()] = $vocabulary;
       }
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 6ed67a1..a38bbc9 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -9,6 +9,7 @@
 use Drupal\taxonomy\Plugin\Core\Entity\Term;
 use Drupal\taxonomy\Plugin\Core\Entity\Vocabulary;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 
 /**
  * Denotes that no term in the vocabulary has a parent.
@@ -904,6 +905,7 @@ function taxonomy_field_info() {
       'default_formatter' => 'taxonomy_term_reference_link',
       'field item class' => 'Drupal\taxonomy\Type\TaxonomyTermReferenceItem',
       'settings' => array(
+        'options_list_callback' => NULL,
         'allowed_values' => array(
           array(
             'vocabulary' => '',
@@ -926,9 +928,9 @@ function taxonomy_field_widget_info_alter(&$info) {
 /**
  * Implements hook_options_list().
  */
-function taxonomy_options_list($field, $instance, $entity) {
-  $function = !empty($field['settings']['options_list_callback']) ? $field['settings']['options_list_callback'] : 'taxonomy_allowed_values';
-  return $function($field, $instance, $entity);
+function taxonomy_options_list(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
+  $function = $field_definition->getFieldSetting('options_list_callback') ?: 'taxonomy_allowed_values';
+  return $function($field_definition, $entity);
 }
 
 /**
@@ -993,28 +995,24 @@ function taxonomy_field_validate(EntityInterface $entity = NULL, $field, $instan
 /**
  * Implements hook_field_is_empty().
  */
-function taxonomy_field_is_empty($item, $field) {
+function taxonomy_field_is_empty($item, $field_type) {
   return !is_array($item) || (empty($item['tid']) && empty($item['entity']));
 }
 
 /**
  * Returns the set of valid terms for a taxonomy field.
  *
- * @param $field
+ * @param \Drupal\Core\Entity\Field\FieldDefinitionInterface $field_definition
  *   The field definition.
- * @param $instance
- *   The instance definition. It is recommended to only use instance level
- *   properties to filter out values from a list defined by field level
- *   properties.
  * @param \Drupal\Core\Entity\EntityInterface $entity
  *   The entity object the field is attached to.
  *
  * @return
  *   The array of valid terms for this field, keyed by term id.
  */
-function taxonomy_allowed_values($field, $instance, EntityInterface $entity) {
+function taxonomy_allowed_values(FieldDefinitionInterface $field_definition, EntityInterface $entity) {
   $options = array();
-  foreach ($field['settings']['allowed_values'] as $tree) {
+  foreach ($field_definition->getFieldSetting('allowed_values') as $tree) {
     if ($vocabulary = taxonomy_vocabulary_load($tree['vocabulary'])) {
       if ($terms = taxonomy_get_tree($vocabulary->id(), $tree['parent'], NULL, TRUE)) {
         foreach ($terms as $term) {
diff --git a/core/modules/telephone/telephone.module b/core/modules/telephone/telephone.module
index 61a39f4..5033bbc 100644
--- a/core/modules/telephone/telephone.module
+++ b/core/modules/telephone/telephone.module
@@ -32,7 +32,7 @@ function telephone_field_info_alter(&$info) {
 /**
  * Implements hook_field_is_empty().
  */
-function telephone_field_is_empty($item, $field) {
+function telephone_field_is_empty($item, $field_type) {
   return !isset($item['value']) || $item['value'] === '';
 }
 
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php
index 4a96cc3..0d76811 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextDefaultFormatter.php
@@ -38,7 +38,7 @@ public function viewElements(EntityInterface $entity, $langcode, array $items) {
     $elements = array();
 
     foreach ($items as $delta => $item) {
-      $output = text_sanitize($this->instance['settings']['text_processing'], $langcode, $item, 'value');
+      $output = text_sanitize($this->getFieldSetting('text_processing'), $langcode, $item, 'value');
       $elements[$delta] = array('#markup' => $output);
     }
 
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php
index 4be366d..35a51e1 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/formatter/TextTrimmedFormatter.php
@@ -68,13 +68,14 @@ public function settingsSummary() {
   public function viewElements(EntityInterface $entity, $langcode, array $items) {
     $elements = array();
 
+    $text_processing = $this->getFieldSetting('text_processing');
     foreach ($items as $delta => $item) {
       if ($this->getPluginId() == 'text_summary_or_trimmed' && !empty($item['summary'])) {
-        $output = text_sanitize($this->instance['settings']['text_processing'], $langcode, $item, 'summary');
+        $output = text_sanitize($text_processing, $langcode, $item, 'summary');
       }
       else {
-        $output = text_sanitize($this->instance['settings']['text_processing'], $langcode, $item, 'value');
-        $output = text_summary($output, $this->instance['settings']['text_processing'] ? $item['format'] : NULL, $this->getSetting('trim_length'));
+        $output = text_sanitize($text_processing, $langcode, $item, 'value');
+        $output = text_summary($output, $text_processing ? $item['format'] : NULL, $this->getSetting('trim_length'));
       }
       $elements[$delta] = array('#markup' => $output);
     }
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
index 496ea12..2fe37a0 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWidget.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\text\Plugin\field\widget\TextareaWidget.
+ * Contains \Drupal\text\Plugin\field\widget\TextareaWidget.
  */
 
 namespace Drupal\text\Plugin\field\widget;
@@ -30,7 +30,7 @@
 class TextareaWidget extends WidgetBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['rows'] = array(
@@ -50,7 +50,7 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $main_widget = $element + array(
@@ -61,7 +61,7 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       '#attributes' => array('class' => array('text-full')),
     );
 
-    if ($this->instance['settings']['text_processing']) {
+    if ($this->getFieldSetting('text_processing')) {
       $element = $main_widget;
       $element['#type'] = 'text_format';
       $element['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
index b3a68ac..b98ce32 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextareaWithSummaryWidget.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\text\Plugin\field\widget\TextareaWithSummaryWidget.
+ * Contains \Drupal\text\Plugin\field\widget\TextareaWithSummaryWidget.
  */
 
 namespace Drupal\text\Plugin\field\widget;
@@ -30,12 +30,12 @@
 class TextareaWithSummaryWidget extends TextareaWidget {
 
   /**
-   * Overrides TextareaWidget::formElement().
+   * {@inheritdoc}
    */
   function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $element = parent::formElement($items, $delta, $element, $langcode, $form, $form_state);
 
-    $display_summary = !empty($items[$delta]['summary']) || $this->instance['settings']['display_summary'];
+    $display_summary = !empty($items[$delta]['summary']) || $this->getFieldSetting('display_summary');
     $element['summary'] = array(
       '#type' => $display_summary ? 'textarea' : 'value',
       '#default_value' => isset($items[$delta]['summary']) ? $items[$delta]['summary'] : NULL,
@@ -55,7 +55,7 @@ function formElement(array $items, $delta, array $element, $langcode, array &$fo
   }
 
   /**
-   * Overrides TextareaWidget::errorElement().
+   * {@inheritdoc}
    */
   public function errorElement(array $element, array $error, array $form, array &$form_state) {
     switch ($error['error']) {
diff --git a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
index a6e26b7..7012c75 100644
--- a/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
+++ b/core/modules/text/lib/Drupal/text/Plugin/field/widget/TextfieldWidget.php
@@ -2,7 +2,7 @@
 
 /**
  * @file
- * Definition of Drupal\text\Plugin\field\widget\TextfieldWidget.
+ * Contains \Drupal\text\Plugin\field\widget\TextfieldWidget.
  */
 
 namespace Drupal\text\Plugin\field\widget;
@@ -30,7 +30,7 @@
 class TextfieldWidget extends WidgetBase {
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::settingsForm().
+   * {@inheritdoc}
    */
   public function settingsForm(array $form, array &$form_state) {
     $element['size'] = array(
@@ -50,7 +50,7 @@ public function settingsForm(array $form, array &$form_state) {
   }
 
   /**
-   * Implements Drupal\field\Plugin\Type\Widget\WidgetInterface::formElement().
+   * {@inheritdoc}
    */
   public function formElement(array $items, $delta, array $element, $langcode, array &$form, array &$form_state) {
     $main_widget = $element + array(
@@ -58,11 +58,11 @@ public function formElement(array $items, $delta, array $element, $langcode, arr
       '#default_value' => isset($items[$delta]['value']) ? $items[$delta]['value'] : NULL,
       '#size' => $this->getSetting('size'),
       '#placeholder' => $this->getSetting('placeholder'),
-      '#maxlength' => $this->field['settings']['max_length'],
+      '#maxlength' => $this->getFieldSetting('max_length'),
       '#attributes' => array('class' => array('text-full')),
     );
 
-    if ($this->instance['settings']['text_processing']) {
+    if ($this->getFieldSetting('text_processing')) {
       $element = $main_widget;
       $element['#type'] = 'text_format';
       $element['#format'] = isset($items[$delta]['format']) ? $items[$delta]['format'] : NULL;
diff --git a/core/modules/text/text.module b/core/modules/text/text.module
index 4fe2115..3869458 100644
--- a/core/modules/text/text.module
+++ b/core/modules/text/text.module
@@ -191,7 +191,7 @@ function text_field_load($entity_type, $entities, $field, $instances, $langcode,
 /**
  * Implements hook_field_is_empty().
  */
-function text_field_is_empty($item, $field) {
+function text_field_is_empty($item, $field_type) {
   if (!isset($item['value']) || $item['value'] === '') {
     return !isset($item['summary']) || $item['summary'] === '';
   }
diff --git a/core/modules/translation_entity/translation_entity.admin.inc b/core/modules/translation_entity/translation_entity.admin.inc
index dd7874c..6a4c0da 100644
--- a/core/modules/translation_entity/translation_entity.admin.inc
+++ b/core/modules/translation_entity/translation_entity.admin.inc
@@ -593,7 +593,7 @@ function _translation_entity_update_field($entity_type, EntityInterface $entity,
 
   // Ensure that we are trying to store only valid data.
   foreach ($entity->{$field_name} as $langcode => $items) {
-    $entity->{$field_name}[$langcode] = _field_filter_items($field, $entity->{$field_name}[$langcode]);
+    $entity->{$field_name}[$langcode] = _field_filter_items($field['type'], $entity->{$field_name}[$langcode]);
     $empty += empty($entity->{$field_name}[$langcode]);
   }
 
diff --git a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
index f872f7d..575c000 100644
--- a/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
+++ b/core/modules/views/lib/Drupal/views/Plugin/entity_reference/selection/ViewsSelection.php
@@ -11,6 +11,7 @@
 use Drupal\Core\Annotation\Translation;
 use Drupal\Core\Database\Query\SelectInterface;
 use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Entity\Field\FieldDefinitionInterface;
 use Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface;
 
 /**
@@ -27,6 +28,20 @@
 class ViewsSelection implements SelectionInterface {
 
   /**
+   * The field definition.
+   *
+   * @var \Drupal\Core\Entity\Field\FieldDefinitionInterface
+   */
+  protected $fieldDefinition;
+
+  /**
+   * The entity object, or NULL
+   *
+   * @var NULL|EntityInterface
+   */
+  protected $entity;
+
+  /**
    * The loaded View object.
    *
    * @var \Drupal\views\ViewExecutable;
@@ -36,9 +51,8 @@ class ViewsSelection implements SelectionInterface {
   /**
    * Constructs a View selection handler.
    */
-  public function __construct($field, $instance = NULL, EntityInterface $entity = NULL) {
-    $this->field = $field;
-    $this->instance = $instance;
+  public function __construct(FieldDefinitionInterface $field_definition, EntityInterface $entity = NULL) {
+    $this->fieldDefinition = $field_definition;
     $this->entity = $entity;
   }
 
@@ -117,13 +131,14 @@ public static function settingsForm(&$field, &$instance) {
    *   Return TRUE if the view was initialized, FALSE otherwise.
    */
   protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $limit = 0, $ids = NULL) {
-    $view_name = $this->instance['settings']['handler_settings']['view']['view_name'];
-    $display_name = $this->instance['settings']['handler_settings']['view']['display_name'];
+    $handler_settings = $this->fieldDefinition->getFieldSetting('handler_settings');
+    $view_name = $handler_settings['view']['view_name'];
+    $display_name = $handler_settings['view']['display_name'];
 
     // Check that the view is valid and the display still exists.
     $this->view = views_get_view($view_name);
     if (!$this->view || !$this->view->access($display_name)) {
-      drupal_set_message(t('The reference view %view_name used in the %field_name field cannot be found.', array('%view_name' => $view_name, '%field_name' => $this->instance['label'])), 'warning');
+      drupal_set_message(t('The reference view %view_name used in the %field_name field cannot be found.', array('%view_name' => $view_name, '%field_name' => $this->fieldDefinition->getFieldLabel())), 'warning');
       return FALSE;
     }
     $this->view->setDisplay($display_name);
@@ -143,8 +158,9 @@ protected function initializeView($match = NULL, $match_operator = 'CONTAINS', $
    * Implements \Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::getReferencableEntities().
    */
   public function getReferencableEntities($match = NULL, $match_operator = 'CONTAINS', $limit = 0) {
-    $display_name = $this->instance['settings']['handler_settings']['view']['display_name'];
-    $arguments = $this->instance['settings']['handler_settings']['view']['arguments'];
+    $handler_settings = $this->fieldDefinition->getFieldSetting('handler_settings');
+    $display_name = $handler_settings['view']['display_name'];
+    $arguments = $handler_settings['view']['arguments'];
     $result = array();
     if ($this->initializeView($match, $match_operator, $limit)) {
       // Get the results.
@@ -173,8 +189,9 @@ public function countReferencableEntities($match = NULL, $match_operator = 'CONT
    * Implements \Drupal\entity_reference\Plugin\Type\Selection\SelectionInterface::validateReferencableEntities().
    */
   public function validateReferencableEntities(array $ids) {
-    $display_name = $this->instance['settings']['handler_settings']['view']['display_name'];
-    $arguments = $this->instance['settings']['handler_settings']['view']['arguments'];
+    $handler_settings = $this->fieldDefinition->getFieldSetting('handler_settings');
+    $display_name = $handler_settings['view']['display_name'];
+    $arguments = $handler_settings['view']['arguments'];
     $result = array();
     if ($this->initializeView(NULL, 'CONTAINS', 0, $ids)) {
       // Get the results.
